diff --git a/frontend/apps/remark42/app/components/comment-form/comment-form.css b/frontend/apps/remark42/app/components/comment-form/comment-form.css index 6344de8884..cf66566116 100644 --- a/frontend/apps/remark42/app/components/comment-form/comment-form.css +++ b/frontend/apps/remark42/app/components/comment-form/comment-form.css @@ -109,16 +109,6 @@ } } -.comment-form__markdown { - margin-bottom: 5px; - font-size: 12px; -} - -.comment-form__markdown-link { - font-weight: 700; - white-space: nowrap; -} - .comment-form__preview { margin-top: 8px; padding: 7px 11px; @@ -137,23 +127,6 @@ background: var(--color5); } -.comment-form__rss { - font-size: 12px; - line-height: 1; -} - -.comment-form__rss-link { - font-weight: 700; - white-space: nowrap; - text-decoration: none; - cursor: pointer; - color: var(--color9); - - &:hover { - color: var(--color33); - } -} - .comment-form__dropdown_rss { text-align: left; diff --git a/frontend/apps/remark42/app/components/comment-form/comment-form.module.css b/frontend/apps/remark42/app/components/comment-form/comment-form.module.css new file mode 100644 index 0000000000..0b97bdd948 --- /dev/null +++ b/frontend/apps/remark42/app/components/comment-form/comment-form.module.css @@ -0,0 +1,20 @@ +.subscriptions { + font-size: 12px; + line-height: 1.5; +} + +.subscriptions > div > div { + margin: 0 0.25em; +} + +.link { + font-weight: 700; + white-space: nowrap; + text-decoration: none; + cursor: pointer; + color: var(--color9); + + &:hover { + color: var(--color33); + } +} diff --git a/frontend/apps/remark42/app/components/comment-form/comment-form.tsx b/frontend/apps/remark42/app/components/comment-form/comment-form.tsx index d5ed7a75ca..99e7b33dc2 100644 --- a/frontend/apps/remark42/app/components/comment-form/comment-form.tsx +++ b/frontend/apps/remark42/app/components/comment-form/comment-form.tsx @@ -1,6 +1,7 @@ import { h, Component, createRef, Fragment } from 'preact'; import { FormattedMessage, IntlShape, defineMessages, useIntl } from 'react-intl'; import b, { Mix } from 'bem-react-helper'; +import clsx from 'clsx'; import { User, Image, Theme } from 'common/types'; import { StaticStore } from 'common/static-store'; @@ -9,6 +10,7 @@ import { extractErrorMessageFromResponse } from 'utils/errorUtils'; import { isUserAnonymous } from 'utils/isUserAnonymous'; import { sleep } from 'utils/sleep'; import { replaceSelection } from 'utils/replaceSelection'; +import { useTheme } from 'hooks/useTheme'; import { Button } from 'components/button'; import { TextareaAutosize } from 'components/textarea-autosize'; import { Auth } from 'components/auth'; @@ -23,7 +25,7 @@ import { updatePersistedComments, getPersistedComment, removePersistedComment } import 'components/raw-content'; import './comment-form.css'; -import { useTheme } from 'hooks/useTheme'; +import styles from './comment-form.module.css'; type State = { preview: string | null; @@ -344,19 +346,17 @@ class CommentFormComponent extends Component<CommentFormComponentProps, State> { }; renderMarkdownTip = () => ( - <div className="comment-form__markdown"> - <FormattedMessage - id="commentForm.notice-about-styling" - defaultMessage="Styling with <a>Markdown</a> is supported" - values={{ - a: (title: string) => ( - <a class="comment-form__markdown-link" target="_blank" href="markdown-help.html"> - {title} - </a> - ), - }} - /> - </div> + <FormattedMessage + id="commentForm.notice-about-styling" + defaultMessage="Styling with <a>Markdown</a> is supported" + values={{ + a: (title: string) => ( + <a target="_blank" href="markdown-help.html" className={styles.link}> + {title} + </a> + ), + }} + /> ); renderSubscribeButtons = () => { @@ -366,29 +366,36 @@ class CommentFormComponent extends Component<CommentFormComponentProps, State> { const isTelegramSubscription = isTelegramNotificationsEnabledOnBackend && settings.isTelegramSubscription; const { isRssSubscription } = settings; - if (!isRssSubscription && !isEmailSubscription && !isTelegramSubscription) { + const subscriptions: JSX.Element[] = []; + + if (isRssSubscription) { + subscriptions.push(<SubscribeByRSS userId={this.props.user?.id} />); + } + + if (isEmailSubscription) { + subscriptions.push(<SubscribeByEmail />); + } + + if (isTelegramSubscription) { + subscriptions.push(<SubscribeByTelegram />); + } + + if (subscriptions.length === 0) { return null; } return ( - <> - <FormattedMessage id="commentForm.subscribe-by" defaultMessage="Subscribe by" />{' '} - {isRssSubscription && <SubscribeByRSS userId={this.props.user?.id ?? null} />} - {isRssSubscription && isEmailSubscription && ( - <> - {' '} - <FormattedMessage id="commentForm.subscribe-or" defaultMessage="or" />{' '} - </> - )} - {isEmailSubscription && <SubscribeByEmail />} - {(isRssSubscription && isTelegramSubscription) || (isEmailSubscription && isTelegramSubscription) ? ( - <> - {' '} - <FormattedMessage id="commentForm.subscribe-or" defaultMessage="or" />{' '} - </> - ) : null} - {isTelegramSubscription && <SubscribeByTelegram />} - </> + <div> + <FormattedMessage id="commentForm.subscribe-by" defaultMessage="Subscribe by" /> + {subscriptions.map((c, i, all) => { + return ( + <Fragment key={i}> + {c} + {i + 1 < all.length && <FormattedMessage id="commentForm.or" defaultMessage="or" />} + </Fragment> + ); + })} + </div> ); }; @@ -482,8 +489,8 @@ class CommentFormComponent extends Component<CommentFormComponentProps, State> { </div> {mode === 'main' && ( - <div className="comment-form__rss"> - {this.renderMarkdownTip()} + <div className={clsx('comment-form-subscriptions', styles.subscriptions)}> + <div>{this.renderMarkdownTip()}</div> {this.renderSubscribeButtons()} </div> )} @@ -491,7 +498,7 @@ class CommentFormComponent extends Component<CommentFormComponentProps, State> { ) : ( <> <Auth /> - {this.renderMarkdownTip()} + <div className={clsx('comment-form-subscriptions', styles.subscriptions)}>{this.renderMarkdownTip()}</div> </> )} </div> diff --git a/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-email/subscribe-by-email.module.css b/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-email/subscribe-by-email.module.css index f53f80fb63..583d90e8f7 100644 --- a/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-email/subscribe-by-email.module.css +++ b/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-email/subscribe-by-email.module.css @@ -3,14 +3,38 @@ flex-wrap: wrap; flex-direction: column; padding: 8px; - width: 200px; + width: 240px; box-sizing: border-box; line-height: 1.2; text-align: left; + font-size: 14px; +} + +.root > * + * { + margin-top: 12px; +} + +.tokenInput { + composes: input from 'components/input/input.module.css'; + box-sizing: border-box; + width: 100%; + min-height: 60px; + max-height: 200px; + margin: 0; + padding: 4px 8px; + resize: vertical; + font-size: 16px; + font-family: inherit; +} + +.backButton { + width: auto; } -.rootToken { - padding-top: 0; +.backButtonArrow { + display: inline-block; + margin-left: -4px; + margin-right: 2px; } .rootSubscribed, @@ -20,37 +44,11 @@ font-size: 14px; } -.title { - margin-bottom: 12px; -} - -.button { - margin-top: 10px; - flex-grow: 1; -} - .preloader { margin: 0 auto; } -.tokenInput { - resize: vertical; - border: 1px solid var(--color31); - padding: 4px; - font-family: inherit; - font-size: 0.8em; - font-weight: normal; - line-height: 1.5; - - &:focus { - box-shadow: 0 0 0 2px var(--color47); - border-color: var(--color15); - outline: none; - } -} - .error { - margin-top: 8px; padding: 6px 8px; line-height: 1.2; background: var(--color26); diff --git a/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-email/subscribe-by-email.tsx b/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-email/subscribe-by-email.tsx index 572d53b658..727695d94e 100644 --- a/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-email/subscribe-by-email.tsx +++ b/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-email/subscribe-by-email.tsx @@ -1,8 +1,7 @@ import { h, FunctionComponent, Fragment } from 'preact'; import { useState, useCallback, useRef } from 'preact/hooks'; import { useSelector, useDispatch } from 'react-redux'; -import b from 'bem-react-helper'; -import { useIntl, defineMessages, IntlShape, FormattedMessage } from 'react-intl'; +import { useIntl, FormattedMessage, defineMessages } from 'react-intl'; import clsx from 'clsx'; import { User } from 'common/types'; @@ -10,17 +9,16 @@ import { StoreState } from 'store'; import { setUserSubscribed } from 'store/user/actions'; import { sleep } from 'utils/sleep'; import { extractErrorMessageFromResponse, RequestError } from 'utils/errorUtils'; -import { getHandleClickProps } from 'common/accessibility'; import { emailVerificationForSubscribe, emailConfirmationForSubscribe, unsubscribeFromEmailUpdates } from 'common/api'; +import { useTheme } from 'hooks/useTheme'; import { Input } from 'components/input'; -import { Button } from 'components/button'; +import { Button } from 'components/auth/components/button'; import { Dropdown } from 'components/dropdown'; import { Preloader } from 'components/preloader'; import { TextareaAutosize } from 'components/textarea-autosize'; import { getPersistedEmail } from 'components/auth/auth.utils'; import { isUserAnonymous } from 'utils/isUserAnonymous'; import { isJwtExpired } from 'utils/jwt'; -import { useTheme } from 'hooks/useTheme'; import styles from './subscribe-by-email.module.css'; @@ -42,7 +40,7 @@ export const SubscribeByEmailForm: FunctionComponent = () => { ); const justSubscribed = useRef<Boolean>(false); - const [step, setStep] = useState(subscribed ? Step.Subscribed : Step.Email); + const [step, setStep] = useState(Step.Token); const [token, setToken] = useState(''); const [emailAddress, setEmailAddress] = useState(getPersistedEmail); @@ -167,8 +165,8 @@ export const SubscribeByEmailForm: FunctionComponent = () => { return ( <div className={clsx(styles.root, styles.rootSubscribed)}> - {text} - <Button kind="primary" size="middle" className={styles.button} onClick={handleUnsubscribe}> + <div>{text}</div> + <Button className={styles.button} onClick={handleUnsubscribe}> <FormattedMessage id="subscribeByEmail.unsubscribe" defaultMessage="Unsubscribe" /> </Button> </div> @@ -184,11 +182,13 @@ export const SubscribeByEmailForm: FunctionComponent = () => { return ( <div className={clsx(styles.root, styles.rootUnsubscribed)}> - <FormattedMessage - id="subscribeByEmail.have-been-unsubscribed" - defaultMessage="You have been unsubscribed by email to updates" - /> - <Button kind="primary" size="middle" className={styles.button} onClick={() => setStep(Step.Close)}> + <div> + <FormattedMessage + id="subscribeByEmail.have-been-unsubscribed" + defaultMessage="You have been unsubscribed by email to updates" + /> + </div> + <Button className={styles.button} onClick={() => setStep(Step.Close)}> <FormattedMessage id="subscribeByEmail.close" defaultMessage="Close" /> </Button> </div> @@ -217,16 +217,37 @@ export const SubscribeByEmailForm: FunctionComponent = () => { )} {step === Step.Token && ( <> - <Button kind="link" {...getHandleClickProps(setEmailStep)}> - <FormattedMessage id="subscribeByEmail.back" defaultMessage="Back" /> - </Button> - <TextareaAutosize - placeholder={intl.formatMessage(messages.token)} - autofocus - onInput={handleChangeToken} - disabled={loading} - value={token} - /> + <div> + <Button className={styles.backButton} size="xs" kind="transparent" onClick={setEmailStep}> + <svg + className={styles.backButtonArrow} + width="14" + height="14" + viewBox="0 0 14 14" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M8.75 3L5 7.25L9 11" + stroke="currentColor" + stroke-width="2" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> + {intl.formatMessage(messages.back)} + </Button> + </div> + <div> + <TextareaAutosize + className={styles.tokenInput} + placeholder={intl.formatMessage(messages.token)} + autofocus + onInput={handleChangeToken} + disabled={loading} + value={token} + /> + </div> </> )} {error !== null && ( @@ -234,13 +255,7 @@ export const SubscribeByEmailForm: FunctionComponent = () => { {error} </div> )} - <Button - className={styles.button} - kind="primary" - size="large" - type="submit" - disabled={!isValidEmailAddress || loading} - > + <Button type="submit" disabled={!isValidEmailAddress || loading}> {loading ? <Preloader className={styles.preloader} /> : buttonLabel} </Button> </form> @@ -255,7 +270,7 @@ export const SubscribeByEmail: FunctionComponent = () => { const buttonTitle = intl.formatMessage(isAnonymous ? messages.onlyRegisteredUsers : messages.subscribeByEmail); return ( - <Dropdown theme={theme} title={intl.formatMessage(messages.email)} disabled={isAnonymous} buttonTitle={buttonTitle}> + <Dropdown theme={theme} title={intl.formatMessage(messages.email)} buttonTitle={buttonTitle}> <SubscribeByEmailForm /> </Dropdown> ); @@ -298,4 +313,8 @@ const messages = defineMessages({ id: 'subscribeByEmail.email', defaultMessage: 'Email', }, + back: { + id: 'subscribeByEmail.back', + defaultMessage: 'Back', + }, }); diff --git a/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-rss/subscribe-by-rss.tsx b/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-rss/subscribe-by-rss.tsx index 639ea86a8d..ab03ccd278 100644 --- a/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-rss/subscribe-by-rss.tsx +++ b/frontend/apps/remark42/app/components/comment-form/components/subscribe-by-rss/subscribe-by-rss.tsx @@ -9,7 +9,7 @@ import { Dropdown, DropdownItem } from 'components/dropdown'; import styles from './subscribe-by-rss.module.css'; import { useTheme } from 'hooks/useTheme'; -export const SubscribeByRSS: FunctionComponent<{ userId: string | null }> = ({ userId }) => { +export const SubscribeByRSS: FunctionComponent<{ userId: string | undefined }> = ({ userId }) => { const intl = useIntl(); const theme = useTheme(); const items: Array<[string, string]> = useMemo(