From 9dcce43360167147846161ba1e340d24b80f05aa Mon Sep 17 00:00:00 2001 From: forehalo Date: Wed, 12 Feb 2025 07:39:09 +0000 Subject: [PATCH] refactor(core): auth ui (#10101) close AF-2202 AF-2203 --- .../auth-components/auth-container.tsx | 7 + .../auth-components/auth-footer.tsx | 7 + .../{modal-header.tsx => auth-header.tsx} | 8 +- .../components/auth-components/auth-input.tsx | 14 +- .../auth-components/back-button.tsx | 7 +- .../src/components/auth-components/index.tsx | 4 +- .../components/auth-components/share.css.ts | 150 +++++------------- packages/frontend/component/src/type.d.ts | 5 + .../core/src/components/affine/auth/oauth.tsx | 2 +- .../src/components/sign-in/add-selfhosted.tsx | 16 +- .../core/src/components/sign-in/back.tsx | 18 +++ .../background-arts/art-dark.inline.svg | 86 ++++++++++ .../background-arts/art-light.inline.svg | 86 ++++++++++ .../sign-in/background-arts/index.tsx | 18 +++ .../sign-in/background-arts/style.css.ts | 14 ++ .../core/src/components/sign-in/index.tsx | 1 + .../components/sign-in/sign-in-with-email.tsx | 119 +++++++------- .../sign-in/sign-in-with-password.tsx | 32 ++-- .../core/src/components/sign-in/sign-in.tsx | 63 +++++--- .../core/src/components/sign-in/style.css.ts | 17 +- .../desktop/dialogs/change-password/index.tsx | 60 +++---- .../src/desktop/dialogs/sign-in/index.tsx | 2 +- .../desktop/dialogs/verify-email/index.tsx | 20 +-- .../core/src/desktop/pages/auth/sign-in.tsx | 6 +- 24 files changed, 458 insertions(+), 304 deletions(-) create mode 100644 packages/frontend/component/src/components/auth-components/auth-container.tsx create mode 100644 packages/frontend/component/src/components/auth-components/auth-footer.tsx rename packages/frontend/component/src/components/auth-components/{modal-header.tsx => auth-header.tsx} (56%) create mode 100644 packages/frontend/core/src/components/sign-in/back.tsx create mode 100644 packages/frontend/core/src/components/sign-in/background-arts/art-dark.inline.svg create mode 100644 packages/frontend/core/src/components/sign-in/background-arts/art-light.inline.svg create mode 100644 packages/frontend/core/src/components/sign-in/background-arts/index.tsx create mode 100644 packages/frontend/core/src/components/sign-in/background-arts/style.css.ts diff --git a/packages/frontend/component/src/components/auth-components/auth-container.tsx b/packages/frontend/component/src/components/auth-components/auth-container.tsx new file mode 100644 index 0000000000..a6482ad764 --- /dev/null +++ b/packages/frontend/component/src/components/auth-components/auth-container.tsx @@ -0,0 +1,7 @@ +import type { PropsWithChildren } from 'react'; + +import { authContainer } from './share.css'; + +export function AuthContainer(props: PropsWithChildren) { + return
{props.children}
; +} diff --git a/packages/frontend/component/src/components/auth-components/auth-footer.tsx b/packages/frontend/component/src/components/auth-components/auth-footer.tsx new file mode 100644 index 0000000000..cae848883f --- /dev/null +++ b/packages/frontend/component/src/components/auth-components/auth-footer.tsx @@ -0,0 +1,7 @@ +import type { PropsWithChildren } from 'react'; + +import { authFooter } from './share.css'; + +export function AuthFooter(props: PropsWithChildren) { + return
{props.children}
; +} diff --git a/packages/frontend/component/src/components/auth-components/modal-header.tsx b/packages/frontend/component/src/components/auth-components/auth-header.tsx similarity index 56% rename from packages/frontend/component/src/components/auth-components/modal-header.tsx rename to packages/frontend/component/src/components/auth-components/auth-header.tsx index a69bec50c6..c012cdc10b 100644 --- a/packages/frontend/component/src/components/auth-components/modal-header.tsx +++ b/packages/frontend/component/src/components/auth-components/auth-header.tsx @@ -1,15 +1,15 @@ import { Logo1Icon } from '@blocksuite/icons/rc'; import type { FC } from 'react'; -import { modalHeaderWrapper } from './share.css'; -export const ModalHeader: FC<{ +import { authHeaderWrapper } from './share.css'; +export const AuthHeader: FC<{ title: string; subTitle?: string; }> = ({ title, subTitle }) => { return ( -
+

- {title === 'AFFiNE Cloud' && } + {title}

{subTitle}

diff --git a/packages/frontend/component/src/components/auth-components/auth-input.tsx b/packages/frontend/component/src/components/auth-components/auth-input.tsx index 7e2ae52d8e..053601a226 100644 --- a/packages/frontend/component/src/components/auth-components/auth-input.tsx +++ b/packages/frontend/component/src/components/auth-components/auth-input.tsx @@ -8,14 +8,12 @@ export type AuthInputProps = InputProps & { label?: string; error?: boolean; errorHint?: ReactNode; - withoutHint?: boolean; onEnter?: () => void; }; export const AuthInput = ({ label, error, errorHint, - withoutHint = false, onEnter, className, ...inputProps @@ -23,7 +21,7 @@ export const AuthInput = ({ return (
{label ? : null} @@ -34,14 +32,8 @@ export const AuthInput = ({ onEnter={onEnter} {...inputProps} /> - {error && errorHint && !withoutHint ? ( -
- {errorHint} -
+ {error && errorHint ? ( +
{errorHint}
) : null}
); diff --git a/packages/frontend/component/src/components/auth-components/back-button.tsx b/packages/frontend/component/src/components/auth-components/back-button.tsx index fa886dd8cb..555fde0743 100644 --- a/packages/frontend/component/src/components/auth-components/back-button.tsx +++ b/packages/frontend/component/src/components/auth-components/back-button.tsx @@ -1,6 +1,5 @@ import { useI18n } from '@affine/i18n'; import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc'; -import { cssVar } from '@toeverything/theme'; import type { FC } from 'react'; import type { ButtonProps } from '../../ui/button'; @@ -12,11 +11,7 @@ export const BackButton: FC = props => { + +
- - + +
+ ); }; diff --git a/packages/frontend/core/src/components/sign-in/back.tsx b/packages/frontend/core/src/components/sign-in/back.tsx new file mode 100644 index 0000000000..6b3b5999f4 --- /dev/null +++ b/packages/frontend/core/src/components/sign-in/back.tsx @@ -0,0 +1,18 @@ +import { BackButton } from '@affine/component/auth-components'; +import { type Dispatch, type SetStateAction, useCallback } from 'react'; + +import type { SignInState } from '.'; + +interface BackButtonProps { + changeState: Dispatch>; +} +export function Back({ changeState }: BackButtonProps) { + const onClick = useCallback(() => { + changeState(prev => ({ + ...prev, + step: 'signIn', + })); + }, [changeState]); + + return ; +} diff --git a/packages/frontend/core/src/components/sign-in/background-arts/art-dark.inline.svg b/packages/frontend/core/src/components/sign-in/background-arts/art-dark.inline.svg new file mode 100644 index 0000000000..e058e4c57f --- /dev/null +++ b/packages/frontend/core/src/components/sign-in/background-arts/art-dark.inline.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/core/src/components/sign-in/background-arts/art-light.inline.svg b/packages/frontend/core/src/components/sign-in/background-arts/art-light.inline.svg new file mode 100644 index 0000000000..5a5cca7c13 --- /dev/null +++ b/packages/frontend/core/src/components/sign-in/background-arts/art-light.inline.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/core/src/components/sign-in/background-arts/index.tsx b/packages/frontend/core/src/components/sign-in/background-arts/index.tsx new file mode 100644 index 0000000000..f665c1727d --- /dev/null +++ b/packages/frontend/core/src/components/sign-in/background-arts/index.tsx @@ -0,0 +1,18 @@ +import { useTheme } from 'next-themes'; + +import darkArt from './art-dark.inline.svg'; +import lightArt from './art-light.inline.svg'; +import { arts, wrapper } from './style.css'; + +export function SignInBackgroundArts() { + const { resolvedTheme } = useTheme(); + + return ( +
+ +
+ ); +} diff --git a/packages/frontend/core/src/components/sign-in/background-arts/style.css.ts b/packages/frontend/core/src/components/sign-in/background-arts/style.css.ts new file mode 100644 index 0000000000..bea396c01b --- /dev/null +++ b/packages/frontend/core/src/components/sign-in/background-arts/style.css.ts @@ -0,0 +1,14 @@ +import { style } from '@vanilla-extract/css'; + +export const wrapper = style({ + position: 'relative', + top: 0, + left: 0, + right: 0, + bottom: 0, +}); + +export const arts = style({ + position: 'absolute', + top: '128px', +}); diff --git a/packages/frontend/core/src/components/sign-in/index.tsx b/packages/frontend/core/src/components/sign-in/index.tsx index 3bcb0ef07a..005a7ef892 100644 --- a/packages/frontend/core/src/components/sign-in/index.tsx +++ b/packages/frontend/core/src/components/sign-in/index.tsx @@ -19,6 +19,7 @@ export interface SignInState { server?: Server; initialServerBaseUrl?: string; email?: string; + hasPassword?: boolean; redirectUrl?: string; } diff --git a/packages/frontend/core/src/components/sign-in/sign-in-with-email.tsx b/packages/frontend/core/src/components/sign-in/sign-in-with-email.tsx index 6957535590..0337d754d3 100644 --- a/packages/frontend/core/src/components/sign-in/sign-in-with-email.tsx +++ b/packages/frontend/core/src/components/sign-in/sign-in-with-email.tsx @@ -1,9 +1,10 @@ import { notify } from '@affine/component'; import { + AuthContainer, AuthContent, + AuthFooter, + AuthHeader, AuthInput, - BackButton, - ModalHeader, } from '@affine/component/auth-components'; import { Button } from '@affine/component/ui/button'; import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks'; @@ -26,6 +27,7 @@ import { } from 'react'; import type { SignInState } from '.'; +import { Back } from './back'; import { Captcha } from './captcha'; import * as style from './style.css'; @@ -123,10 +125,6 @@ export const SignInWithEmailStep = ({ changeState(prev => ({ ...prev, step: 'signInWithPassword' })); }, [changeState]); - const onBackBottomClick = useCallback(() => { - changeState(prev => ({ ...prev, step: 'signIn' })); - }, [changeState]); - const onOtpChanged = useCallback((value: string) => { setOtp(value); setOtpError(undefined); @@ -158,54 +156,55 @@ export const SignInWithEmailStep = ({ return !verifyToken && needCaptcha ? ( <> - + - + ) : ( - <> - + - - }} + +

+ }} + /> +

+ + -
- + - - -
-
+
-
- {t['com.affine.auth.sign.auth.code.message']()} -   - - ), - }} - /> -
+ +
+ {t['com.affine.auth.sign.auth.code.message']()} +   + {state.hasPassword && ( + + ), + }} + /> + )} +
- - + +
+ ); }; diff --git a/packages/frontend/core/src/components/sign-in/sign-in-with-password.tsx b/packages/frontend/core/src/components/sign-in/sign-in-with-password.tsx index f79ac964b5..002fcfd5fe 100644 --- a/packages/frontend/core/src/components/sign-in/sign-in-with-password.tsx +++ b/packages/frontend/core/src/components/sign-in/sign-in-with-password.tsx @@ -1,8 +1,10 @@ -import { notify, Wrapper } from '@affine/component'; +import { notify } from '@affine/component'; import { + AuthContainer, + AuthContent, + AuthFooter, + AuthHeader, AuthInput, - BackButton, - ModalHeader, } from '@affine/component/auth-components'; import { Button } from '@affine/component/ui/button'; import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks'; @@ -20,6 +22,7 @@ import type { Dispatch, SetStateAction } from 'react'; import { useCallback, useEffect, useState } from 'react'; import type { SignInState } from '.'; +import { Back } from './back'; import { Captcha } from './captcha'; import * as styles from './style.css'; @@ -105,18 +108,13 @@ export const SignInWithPasswordStep = ({ }, [changeState]); return ( - <> - + - + {t['com.affine.auth.sign.in']()} - - { - changeState(prev => ({ ...prev, step: 'signIn' })); - }, [changeState])} - /> - + + + + + ); }; diff --git a/packages/frontend/core/src/components/sign-in/sign-in.tsx b/packages/frontend/core/src/components/sign-in/sign-in.tsx index efbe5e2199..f25b1842ac 100644 --- a/packages/frontend/core/src/components/sign-in/sign-in.tsx +++ b/packages/frontend/core/src/components/sign-in/sign-in.tsx @@ -1,5 +1,10 @@ import { Button, notify } from '@affine/component'; -import { AuthInput, ModalHeader } from '@affine/component/auth-components'; +import { + AuthContainer, + AuthContent, + AuthHeader, + AuthInput, +} from '@affine/component/auth-components'; import { OAuth } from '@affine/core/components/affine/auth/oauth'; import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks'; import { AuthService, ServerService } from '@affine/core/modules/cloud'; @@ -7,7 +12,11 @@ import type { AuthSessionStatus } from '@affine/core/modules/cloud/entities/sess import { FeatureFlagService } from '@affine/core/modules/feature-flag'; import { ServerDeploymentType } from '@affine/graphql'; import { Trans, useI18n } from '@affine/i18n'; -import { ArrowRightBigIcon, PublishIcon } from '@blocksuite/icons/rc'; +import { + ArrowRightBigIcon, + LocalWorkspaceIcon, + PublishIcon, +} from '@blocksuite/icons/rc'; import { useLiveData, useService } from '@toeverything/infra'; import { cssVar } from '@toeverything/theme'; import { @@ -93,6 +102,7 @@ export const SignInStep = ({ ...prev, email, step: 'signInWithPassword', + hasPassword: true, })); } else { if (magicLink) { @@ -100,6 +110,7 @@ export const SignInStep = ({ ...prev, email, step: 'signInWithEmail', + hasPassword: false, })); } else { notify.error({ @@ -113,6 +124,7 @@ export const SignInStep = ({ ...prev, email, step: 'signInWithEmail', + hasPassword: false, })); } else { notify.error({ @@ -140,15 +152,15 @@ export const SignInStep = ({ }, [changeState]); return ( - <> - + - + + -
{!isSelfhosted && - BUILD_CONFIG.isElectron && - enableMultipleCloudServers && ( - - )} -
- {t['com.affine.mobile.sign-in.skip.hint']()} -
+ BUILD_CONFIG.isElectron && + enableMultipleCloudServers ? ( + + ) : ( +
+ {t['com.affine.mobile.sign-in.skip.hint']()} +
+ )}
-
- +
+ ); }; diff --git a/packages/frontend/core/src/components/sign-in/style.css.ts b/packages/frontend/core/src/components/sign-in/style.css.ts index 931ccfdd1a..c83413b73a 100644 --- a/packages/frontend/core/src/components/sign-in/style.css.ts +++ b/packages/frontend/core/src/components/sign-in/style.css.ts @@ -2,16 +2,12 @@ import { cssVar } from '@toeverything/theme'; import { cssVarV2 } from '@toeverything/theme/v2'; import { globalStyle, style } from '@vanilla-extract/css'; -export const authModalContent = style({ - marginTop: '30px', -}); - export const authMessage = style({ - marginTop: '30px', color: cssVar('textSecondaryColor'), fontSize: cssVar('fontXs'), - lineHeight: 1.5, + lineHeight: '20px', }); + globalStyle(`${authMessage} a`, { color: cssVar('linkColor'), }); @@ -42,14 +38,7 @@ export const linkButton = style({ userSelect: 'none', }); -export const resendButtonWrapper = style({ - marginTop: 20, -}); - export const addSelfhostedButton = style({ - marginTop: 10, - marginLeft: -5, - marginBottom: 16, color: cssVarV2('text/link'), }); @@ -62,8 +51,6 @@ export const skipDivider = style({ gap: 12, alignItems: 'center', height: 20, - marginTop: 12, - marginBottom: 12, }); export const skipDividerLine = style({ diff --git a/packages/frontend/core/src/desktop/dialogs/change-password/index.tsx b/packages/frontend/core/src/desktop/dialogs/change-password/index.tsx index cd9a5d5e24..d3b628ca26 100644 --- a/packages/frontend/core/src/desktop/dialogs/change-password/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/change-password/index.tsx @@ -1,8 +1,8 @@ -import { Button, Modal, notify, Wrapper } from '@affine/component'; +import { Button, Modal, notify } from '@affine/component'; import { AuthContent, + AuthHeader, AuthInput, - ModalHeader, } from '@affine/component/auth-components'; import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks'; import { @@ -108,7 +108,7 @@ export const ChangePasswordDialog = ({ style: { padding: '44px 40px 20px' }, }} > - - {hasPassword - ? t['com.affine.auth.reset.password.message']() - : t['com.affine.auth.set.password.message']({ - min: String(passwordLimits.minLength), - max: String(passwordLimits.maxLength), - })} - - - +

+ {hasPassword + ? t['com.affine.auth.reset.password.message']() + : t['com.affine.auth.set.password.message']({ + min: String(passwordLimits.minLength), + max: String(passwordLimits.maxLength), + })} +

-
- - + + ); }; diff --git a/packages/frontend/core/src/desktop/dialogs/sign-in/index.tsx b/packages/frontend/core/src/desktop/dialogs/sign-in/index.tsx index 7816142cef..41e8086fef 100644 --- a/packages/frontend/core/src/desktop/dialogs/sign-in/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/sign-in/index.tsx @@ -24,7 +24,7 @@ export const SignInDialog = ({ open onOpenChange={() => close()} width={400} - minHeight={500} + height={550} contentOptions={{ ['data-testid' as string]: 'auth-modal', style: { padding: '44px 40px 20px' }, diff --git a/packages/frontend/core/src/desktop/dialogs/verify-email/index.tsx b/packages/frontend/core/src/desktop/dialogs/verify-email/index.tsx index bef3fa5732..0ff4933c4f 100644 --- a/packages/frontend/core/src/desktop/dialogs/verify-email/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/verify-email/index.tsx @@ -1,8 +1,8 @@ -import { Button, Modal, notify, Wrapper } from '@affine/component'; +import { Button, Modal, notify } from '@affine/component'; import { AuthContent, + AuthHeader, AuthInput, - ModalHeader, } from '@affine/component/auth-components'; import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks'; import { @@ -106,28 +106,18 @@ export const VerifyEmailDialog = ({ style: { padding: '44px 40px 20px' }, }} > - - {t['com.affine.auth.verify.email.message']({ email })} - - - +

{t['com.affine.auth.verify.email.message']({ email })}

-
- +