mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-22 00:37:05 +08:00
feat(core): add responsive styles to registration page (#5044)
The responsive style of the login and registration page has been adjusted, with special treatment given to the input. work for #4843
This commit is contained in:
1
packages/common/env/src/global.ts
vendored
1
packages/common/env/src/global.ts
vendored
@@ -18,6 +18,7 @@ export const runtimeFlagsSchema = z.object({
|
|||||||
enableBroadcastChannelProvider: z.boolean(),
|
enableBroadcastChannelProvider: z.boolean(),
|
||||||
enableDebugPage: z.boolean(),
|
enableDebugPage: z.boolean(),
|
||||||
changelogUrl: z.string(),
|
changelogUrl: z.string(),
|
||||||
|
downloadUrl: z.string(),
|
||||||
// see: tools/workers
|
// see: tools/workers
|
||||||
imageProxyUrl: z.string(),
|
imageProxyUrl: z.string(),
|
||||||
enablePreloading: z.boolean(),
|
enablePreloading: z.boolean(),
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ export const tipsContainer = style({
|
|||||||
position: 'sticky',
|
position: 'sticky',
|
||||||
gap: '16px',
|
gap: '16px',
|
||||||
containerType: 'inline-size',
|
containerType: 'inline-size',
|
||||||
|
'@media': {
|
||||||
|
'screen and (max-width: 520px)': {
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const tipsMessage = style({
|
export const tipsMessage = style({
|
||||||
@@ -54,4 +59,9 @@ export const tipsRightItem = style({
|
|||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: '16px',
|
gap: '16px',
|
||||||
|
'@media': {
|
||||||
|
'screen and (max-width: 520px)': {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import * as styles from './index.css';
|
||||||
|
import { useNavConfig } from './use-nav-config';
|
||||||
|
|
||||||
|
export const DesktopNavbar = () => {
|
||||||
|
const config = useNavConfig();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.topNavLinks}>
|
||||||
|
{config.map(item => {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={item.title}
|
||||||
|
href={item.path}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className={styles.topNavLink}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import { style } from '@vanilla-extract/css';
|
||||||
|
|
||||||
|
export const root = style({
|
||||||
|
height: '100vh',
|
||||||
|
width: '100vw',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
fontSize: 'var(--affine-font-base)',
|
||||||
|
position: 'relative',
|
||||||
|
background: 'var(--affine-background-primary-color)',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const affineLogo = style({
|
||||||
|
color: 'inherit',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const topNav = style({
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
padding: '16px 120px',
|
||||||
|
selectors: {
|
||||||
|
'&.mobile': {
|
||||||
|
padding: '16px 20px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const topNavLinks = style({
|
||||||
|
display: 'flex',
|
||||||
|
columnGap: 4,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const topNavLink = style({
|
||||||
|
color: 'var(--affine-text-primary-color)',
|
||||||
|
fontSize: 'var(--affine-font-sm)',
|
||||||
|
fontWeight: 500,
|
||||||
|
textDecoration: 'none',
|
||||||
|
padding: '4px 18px',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const iconButton = style({
|
||||||
|
fontSize: '24px',
|
||||||
|
pointerEvents: 'auto',
|
||||||
|
selectors: {
|
||||||
|
'&.plain': {
|
||||||
|
color: 'var(--affine-text-primary-color)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const menu = style({
|
||||||
|
width: '100vw',
|
||||||
|
height: '100vh',
|
||||||
|
padding: '0',
|
||||||
|
background: 'var(--affine-background-primary-color)',
|
||||||
|
borderRadius: '0',
|
||||||
|
border: 'none',
|
||||||
|
boxShadow: 'none',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const menuItem = style({
|
||||||
|
color: 'var(--affine-text-primary-color)',
|
||||||
|
fontSize: 'var(--affine-font-sm)',
|
||||||
|
fontWeight: 500,
|
||||||
|
textDecoration: 'none',
|
||||||
|
padding: '12px 20px',
|
||||||
|
maxWidth: '100%',
|
||||||
|
position: 'relative',
|
||||||
|
borderRadius: '0',
|
||||||
|
transition: 'background 0.3s ease',
|
||||||
|
selectors: {
|
||||||
|
'&:after': {
|
||||||
|
position: 'absolute',
|
||||||
|
content: '""',
|
||||||
|
bottom: 0,
|
||||||
|
display: 'block',
|
||||||
|
width: 'calc(100% - 40px)',
|
||||||
|
height: '0.5px',
|
||||||
|
background: 'var(--affine-black-10)',
|
||||||
|
},
|
||||||
|
'&:not(:last-of-type)': {
|
||||||
|
marginBottom: '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './layout';
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { Button } from '@affine/component/ui/button';
|
||||||
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
|
import { Logo1Icon } from '@blocksuite/icons';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
import { DesktopNavbar } from './desktop-navbar';
|
||||||
|
import * as styles from './index.css';
|
||||||
|
import { MobileNavbar } from './mobile-navbar';
|
||||||
|
|
||||||
|
export const AffineOtherPageLayout = ({
|
||||||
|
isSmallScreen,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
isSmallScreen: boolean;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
|
const openDownloadLink = useCallback(() => {
|
||||||
|
open(runtimeConfig.downloadUrl, '_blank');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.root}>
|
||||||
|
<div
|
||||||
|
className={clsx(styles.topNav, {
|
||||||
|
mobile: isSmallScreen,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<a href="/" rel="noreferrer" className={styles.affineLogo}>
|
||||||
|
<Logo1Icon width={24} height={24} />
|
||||||
|
</a>
|
||||||
|
{isSmallScreen ? (
|
||||||
|
<MobileNavbar />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<DesktopNavbar />
|
||||||
|
<Button onClick={openDownloadLink}>
|
||||||
|
{t['com.affine.auth.open.affine.download-app']()}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import { IconButton } from '@affine/component/ui/button';
|
||||||
|
import { Menu, MenuItem } from '@affine/component/ui/menu';
|
||||||
|
import { CloseIcon, PropertyIcon } from '@blocksuite/icons';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import * as styles from './index.css';
|
||||||
|
import { useNavConfig } from './use-nav-config';
|
||||||
|
|
||||||
|
export const MobileNavbar = () => {
|
||||||
|
const [openMenu, setOpenMenu] = useState(false);
|
||||||
|
const navConfig = useNavConfig();
|
||||||
|
|
||||||
|
const menuItems = (
|
||||||
|
<>
|
||||||
|
{navConfig.map(item => {
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
key={item.title}
|
||||||
|
onClick={() => {
|
||||||
|
open(item.path, '_blank');
|
||||||
|
}}
|
||||||
|
className={styles.menuItem}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Menu
|
||||||
|
items={menuItems}
|
||||||
|
contentOptions={{
|
||||||
|
className: styles.menu,
|
||||||
|
sideOffset: 20,
|
||||||
|
}}
|
||||||
|
rootOptions={{
|
||||||
|
open: openMenu,
|
||||||
|
onOpenChange: setOpenMenu,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton type="plain" className={styles.iconButton}>
|
||||||
|
{openMenu ? <CloseIcon /> : <PropertyIcon />}
|
||||||
|
</IconButton>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
export const useNavConfig = () => {
|
||||||
|
const t = useAFFiNEI18N();
|
||||||
|
return useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
title: t['com.affine.other-page.nav.official-website'](),
|
||||||
|
path: 'https://affine.pro',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['com.affine.other-page.nav.affine-community'](),
|
||||||
|
path: 'https://community.affine.pro/home',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['com.affine.other-page.nav.blog'](),
|
||||||
|
path: 'https://affine.pro/blog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t['com.affine.other-page.nav.contact-us'](),
|
||||||
|
path: 'https://affine.pro/about-us',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -2,7 +2,7 @@ import clsx from 'clsx';
|
|||||||
import type { FC, HTMLAttributes } from 'react';
|
import type { FC, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
import { Input, type InputProps } from '../../ui/input';
|
import { Input, type InputProps } from '../../ui/input';
|
||||||
import { authInputWrapper, formHint } from './share.css';
|
import * as styles from './share.css';
|
||||||
export type AuthInputProps = InputProps & {
|
export type AuthInputProps = InputProps & {
|
||||||
label?: string;
|
label?: string;
|
||||||
error?: boolean;
|
error?: boolean;
|
||||||
@@ -22,13 +22,14 @@ export const AuthInput: FC<AuthInputProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(authInputWrapper, className, {
|
className={clsx(styles.authInputWrapper, className, {
|
||||||
'without-hint': withoutHint,
|
'without-hint': withoutHint,
|
||||||
})}
|
})}
|
||||||
{...otherWrapperProps}
|
{...otherWrapperProps}
|
||||||
>
|
>
|
||||||
{label ? <label>{label}</label> : null}
|
{label ? <label>{label}</label> : null}
|
||||||
<Input
|
<Input
|
||||||
|
className={styles.input}
|
||||||
size="extraLarge"
|
size="extraLarge"
|
||||||
status={error ? 'error' : 'default'}
|
status={error ? 'error' : 'default'}
|
||||||
onKeyDown={e => {
|
onKeyDown={e => {
|
||||||
@@ -40,7 +41,7 @@ export const AuthInput: FC<AuthInputProps> = ({
|
|||||||
/>
|
/>
|
||||||
{error && errorHint && !withoutHint ? (
|
{error && errorHint && !withoutHint ? (
|
||||||
<div
|
<div
|
||||||
className={clsx(formHint, {
|
className={clsx(styles.formHint, {
|
||||||
error: error,
|
error: error,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,32 +1,41 @@
|
|||||||
import type { FC, PropsWithChildren, ReactNode } from 'react';
|
import {
|
||||||
|
type FC,
|
||||||
|
type PropsWithChildren,
|
||||||
|
type ReactNode,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
import { Empty } from '../../ui/empty';
|
import { Empty } from '../../ui/empty';
|
||||||
import { Wrapper } from '../../ui/layout';
|
import { AffineOtherPageLayout } from '../affine-other-page-layout';
|
||||||
import { Logo } from './logo';
|
|
||||||
import { authPageContainer } from './share.css';
|
import { authPageContainer } from './share.css';
|
||||||
|
|
||||||
export const AuthPageContainer: FC<
|
export const AuthPageContainer: FC<
|
||||||
PropsWithChildren<{ title?: ReactNode; subtitle?: ReactNode }>
|
PropsWithChildren<{ title?: ReactNode; subtitle?: ReactNode }>
|
||||||
> = ({ children, title, subtitle }) => {
|
> = ({ children, title, subtitle }) => {
|
||||||
|
const [isSmallScreen, setIsSmallScreen] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkScreenSize = () => {
|
||||||
|
setIsSmallScreen(window.innerWidth <= 1024);
|
||||||
|
};
|
||||||
|
checkScreenSize();
|
||||||
|
window.addEventListener('resize', checkScreenSize);
|
||||||
|
return () => window.removeEventListener('resize', checkScreenSize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={authPageContainer}>
|
<AffineOtherPageLayout isSmallScreen={isSmallScreen}>
|
||||||
<Wrapper
|
<div className={authPageContainer}>
|
||||||
style={{
|
<div className="wrapper">
|
||||||
position: 'absolute',
|
<div className="content">
|
||||||
top: 25,
|
<p className="title">{title}</p>
|
||||||
left: 20,
|
<p className="subtitle">{subtitle}</p>
|
||||||
}}
|
{children}
|
||||||
>
|
</div>
|
||||||
<Logo />
|
{isSmallScreen ? null : <Empty />}
|
||||||
</Wrapper>
|
|
||||||
<div className="wrapper">
|
|
||||||
<div className="content">
|
|
||||||
<p className="title">{title}</p>
|
|
||||||
<p className="subtitle">{subtitle}</p>
|
|
||||||
{children}
|
|
||||||
</div>
|
</div>
|
||||||
<Empty />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</AffineOtherPageLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ export const ChangeEmailPage = ({
|
|||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
<AuthInput
|
<AuthInput
|
||||||
width={320}
|
|
||||||
label={t['com.affine.settings.email']()}
|
label={t['com.affine.settings.email']()}
|
||||||
placeholder={t['com.affine.auth.sign.email.placeholder']()}
|
placeholder={t['com.affine.auth.sign.email.placeholder']()}
|
||||||
value={email}
|
value={email}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { type FC, useEffect } from 'react';
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import { Input, type InputProps } from '../../../ui/input';
|
import { Input, type InputProps } from '../../../ui/input';
|
||||||
|
import * as styles from '../share.css';
|
||||||
import { ErrorIcon } from './error';
|
import { ErrorIcon } from './error';
|
||||||
import { SuccessIcon } from './success';
|
import { SuccessIcon } from './success';
|
||||||
import { Tag } from './tag';
|
import { Tag } from './tag';
|
||||||
@@ -74,6 +75,7 @@ export const PasswordInput: FC<
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Input
|
<Input
|
||||||
|
className={styles.input}
|
||||||
type="password"
|
type="password"
|
||||||
size="extraLarge"
|
size="extraLarge"
|
||||||
style={{ marginBottom: 20 }}
|
style={{ marginBottom: 20 }}
|
||||||
@@ -83,6 +85,7 @@ export const PasswordInput: FC<
|
|||||||
{...inputProps}
|
{...inputProps}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
|
className={styles.input}
|
||||||
type="password"
|
type="password"
|
||||||
size="extraLarge"
|
size="extraLarge"
|
||||||
placeholder={t['com.affine.auth.set.password.placeholder.confirm']()}
|
placeholder={t['com.affine.auth.set.password.placeholder.confirm']()}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ export const SetPassword: FC<{
|
|||||||
<>
|
<>
|
||||||
<Wrapper marginTop={30} marginBottom={42}>
|
<Wrapper marginTop={30} marginBottom={42}>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
width={320}
|
|
||||||
onPass={useCallback(password => {
|
onPass={useCallback(password => {
|
||||||
setPasswordPass(true);
|
setPasswordPass(true);
|
||||||
passwordRef.current = password;
|
passwordRef.current = password;
|
||||||
|
|||||||
@@ -151,14 +151,25 @@ export const authPageContainer = style({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
fontSize: 'var(--affine-font-base)',
|
fontSize: 'var(--affine-font-base)',
|
||||||
|
'@media': {
|
||||||
|
'screen and (max-width: 1024px)': {
|
||||||
|
flexDirection: 'column',
|
||||||
|
padding: '100px 20px',
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
globalStyle(`${authPageContainer} .wrapper`, {
|
globalStyle(`${authPageContainer} .wrapper`, {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
'@media': {
|
||||||
|
'screen and (max-width: 1024px)': {
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
globalStyle(`${authPageContainer} .content`, {
|
globalStyle(`${authPageContainer} .content`, {
|
||||||
maxWidth: '700px',
|
maxWidth: '700px',
|
||||||
minWidth: '550px',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
globalStyle(`${authPageContainer} .title`, {
|
globalStyle(`${authPageContainer} .title`, {
|
||||||
@@ -178,3 +189,12 @@ export const signInPageContainer = style({
|
|||||||
width: '400px',
|
width: '400px',
|
||||||
margin: '205px auto 0',
|
margin: '205px auto 0',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const input = style({
|
||||||
|
width: '330px',
|
||||||
|
'@media': {
|
||||||
|
'screen and (max-width: 520px)': {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const notFoundPageContainer = style({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
width: '100vw',
|
width: '100vw',
|
||||||
|
padding: '0 20px',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const wrapper = style({
|
export const wrapper = style({
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
|
|||||||
enableBroadcastChannelProvider: true,
|
enableBroadcastChannelProvider: true,
|
||||||
enableDebugPage: true,
|
enableDebugPage: true,
|
||||||
changelogUrl: 'https://affine.pro/what-is-new',
|
changelogUrl: 'https://affine.pro/what-is-new',
|
||||||
|
downloadUrl: 'https://affine.pro/download',
|
||||||
imageProxyUrl: 'https://workers.toeverything.workers.dev/proxy/image',
|
imageProxyUrl: 'https://workers.toeverything.workers.dev/proxy/image',
|
||||||
enablePreloading: true,
|
enablePreloading: true,
|
||||||
enableNewSettingModal: true,
|
enableNewSettingModal: true,
|
||||||
@@ -67,6 +68,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
|
|||||||
enableBroadcastChannelProvider: true,
|
enableBroadcastChannelProvider: true,
|
||||||
enableDebugPage: true,
|
enableDebugPage: true,
|
||||||
changelogUrl: 'https://github.com/toeverything/AFFiNE/releases',
|
changelogUrl: 'https://github.com/toeverything/AFFiNE/releases',
|
||||||
|
downloadUrl: 'https://affine.pro/download',
|
||||||
imageProxyUrl: 'https://workers.toeverything.workers.dev/proxy/image',
|
imageProxyUrl: 'https://workers.toeverything.workers.dev/proxy/image',
|
||||||
enablePreloading: true,
|
enablePreloading: true,
|
||||||
enableNewSettingModal: true,
|
enableNewSettingModal: true,
|
||||||
|
|||||||
@@ -1,87 +1,9 @@
|
|||||||
import { style } from '@vanilla-extract/css';
|
import { style } from '@vanilla-extract/css';
|
||||||
|
|
||||||
export const root = style({
|
|
||||||
height: '100vh',
|
|
||||||
width: '100vw',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
fontSize: 'var(--affine-font-base)',
|
|
||||||
position: 'relative',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const affineLogo = style({
|
|
||||||
color: 'inherit',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const topNav = style({
|
|
||||||
position: 'absolute',
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
padding: '16px 120px',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const topNavLinks = style({
|
|
||||||
display: 'flex',
|
|
||||||
columnGap: 4,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const topNavLink = style({
|
|
||||||
color: 'var(--affine-text-primary-color)',
|
|
||||||
fontSize: 'var(--affine-font-sm)',
|
|
||||||
fontWeight: 500,
|
|
||||||
textDecoration: 'none',
|
|
||||||
padding: '4px 18px',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const tryAgainLink = style({
|
|
||||||
color: 'var(--affine-link-color)',
|
|
||||||
fontWeight: 500,
|
|
||||||
textDecoration: 'none',
|
|
||||||
fontSize: 'var(--affine-font-sm)',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const centerContent = style({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginTop: 40,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const prompt = style({
|
|
||||||
marginTop: 20,
|
|
||||||
marginBottom: 12,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const body = style({
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
width: '100%',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
gap: '48px',
|
|
||||||
padding: '0 20px',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const leftContainer = style({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
width: '548px',
|
|
||||||
gap: '28px',
|
|
||||||
});
|
|
||||||
export const leftContentTitle = style({
|
|
||||||
fontSize: 'var(--affine-font-title)',
|
|
||||||
fontWeight: 700,
|
|
||||||
minHeight: '44px',
|
|
||||||
});
|
|
||||||
export const leftContentText = style({
|
export const leftContentText = style({
|
||||||
fontSize: 'var(--affine-font-base)',
|
fontSize: 'var(--affine-font-base)',
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
lineHeight: '1.6',
|
lineHeight: '1.6',
|
||||||
|
maxWidth: '548px',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const mail = style({
|
export const mail = style({
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { Empty } from '@affine/component';
|
import { AuthPageContainer } from '@affine/component/auth-components';
|
||||||
import { Button } from '@affine/component/ui/button';
|
import { Button } from '@affine/component/ui/button';
|
||||||
import { Trans } from '@affine/i18n';
|
import { Trans } from '@affine/i18n';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { Logo1Icon } from '@blocksuite/icons';
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
import { useNavigateHelper } from '../hooks/use-navigate-helper';
|
import { useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||||
@@ -11,93 +10,40 @@ import * as styles from './upgrade-success.css';
|
|||||||
export const UpgradeSuccess = () => {
|
export const UpgradeSuccess = () => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
const openDownloadLink = useCallback(() => {
|
|
||||||
const url = `https://affine.pro/download`;
|
|
||||||
open(url, '_blank');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const { jumpToIndex } = useNavigateHelper();
|
const { jumpToIndex } = useNavigateHelper();
|
||||||
const openAffine = useCallback(() => {
|
const openAffine = useCallback(() => {
|
||||||
jumpToIndex();
|
jumpToIndex();
|
||||||
}, [jumpToIndex]);
|
}, [jumpToIndex]);
|
||||||
|
|
||||||
return (
|
const subtitle = (
|
||||||
<div className={styles.root}>
|
<div className={styles.leftContentText}>
|
||||||
<div className={styles.topNav}>
|
{t['com.affine.payment.upgrade-success-page.text']()}
|
||||||
<a href="/" rel="noreferrer" className={styles.affineLogo}>
|
<div>
|
||||||
<Logo1Icon width={24} height={24} />
|
<Trans
|
||||||
</a>
|
i18nKey={'com.affine.payment.upgrade-success-page.support'}
|
||||||
|
components={{
|
||||||
<div className={styles.topNavLinks}>
|
1: (
|
||||||
<a
|
<a
|
||||||
href="https://affine.pro"
|
href="mailto:support@toeverything.info"
|
||||||
target="_blank"
|
className={styles.mail}
|
||||||
rel="noreferrer"
|
|
||||||
className={styles.topNavLink}
|
|
||||||
>
|
|
||||||
{t['com.affine.other-page.nav.official-website']()}
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://community.affine.pro/home"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className={styles.topNavLink}
|
|
||||||
>
|
|
||||||
{t['com.affine.other-page.nav.affine-community']()}
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://affine.pro/blog"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className={styles.topNavLink}
|
|
||||||
>
|
|
||||||
{t['com.affine.other-page.nav.blog']()}
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://affine.pro/about-us"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className={styles.topNavLink}
|
|
||||||
>
|
|
||||||
{t['com.affine.other-page.nav.contact-us']()}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button onClick={openDownloadLink}>
|
|
||||||
{t['com.affine.auth.open.affine.download-app']()}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className={styles.body}>
|
|
||||||
<div className={styles.leftContainer}>
|
|
||||||
<div className={styles.leftContentTitle}>
|
|
||||||
{t['com.affine.payment.upgrade-success-page.title']()}
|
|
||||||
</div>
|
|
||||||
<div className={styles.leftContentText}>
|
|
||||||
{t['com.affine.payment.upgrade-success-page.text']()}
|
|
||||||
<div>
|
|
||||||
<Trans
|
|
||||||
i18nKey={'com.affine.payment.upgrade-success-page.support'}
|
|
||||||
components={{
|
|
||||||
1: (
|
|
||||||
<a
|
|
||||||
href="mailto:support@toeverything.info"
|
|
||||||
className={styles.mail}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
),
|
||||||
</div>
|
}}
|
||||||
<div>
|
/>
|
||||||
<Button type="primary" size="extraLarge" onClick={openAffine}>
|
|
||||||
{t['com.affine.other-page.nav.open-affine']()}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Empty />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthPageContainer
|
||||||
|
title={t['com.affine.payment.upgrade-success-page.title']()}
|
||||||
|
subtitle={subtitle}
|
||||||
|
>
|
||||||
|
<Button type="primary" size="extraLarge" onClick={openAffine}>
|
||||||
|
{t['com.affine.other-page.nav.open-affine']()}
|
||||||
|
</Button>
|
||||||
|
</AuthPageContainer>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Component = () => {
|
export const Component = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user