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 GitHub
parent aabac9e921
commit db40cd35c6
33 changed files with 1540 additions and 141 deletions

View File

@@ -0,0 +1,4 @@
export { SettingModal, type SettingModalProps } from './modal';
export { SettingHeader } from './setting-header';
export { SettingRow } from './setting-row';
export { SettingWrapper } from './wrapper';

View File

@@ -0,0 +1,42 @@
import { Modal, ModalCloseButton, ModalWrapper } from '@affine/component';
import type { FC, PropsWithChildren } from 'react';
import { useCallback } from 'react';
export type SettingModalProps = {
open: boolean;
setOpen: (value: boolean) => void;
};
export const SettingModal: FC<PropsWithChildren<SettingModalProps>> = ({
children,
open,
setOpen,
}) => {
const handleClose = useCallback(() => {
setOpen(false);
}, [setOpen]);
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',
backgroundColor: 'var(--affine-white)',
}}
>
<ModalCloseButton top={16} right={20} onClick={handleClose} />
{children}
</ModalWrapper>
</Modal>
);
};

View File

@@ -0,0 +1,14 @@
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>
);
};

View File

@@ -0,0 +1,30 @@
import clsx from 'clsx';
import type { CSSProperties, FC, PropsWithChildren, ReactElement } from 'react';
import { settingRow } from './share.css';
export const SettingRow: FC<
PropsWithChildren<{
name: string | ReactElement;
desc: string | ReactElement;
style?: CSSProperties;
onClick?: () => void;
spreadCol?: boolean;
}>
> = ({ name, desc, children, onClick, style, spreadCol = true }) => {
return (
<div
className={clsx(settingRow, {
'two-col': spreadCol,
})}
style={style}
onClick={onClick}
>
<div className="left-col">
<div className="name">{name}</div>
<div className="desc">{desc}</div>
</div>
{spreadCol ? <div className="right-col">{children}</div> : children}
</div>
);
};

View File

@@ -0,0 +1,82 @@
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({
marginBottom: '25px',
color: 'var(--affine-text-primary-color)',
borderRadius: '8px',
selectors: {
'&.two-col': {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
},
'&:last-of-type': {
marginBottom: '0',
},
},
});
globalStyle(`${settingRow} .left-col`, {
flexShrink: 0,
maxWidth: '100%',
});
globalStyle(`${settingRow}.two-col .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',
flexShrink: 0,
});

View File

@@ -0,0 +1,15 @@
import type { FC, PropsWithChildren } from 'react';
import { wrapper } from './share.css';
export const SettingWrapper: FC<
PropsWithChildren<{
title?: string;
}>
> = ({ title, children }) => {
return (
<div className={wrapper}>
{title ? <div className="title">{title}</div> : null}
{children}
</div>
);
};

View File

@@ -0,0 +1,37 @@
import * as Avatar from '@radix-ui/react-avatar';
import clsx from 'clsx';
import type { CSSProperties, FC } from 'react';
import * as style from './style.css';
export type UserAvatar = {
size?: number;
url?: string;
name?: string;
className?: string;
style?: CSSProperties;
};
export const UserAvatar: FC<UserAvatar> = ({
size = 20,
style: propsStyles = {},
url,
name,
className,
}) => {
return (
<Avatar.Root
style={{
width: size,
height: size,
...propsStyles,
}}
className={clsx(style.avatarRoot, className)}
>
<Avatar.Image className={style.avatarImage} src={url} alt={name} />
<Avatar.Fallback className={style.avatarFallback} delayMs={600}>
{name?.slice(0, 1) || 'A'}
</Avatar.Fallback>
</Avatar.Root>
);
};

View File

@@ -0,0 +1,31 @@
import { style } from '@vanilla-extract/css';
export const avatarRoot = style({
display: 'inline-flex',
flexShrink: 0,
alignItems: 'center',
justifyContent: 'center',
verticalAlign: 'middle',
overflow: 'hidden',
userSelect: 'none',
borderRadius: '100%',
});
export const avatarImage = style({
width: '100%',
height: '100%',
objectFit: 'cover',
borderRadius: 'inherit',
});
export const avatarFallback = style({
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'var(--affine-primary-color)',
color: 'var(--affine-white)',
fontSize: 'var(--affine-font-base)',
lineHeight: '1',
fontWeight: '500',
});

View File

@@ -10,14 +10,14 @@ export const SIZE_CONFIG = {
fontSize: 16,
borderRadius: 4,
height: 26,
padding: 24,
padding: 6,
},
[SIZE_MIDDLE]: {
iconSize: 20,
fontSize: 16,
borderRadius: 4,
height: 32,
padding: 24,
padding: 12,
},
[SIZE_DEFAULT]: {
iconSize: 24,