mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00: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(),
|
||||
enableDebugPage: z.boolean(),
|
||||
changelogUrl: z.string(),
|
||||
downloadUrl: z.string(),
|
||||
// see: tools/workers
|
||||
imageProxyUrl: z.string(),
|
||||
enablePreloading: z.boolean(),
|
||||
|
||||
@@ -40,6 +40,11 @@ export const tipsContainer = style({
|
||||
position: 'sticky',
|
||||
gap: '16px',
|
||||
containerType: 'inline-size',
|
||||
'@media': {
|
||||
'screen and (max-width: 520px)': {
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const tipsMessage = style({
|
||||
@@ -54,4 +59,9 @@ export const tipsRightItem = style({
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
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 { Input, type InputProps } from '../../ui/input';
|
||||
import { authInputWrapper, formHint } from './share.css';
|
||||
import * as styles from './share.css';
|
||||
export type AuthInputProps = InputProps & {
|
||||
label?: string;
|
||||
error?: boolean;
|
||||
@@ -22,13 +22,14 @@ export const AuthInput: FC<AuthInputProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(authInputWrapper, className, {
|
||||
className={clsx(styles.authInputWrapper, className, {
|
||||
'without-hint': withoutHint,
|
||||
})}
|
||||
{...otherWrapperProps}
|
||||
>
|
||||
{label ? <label>{label}</label> : null}
|
||||
<Input
|
||||
className={styles.input}
|
||||
size="extraLarge"
|
||||
status={error ? 'error' : 'default'}
|
||||
onKeyDown={e => {
|
||||
@@ -40,7 +41,7 @@ export const AuthInput: FC<AuthInputProps> = ({
|
||||
/>
|
||||
{error && errorHint && !withoutHint ? (
|
||||
<div
|
||||
className={clsx(formHint, {
|
||||
className={clsx(styles.formHint, {
|
||||
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 { Wrapper } from '../../ui/layout';
|
||||
import { Logo } from './logo';
|
||||
import { AffineOtherPageLayout } from '../affine-other-page-layout';
|
||||
import { authPageContainer } from './share.css';
|
||||
|
||||
export const AuthPageContainer: FC<
|
||||
PropsWithChildren<{ title?: ReactNode; subtitle?: ReactNode }>
|
||||
> = ({ 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 (
|
||||
<div className={authPageContainer}>
|
||||
<Wrapper
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 25,
|
||||
left: 20,
|
||||
}}
|
||||
>
|
||||
<Logo />
|
||||
</Wrapper>
|
||||
<div className="wrapper">
|
||||
<div className="content">
|
||||
<p className="title">{title}</p>
|
||||
<p className="subtitle">{subtitle}</p>
|
||||
{children}
|
||||
<AffineOtherPageLayout isSmallScreen={isSmallScreen}>
|
||||
<div className={authPageContainer}>
|
||||
<div className="wrapper">
|
||||
<div className="content">
|
||||
<p className="title">{title}</p>
|
||||
<p className="subtitle">{subtitle}</p>
|
||||
{children}
|
||||
</div>
|
||||
{isSmallScreen ? null : <Empty />}
|
||||
</div>
|
||||
<Empty />
|
||||
</div>
|
||||
</div>
|
||||
</AffineOtherPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -44,7 +44,6 @@ export const ChangeEmailPage = ({
|
||||
>
|
||||
<>
|
||||
<AuthInput
|
||||
width={320}
|
||||
label={t['com.affine.settings.email']()}
|
||||
placeholder={t['com.affine.auth.sign.email.placeholder']()}
|
||||
value={email}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { type FC, useEffect } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { Input, type InputProps } from '../../../ui/input';
|
||||
import * as styles from '../share.css';
|
||||
import { ErrorIcon } from './error';
|
||||
import { SuccessIcon } from './success';
|
||||
import { Tag } from './tag';
|
||||
@@ -74,6 +75,7 @@ export const PasswordInput: FC<
|
||||
return (
|
||||
<>
|
||||
<Input
|
||||
className={styles.input}
|
||||
type="password"
|
||||
size="extraLarge"
|
||||
style={{ marginBottom: 20 }}
|
||||
@@ -83,6 +85,7 @@ export const PasswordInput: FC<
|
||||
{...inputProps}
|
||||
/>
|
||||
<Input
|
||||
className={styles.input}
|
||||
type="password"
|
||||
size="extraLarge"
|
||||
placeholder={t['com.affine.auth.set.password.placeholder.confirm']()}
|
||||
|
||||
@@ -19,7 +19,6 @@ export const SetPassword: FC<{
|
||||
<>
|
||||
<Wrapper marginTop={30} marginBottom={42}>
|
||||
<PasswordInput
|
||||
width={320}
|
||||
onPass={useCallback(password => {
|
||||
setPasswordPass(true);
|
||||
passwordRef.current = password;
|
||||
|
||||
@@ -151,14 +151,25 @@ export const authPageContainer = style({
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
fontSize: 'var(--affine-font-base)',
|
||||
'@media': {
|
||||
'screen and (max-width: 1024px)': {
|
||||
flexDirection: 'column',
|
||||
padding: '100px 20px',
|
||||
justifyContent: 'flex-start',
|
||||
},
|
||||
},
|
||||
});
|
||||
globalStyle(`${authPageContainer} .wrapper`, {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
'@media': {
|
||||
'screen and (max-width: 1024px)': {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
},
|
||||
});
|
||||
globalStyle(`${authPageContainer} .content`, {
|
||||
maxWidth: '700px',
|
||||
minWidth: '550px',
|
||||
});
|
||||
|
||||
globalStyle(`${authPageContainer} .title`, {
|
||||
@@ -178,3 +189,12 @@ export const signInPageContainer = style({
|
||||
width: '400px',
|
||||
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',
|
||||
justifyContent: 'center',
|
||||
width: '100vw',
|
||||
padding: '0 20px',
|
||||
});
|
||||
|
||||
export const wrapper = style({
|
||||
|
||||
@@ -20,6 +20,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
|
||||
enableBroadcastChannelProvider: true,
|
||||
enableDebugPage: true,
|
||||
changelogUrl: 'https://affine.pro/what-is-new',
|
||||
downloadUrl: 'https://affine.pro/download',
|
||||
imageProxyUrl: 'https://workers.toeverything.workers.dev/proxy/image',
|
||||
enablePreloading: true,
|
||||
enableNewSettingModal: true,
|
||||
@@ -67,6 +68,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
|
||||
enableBroadcastChannelProvider: true,
|
||||
enableDebugPage: true,
|
||||
changelogUrl: 'https://github.com/toeverything/AFFiNE/releases',
|
||||
downloadUrl: 'https://affine.pro/download',
|
||||
imageProxyUrl: 'https://workers.toeverything.workers.dev/proxy/image',
|
||||
enablePreloading: true,
|
||||
enableNewSettingModal: true,
|
||||
|
||||
@@ -1,87 +1,9 @@
|
||||
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({
|
||||
fontSize: 'var(--affine-font-base)',
|
||||
fontWeight: 400,
|
||||
lineHeight: '1.6',
|
||||
maxWidth: '548px',
|
||||
});
|
||||
|
||||
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 { Trans } from '@affine/i18n';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { Logo1Icon } from '@blocksuite/icons';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
@@ -11,93 +10,40 @@ import * as styles from './upgrade-success.css';
|
||||
export const UpgradeSuccess = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const openDownloadLink = useCallback(() => {
|
||||
const url = `https://affine.pro/download`;
|
||||
open(url, '_blank');
|
||||
}, []);
|
||||
|
||||
const { jumpToIndex } = useNavigateHelper();
|
||||
const openAffine = useCallback(() => {
|
||||
jumpToIndex();
|
||||
}, [jumpToIndex]);
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.topNav}>
|
||||
<a href="/" rel="noreferrer" className={styles.affineLogo}>
|
||||
<Logo1Icon width={24} height={24} />
|
||||
</a>
|
||||
|
||||
<div className={styles.topNavLinks}>
|
||||
<a
|
||||
href="https://affine.pro"
|
||||
target="_blank"
|
||||
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}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
const subtitle = (
|
||||
<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>
|
||||
);
|
||||
|
||||
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 = () => {
|
||||
|
||||
Reference in New Issue
Block a user