feat: migrate workspace setting with new design to setting modal (#2900)

Co-authored-by: Alex Yang <himself65@outlook.com>
This commit is contained in:
Qi
2023-06-28 22:45:33 +08:00
committed by Alex Yang
parent 5a3e5a1565
commit 4cca8a16ab
33 changed files with 1540 additions and 141 deletions
@@ -1,14 +0,0 @@
import type { FC } from 'react';
import { settingHeader } from './share.css';
export const SettingHeader: FC<{ title: string; subtitle?: string }> = ({
title,
subtitle,
}) => {
return (
<div className={settingHeader}>
<div className="title">{title}</div>
<div className="subtitle">{subtitle}</div>
</div>
);
};
@@ -1,22 +0,0 @@
import type { CSSProperties, FC, PropsWithChildren, ReactElement } from 'react';
import { settingRow } from './share.css';
export const SettingRow: FC<
PropsWithChildren<{
name: string;
desc: string | ReactElement;
style?: CSSProperties;
onClick?: () => void;
}>
> = ({ name, desc, children, onClick, style }) => {
return (
<div className={settingRow} style={style} onClick={onClick}>
<div className="left-col">
<div className="name">{name}</div>
<div className="desc">{desc}</div>
</div>
<div className="right-col">{children}</div>
</div>
);
};
@@ -1,69 +0,0 @@
import { globalStyle, style } from '@vanilla-extract/css';
export const settingHeader = style({
height: '68px',
borderBottom: '1px solid var(--affine-border-color)',
marginBottom: '24px',
});
globalStyle(`${settingHeader} .title`, {
fontSize: 'var(--affine-font-base)',
fontWeight: 600,
lineHeight: '24px',
marginBottom: '4px',
});
globalStyle(`${settingHeader} .subtitle`, {
fontSize: 'var(--affine-font-xs)',
lineHeight: '16px',
color: 'var(--affine-text-secondary-color)',
});
export const wrapper = style({
borderBottom: '1px solid var(--affine-border-color)',
paddingBottom: '24px',
marginBottom: '24px',
selectors: {
'&:last-of-type': {
borderBottom: 'none',
paddingBottom: '0',
marginBottom: '0',
},
},
});
globalStyle(`${wrapper} .title`, {
fontSize: 'var(--affine-font-sm)',
fontWeight: 600,
lineHeight: '18px',
color: 'var(--affine-text-secondary-color)',
marginBottom: '16px',
});
export const settingRow = style({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: '25px',
color: 'var(--affine-text-primary-color)',
});
globalStyle(`${settingRow} .left-col`, {
flexShrink: 0,
maxWidth: '80%',
});
globalStyle(`${settingRow} .name`, {
marginBottom: '2px',
fontSize: 'var(--affine-font-sm)',
fontWeight: 600,
});
globalStyle(`${settingRow} .desc`, {
fontSize: 'var(--affine-font-xs)',
color: 'var(--affine-text-secondary-color)',
});
globalStyle(`${settingRow} .right-col`, {
flexGrow: 1,
display: 'flex',
justifyContent: 'flex-end',
paddingLeft: '15px',
});
@@ -1,14 +0,0 @@
import type { FC, PropsWithChildren } from 'react';
import { wrapper } from './share.css';
export const Wrapper: FC<PropsWithChildren<{ title?: string }>> = ({
title,
children,
}) => {
return (
<div className={wrapper}>
{title ? <div className="title">{title}</div> : null}
{children}
</div>
);
};
@@ -1,2 +1,2 @@
// Some settings are not implemented yet, but need to show in the setting modal when boss is watching.
export const IS_EXHIBITION = false;
export const IS_EXHIBITION = true;
@@ -1,14 +1,13 @@
import { Switch } from '@affine/component';
import { relatedLinks } from '@affine/component/contact-modal';
import { isDesktop } from '@affine/env/constant';
import { SettingHeader } from '@affine/component/setting-components';
import { SettingRow } from '@affine/component/setting-components';
import { SettingWrapper } from '@affine/component/setting-components';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { ArrowRightSmallIcon, OpenInNewIcon } from '@blocksuite/icons';
import { useCallback } from 'react';
import { type AppSetting, useAppSetting } from '../../../../../atoms/settings';
import { SettingHeader } from '../../common/setting-header';
import { SettingRow } from '../../common/setting-row';
import { Wrapper } from '../../common/wrapper';
import { IS_EXHIBITION } from '../../config';
import { communityItem, communityWrapper, link } from './style.css';
@@ -24,8 +23,8 @@ export const AboutAffine = () => {
return (
<>
<SettingHeader title={t['About AFFiNE']()} subtitle={t['None yet']()} />
{IS_EXHIBITION && isDesktop ? (
<Wrapper title={t['Version']()}>
{IS_EXHIBITION && environment.isDesktop ? (
<SettingWrapper title={t['Version']()}>
<SettingRow
name={t['Check for updates']()}
desc={t['New version is ready']()}
@@ -65,9 +64,9 @@ export const AboutAffine = () => {
>
<ArrowRightSmallIcon />
</SettingRow>
</Wrapper>
</SettingWrapper>
) : null}
<Wrapper title={t['Contact with us']()}>
<SettingWrapper title={t['Contact with us']()}>
<a className={link} href="https://affine.pro" target="_blank">
{t['Official Website']()}
<OpenInNewIcon className="icon" />
@@ -76,8 +75,8 @@ export const AboutAffine = () => {
{t['AFFiNE Community']()}
<OpenInNewIcon className="icon" />
</a>
</Wrapper>
<Wrapper title={t['Communities']()}>
</SettingWrapper>
<SettingWrapper title={t['Communities']()}>
<div className={communityWrapper}>
{relatedLinks.map(({ icon, title, link }) => {
return (
@@ -94,8 +93,8 @@ export const AboutAffine = () => {
);
})}
</div>
</Wrapper>
<Wrapper title={t['Info of legal']()}>
</SettingWrapper>
<SettingWrapper title={t['Info of legal']()}>
<a className={link} href="https://affine.pro/privacy" target="_blank">
{t['Privacy']()}
<OpenInNewIcon className="icon" />
@@ -104,7 +103,7 @@ export const AboutAffine = () => {
{t['Terms of Use']()}
<OpenInNewIcon className="icon" />
</a>
</Wrapper>
</SettingWrapper>
</>
);
};
@@ -1,5 +1,7 @@
import { RadioButton, RadioButtonGroup, Switch } from '@affine/component';
import { isDesktop } from '@affine/env/constant';
import { SettingHeader } from '@affine/component/setting-components';
import { SettingRow } from '@affine/component/setting-components';
import { SettingWrapper } from '@affine/component/setting-components';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useTheme } from 'next-themes';
import { useCallback } from 'react';
@@ -10,9 +12,6 @@ import {
windowFrameStyleOptions,
} from '../../../../../atoms/settings';
import { LanguageMenu } from '../../../language-menu';
import { SettingHeader } from '../../common/setting-header';
import { SettingRow } from '../../common/setting-row';
import { Wrapper } from '../../common/wrapper';
import { IS_EXHIBITION } from '../../config';
import { DateFormatSetting } from './date-format-setting';
import { settingWrapper } from './style.css';
@@ -56,7 +55,7 @@ export const AppearanceSettings = () => {
subtitle={t['Customize your AFFiNE Appearance']()}
/>
<Wrapper title={t['Theme']()}>
<SettingWrapper title={t['Theme']()}>
<SettingRow
name={t['Color Scheme']()}
desc={t['Choose your color scheme']()}
@@ -71,7 +70,7 @@ export const AppearanceSettings = () => {
<LanguageMenu />
</div>
</SettingRow>
{IS_EXHIBITION && isDesktop ? (
{IS_EXHIBITION && environment.isDesktop ? (
<SettingRow
name={t['Client Border Style']()}
desc={t['Customize the appearance of the client.']()}
@@ -92,7 +91,7 @@ export const AppearanceSettings = () => {
onChange={checked => changeSwitch('fullWidthLayout', checked)}
/>
</SettingRow>
{IS_EXHIBITION && isDesktop ? (
{IS_EXHIBITION && environment.isDesktop ? (
<SettingRow
name={t['Window frame style']()}
desc={t['Customize appearance of Windows Client.']()}
@@ -114,9 +113,9 @@ export const AppearanceSettings = () => {
</RadioButtonGroup>
</SettingRow>
) : null}
</Wrapper>
</SettingWrapper>
{IS_EXHIBITION ? (
<Wrapper title={t['Date']()}>
<SettingWrapper title={t['Date']()}>
<SettingRow
name={t['Date Format']()}
desc={t['Customize your date style.']()}
@@ -134,11 +133,11 @@ export const AppearanceSettings = () => {
onChange={checked => changeSwitch('startWeekOnMonday', checked)}
/>
</SettingRow>
</Wrapper>
</SettingWrapper>
) : null}
{isDesktop ? (
<Wrapper title={t['Sidebar']()}>
{environment.isDesktop ? (
<SettingWrapper title={t['Sidebar']()}>
<SettingRow
name={t['Disable the noise background on the sidebar']()}
desc={t['None yet']()}
@@ -161,7 +160,7 @@ export const AppearanceSettings = () => {
}
/>
</SettingRow>
</Wrapper>
</SettingWrapper>
) : null}
</>
);
@@ -3,7 +3,7 @@ import { style } from '@vanilla-extract/css';
export const settingWrapper = style({
flexGrow: 1,
display: 'flex',
width: '50%',
justifyContent: 'flex-end',
minWidth: '150px',
maxWidth: '250px',
});
@@ -1,3 +1,5 @@
import { SettingHeader } from '@affine/component/setting-components';
import { SettingWrapper } from '@affine/component/setting-components';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import {
@@ -6,8 +8,6 @@ import {
useMarkdownShortcuts,
usePageShortcuts,
} from '../../../../../hooks/affine/use-shortcuts';
import { SettingHeader } from '../../common/setting-header';
import { Wrapper } from '../../common/wrapper';
import { shortcutRow } from './style.css';
export const Shortcuts = () => {
@@ -24,7 +24,7 @@ export const Shortcuts = () => {
title={t['Keyboard Shortcuts']()}
subtitle={t['Check Keyboard Shortcuts quickly']()}
/>
<Wrapper title={t['General']()}>
<SettingWrapper title={t['General']()}>
{Object.entries(generalShortcuts).map(([title, shortcuts]) => {
return (
<div key={title} className={shortcutRow}>
@@ -33,8 +33,8 @@ export const Shortcuts = () => {
</div>
);
})}
</Wrapper>
<Wrapper title={t['Page']()}>
</SettingWrapper>
<SettingWrapper title={t['Page']()}>
{Object.entries(pageShortcuts).map(([title, shortcuts]) => {
return (
<div key={title} className={shortcutRow}>
@@ -43,8 +43,8 @@ export const Shortcuts = () => {
</div>
);
})}
</Wrapper>
<Wrapper title={t['Edgeless']()}>
</SettingWrapper>
<SettingWrapper title={t['Edgeless']()}>
{Object.entries(edgelessShortcuts).map(([title, shortcuts]) => {
return (
<div key={title} className={shortcutRow}>
@@ -53,8 +53,8 @@ export const Shortcuts = () => {
</div>
);
})}
</Wrapper>
<Wrapper title={t['Markdown Syntax']()}>
</SettingWrapper>
<SettingWrapper title={t['Markdown Syntax']()}>
{Object.entries(markdownShortcuts).map(([title, shortcuts]) => {
return (
<div key={title} className={shortcutRow}>
@@ -63,7 +63,7 @@ export const Shortcuts = () => {
</div>
);
})}
</Wrapper>
</SettingWrapper>
</>
);
};
@@ -1,4 +1,7 @@
import { Modal, ModalCloseButton, ModalWrapper } from '@affine/component';
import {
SettingModal as SettingModalBase,
type SettingModalProps,
} from '@affine/component/setting-components';
import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
@@ -6,13 +9,11 @@ import type {
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { ContactWithUsIcon } from '@blocksuite/icons';
import type { NextRouter } from 'next/router';
import type React from 'react';
import { useCallback, useMemo, useState } from 'react';
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
import { useWorkspaces } from '../../../hooks/use-workspaces';
import type { BlockSuiteWorkspace } from '../../../shared';
import { AccountSetting } from './account-setting';
import {
GeneralSetting,
@@ -24,15 +25,7 @@ import { settingContent } from './style.css';
import type { Workspace } from './type';
import { WorkSpaceSetting } from './workspace-setting';
export type QuickSearchModalProps = {
currentWorkspace?: BlockSuiteWorkspace;
workspaceList?: BlockSuiteWorkspace[];
open: boolean;
setOpen: (value: boolean) => void;
router: NextRouter;
};
export const SettingModal: React.FC<QuickSearchModalProps> = ({
export const SettingModal: React.FC<SettingModalProps> = ({
open,
setOpen,
}) => {
@@ -55,9 +48,6 @@ export const SettingModal: React.FC<QuickSearchModalProps> = ({
generalKey: generalSettingList[0].key,
isAccount: false,
});
const handleClose = useCallback(() => {
setOpen(false);
}, [setOpen]);
const onGeneralSettingClick = useCallback((key: GeneralSettingKeys) => {
setCurrentRef({
@@ -82,59 +72,41 @@ export const SettingModal: React.FC<QuickSearchModalProps> = ({
}, []);
return (
<Modal
open={open}
onClose={handleClose}
wrapperPosition={['center', 'center']}
data-testid="setting-modal"
>
<ModalWrapper
width={1080}
height={760}
style={{
maxHeight: '85vh',
maxWidth: '70vw',
overflow: 'hidden',
display: 'flex',
}}
>
<ModalCloseButton top={16} right={20} onClick={handleClose} />
<SettingModalBase open={open} setOpen={setOpen}>
<SettingSidebar
generalSettingList={generalSettingList}
onGeneralSettingClick={onGeneralSettingClick}
currentWorkspace={
currentWorkspace as AffineLegacyCloudWorkspace | LocalWorkspace
}
workspaceList={workspaceList}
onWorkspaceSettingClick={onWorkspaceSettingClick}
selectedGeneralKey={currentRef.generalKey}
selectedWorkspace={currentRef.workspace}
onAccountSettingClick={onAccountSettingClick}
/>
<SettingSidebar
generalSettingList={generalSettingList}
onGeneralSettingClick={onGeneralSettingClick}
currentWorkspace={
currentWorkspace as AffineLegacyCloudWorkspace | LocalWorkspace
}
workspaceList={workspaceList}
onWorkspaceSettingClick={onWorkspaceSettingClick}
selectedGeneralKey={currentRef.generalKey}
selectedWorkspace={currentRef.workspace}
onAccountSettingClick={onAccountSettingClick}
/>
<div className={settingContent}>
<div className="wrapper">
<div className="content">
{currentRef.workspace ? (
<WorkSpaceSetting workspace={currentRef.workspace} />
) : null}
{currentRef.generalKey ? (
<GeneralSetting generalKey={currentRef.generalKey} />
) : null}
{currentRef.isAccount ? <AccountSetting /> : null}
</div>
<div className="footer">
<ContactWithUsIcon />
<a href="https://community.affine.pro/home" target="_blank">
{t[
'Need more customization options? You can suggest them to us in the community.'
]()}
</a>
</div>
<div className={settingContent}>
<div className="wrapper">
<div className="content">
{currentRef.workspace ? (
<WorkSpaceSetting workspace={currentRef.workspace} />
) : null}
{currentRef.generalKey ? (
<GeneralSetting generalKey={currentRef.generalKey} />
) : null}
{currentRef.isAccount ? <AccountSetting /> : null}
</div>
<div className="footer">
<ContactWithUsIcon />
<a href="https://community.affine.pro/home" target="_blank">
{t[
'Need more customization options? You can suggest them to us in the community.'
]()}
</a>
</div>
</div>
</ModalWrapper>
</Modal>
</div>
</SettingModalBase>
);
};
@@ -1,3 +1,4 @@
import { UserAvatar } from '@affine/component/user-avatar';
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
import type {
AffineLegacyCloudWorkspace,
@@ -5,6 +6,7 @@ import type {
} from '@affine/env/workspace';
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
import clsx from 'clsx';
import React from 'react';
import type {
GeneralSettingKeys,
@@ -84,7 +86,13 @@ export const SettingSidebar = ({
</div>
<div className={accountButton} onClick={onAccountSettingClick}>
<div className="avatar"></div>
<UserAvatar
size={28}
name="Account NameAccount Name"
url={''}
className="avatar"
/>
<div className="content">
<div className="name" title="xxx">
Account NameAccount Name
@@ -3,9 +3,7 @@ import { globalStyle, style } from '@vanilla-extract/css';
export const settingSlideBar = style({
width: '25%',
maxWidth: '242px',
// TODO: use color variable
// background: 'var(--affine-background-secondary-color)',
backgroundColor: '#F4F4F5',
background: 'var(--affine-background-secondary-color)',
padding: '20px 16px',
height: '100%',
flexShrink: 0,
@@ -107,14 +105,9 @@ export const accountButton = style({
});
globalStyle(`${accountButton} .avatar`, {
width: '28px',
height: '28px',
border: '1px solid',
borderColor: 'var(--affine-white)',
borderRadius: '14px',
flexShrink: '0',
marginRight: '10px',
background: 'red',
});
globalStyle(`${accountButton} .content`, {
flexGrow: '1',