style: move trash button group to page bottom (#3352)

This commit is contained in:
JimmFly
2023-07-25 13:21:16 +08:00
committed by GitHub
parent be81e63eed
commit e3f66d7e22
12 changed files with 136 additions and 103 deletions

View File

@@ -43,6 +43,9 @@ export const EditorModeSwitch = ({
assertExists(pageMeta);
const { trash } = pageMeta;
useEffect(() => {
if (trash) {
return;
}
const keydown = (e: KeyboardEvent) => {
if (
!environment.isServer && environment.isMacOs
@@ -64,7 +67,7 @@ export const EditorModeSwitch = ({
document.addEventListener('keydown', keydown, { capture: true });
return () =>
document.removeEventListener('keydown', keydown, { capture: true });
}, [setSetting, t]);
}, [setSetting, t, trash]);
return (
<Tooltip content={<TooltipContent />}>
@@ -77,6 +80,7 @@ export const EditorModeSwitch = ({
data-testid="switch-page-mode-button"
active={currentMode === 'page'}
hide={trash && currentMode !== 'page'}
trash={trash}
onClick={() => {
setSetting(setting => {
if (setting?.mode !== 'page') {
@@ -90,6 +94,7 @@ export const EditorModeSwitch = ({
data-testid="switch-edgeless-mode-button"
active={currentMode === 'edgeless'}
hide={trash && currentMode !== 'edgeless'}
trash={trash}
onClick={() => {
setSetting(setting => {
if (setting?.mode !== 'edgeless') {

View File

@@ -34,14 +34,19 @@ export const StyledEditorModeSwitch = styled('div')<{
export const StyledSwitchItem = styled('button')<{
active?: boolean;
hide?: boolean;
}>(({ active = false, hide = false }) => {
trash?: boolean;
}>(({ active = false, hide = false, trash = false }) => {
return {
width: '24px',
height: '24px',
borderRadius: '8px',
WebkitAppRegion: 'no-drag',
boxShadow: active ? 'var(--affine-shadow-1)' : 'none',
color: active ? 'var(--affine-primary-color)' : 'var(--affine-icon-color)',
color: active
? trash
? 'var(--affine-error-color)'
: 'var(--affine-primary-color)'
: 'var(--affine-icon-color)',
display: hide ? 'none' : 'inline-flex',
alignItems: 'center',
justifyContent: 'center',

View File

@@ -8,12 +8,14 @@ import { StyledSwitchItem } from './style';
type HoverAnimateControllerProps = {
active?: boolean;
hide?: boolean;
trash?: boolean;
children: React.ReactElement;
} & HTMLAttributes<HTMLButtonElement>;
const HoverAnimateController = ({
active,
hide,
trash,
children,
...props
}: HoverAnimateControllerProps) => {
@@ -22,6 +24,7 @@ const HoverAnimateController = ({
<StyledSwitchItem
hide={hide}
active={active}
trash={trash}
onMouseEnter={() => {
setStartAnimate(true);
}}

View File

@@ -0,0 +1,15 @@
import { style } from '@vanilla-extract/css';
export const group = style({
width: '100%',
position: 'absolute',
bottom: '100px',
left: '0',
display: 'flex',
gap: '24px',
justifyContent: 'center',
});
export const buttonContainer = style({
boxShadow: 'var(--affine-float-button-shadow-2)',
borderRadius: '8px',
});

View File

@@ -10,7 +10,7 @@ import { useCallback, useState } from 'react';
import { useBlockSuiteMetaHelper } from '../../../../hooks/affine/use-block-suite-meta-helper';
import { useCurrentWorkspace } from '../../../../hooks/current/use-current-workspace';
import { useNavigateHelper } from '../../../../hooks/use-navigate-helper';
import { buttonContainer, group } from './styles.css';
export const TrashButtonGroup = () => {
// fixme(himself65): remove these hooks ASAP
const [workspace] = useCurrentWorkspace();
@@ -29,25 +29,29 @@ export const TrashButtonGroup = () => {
const [open, setOpen] = useState(false);
return (
<>
<Button
shape="round"
style={{ marginRight: '24px' }}
onClick={() => {
restoreFromTrash(pageId);
}}
>
{t['Restore it']()}
</Button>
<Button
shape="round"
type="error"
onClick={() => {
setOpen(true);
}}
>
{t['Delete permanently']()}
</Button>
<div className={group}>
<div className={buttonContainer}>
<Button
type="processing"
onClick={() => {
restoreFromTrash(pageId);
}}
size="large"
>
{t['Restore it']()}
</Button>
</div>
<div className={buttonContainer}>
<Button
type="error"
onClick={() => {
setOpen(true);
}}
size="large"
>
{t['Delete permanently']()}
</Button>
</div>
<Confirm
title={t['TrashButtonGroupTitle']()}
content={t['TrashButtonGroupDescription']()}
@@ -65,7 +69,7 @@ export const TrashButtonGroup = () => {
setOpen(false);
}}
/>
</>
</div>
);
};

View File

@@ -23,7 +23,6 @@ import { currentModeAtom } from '../../../atoms/mode';
import type { AffineOfficialWorkspace } from '../../../shared';
import DownloadClientTip from './download-tips';
import { EditorOptionMenu } from './header-right-items/editor-option-menu';
import TrashButtonGroup from './header-right-items/trash-button-group';
import * as styles from './styles.css';
import { OSWarningMessage, shouldShowWarning } from './utils';
@@ -38,7 +37,6 @@ export type BaseHeaderProps<
export enum HeaderRightItemName {
EditorOptionMenu = 'editorOptionMenu',
TrashButtonGroup = 'trashButtonGroup',
// some windows only items
WindowsAppControls = 'windowsAppControls',
}
@@ -56,16 +54,10 @@ type HeaderItem = {
};
const HeaderRightItems: Record<HeaderRightItemName, HeaderItem> = {
[HeaderRightItemName.TrashButtonGroup]: {
Component: TrashButtonGroup,
availableWhen: (_, currentPage) => {
return currentPage?.meta.trash === true;
},
},
[HeaderRightItemName.EditorOptionMenu]: {
Component: EditorOptionMenu,
availableWhen: (_, currentPage, { isPublic }) => {
return !isPublic;
return !isPublic && currentPage?.meta.trash !== true;
},
},
[HeaderRightItemName.WindowsAppControls]: {

View File

@@ -25,6 +25,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
import { pageSettingFamily } from '../atoms';
import { fontStyleOptions, useAppSetting } from '../atoms/settings';
import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor';
import TrashButtonGroup from './blocksuite/workspace-header/header-right-items/trash-button-group';
import * as styles from './page-detail-editor.css';
import { pluginContainer } from './page-detail-editor.css';
@@ -67,62 +68,65 @@ const EditorWrapper = memo(function EditorWrapper({
}, [appSettings.fontStyle]);
return (
<Editor
className={clsx(styles.editor, {
'full-screen': appSettings.fullWidthLayout,
})}
style={
{
'--affine-font-family': value,
} as CSSProperties
}
key={`${workspace.id}-${pageId}`}
mode={isPublic ? 'page' : currentMode}
page={page}
onInit={useCallback(
(page: Page, editor: Readonly<EditorContainer>) => {
onInit(page, editor);
},
[onInit]
)}
setBlockHub={setBlockHub}
onLoad={useCallback(
(page: Page, editor: EditorContainer) => {
page.workspace.setPageMeta(page.id, {
updatedDate: Date.now(),
});
localStorage.setItem('last_page_id', page.id);
let dispose = () => {};
if (onLoad) {
dispose = onLoad(page, editor);
}
const editorItems = rootStore.get(editorItemsAtom);
let disposes: (() => void)[] = [];
const renderTimeout = setTimeout(() => {
disposes = Object.entries(editorItems).map(([id, editorItem]) => {
const div = document.createElement('div');
div.setAttribute('plugin-id', id);
const cleanup = editorItem(div, editor);
assertExists(parent);
document.body.appendChild(div);
return () => {
cleanup();
document.body.removeChild(div);
};
<>
<Editor
className={clsx(styles.editor, {
'full-screen': appSettings.fullWidthLayout,
})}
style={
{
'--affine-font-family': value,
} as CSSProperties
}
key={`${workspace.id}-${pageId}`}
mode={isPublic ? 'page' : currentMode}
page={page}
onInit={useCallback(
(page: Page, editor: Readonly<EditorContainer>) => {
onInit(page, editor);
},
[onInit]
)}
setBlockHub={setBlockHub}
onLoad={useCallback(
(page: Page, editor: EditorContainer) => {
page.workspace.setPageMeta(page.id, {
updatedDate: Date.now(),
});
localStorage.setItem('last_page_id', page.id);
let dispose = () => {};
if (onLoad) {
dispose = onLoad(page, editor);
}
const editorItems = rootStore.get(editorItemsAtom);
let disposes: (() => void)[] = [];
const renderTimeout = setTimeout(() => {
disposes = Object.entries(editorItems).map(([id, editorItem]) => {
const div = document.createElement('div');
div.setAttribute('plugin-id', id);
const cleanup = editorItem(div, editor);
assertExists(parent);
document.body.appendChild(div);
return () => {
cleanup();
document.body.removeChild(div);
};
});
});
});
return () => {
dispose();
clearTimeout(renderTimeout);
setTimeout(() => {
disposes.forEach(dispose => dispose());
});
};
},
[onLoad]
)}
/>
return () => {
dispose();
clearTimeout(renderTimeout);
setTimeout(() => {
disposes.forEach(dispose => dispose());
});
};
},
[onLoad]
)}
/>
{meta.trash && <TrashButtonGroup />}
</>
);
});

View File

@@ -37,7 +37,7 @@
"@radix-ui/react-toast": "^1.1.4",
"@toeverything/hooks": "workspace:*",
"@toeverything/plugin-infra": "workspace:*",
"@toeverything/theme": "^0.7.7",
"@toeverything/theme": "^0.7.9",
"@vanilla-extract/dynamic": "^2.0.3",
"clsx": "^2.0.0",
"dayjs": "^1.11.9",

View File

@@ -70,7 +70,7 @@ export const button = style({
color: 'var(--affine-white)',
background: 'var(--affine-primary-color)',
borderColor: 'var(--affine-black-10)',
boxShadow: '0px 1px 2px 0px rgba(255, 255, 255, 0.25) inset',
boxShadow: 'var(--affine-button-inner-shadow)',
},
'&.primary:hover': {
background:
@@ -85,10 +85,10 @@ export const button = style({
},
'&.error': {
color: 'var(--affine-white)',
color: 'var(--affine-pure-white)',
background: 'var(--affine-error-color)',
borderColor: 'var(--affine-black-10)',
boxShadow: '0px 1px 2px 0px rgba(255, 255, 255, 0.25) inset',
boxShadow: 'var(--affine-button-inner-shadow)',
},
'&.error:hover': {
background:
@@ -106,7 +106,7 @@ export const button = style({
color: 'var(--affine-white)',
background: 'var(--affine-warning-color)',
borderColor: 'var(--affine-black-10)',
boxShadow: '0px 1px 2px 0px rgba(255, 255, 255, 0.25) inset',
boxShadow: 'var(--affine-button-inner-shadow)',
},
'&.warning:hover': {
background:
@@ -121,10 +121,10 @@ export const button = style({
},
'&.success': {
color: 'var(--affine-white)',
color: 'var(--affine-pure-white)',
background: 'var(--affine-success-color)',
borderColor: 'var(--affine-black-10)',
boxShadow: '0px 1px 2px 0px rgba(255, 255, 255, 0.25) inset',
boxShadow: 'var(--affine-button-inner-shadow)',
},
'&.success:hover': {
background:
@@ -139,10 +139,10 @@ export const button = style({
},
'&.processing': {
color: 'var(--affine-white)',
color: 'var(--affine-pure-white)',
background: 'var(--affine-processing-color)',
borderColor: 'var(--affine-black-10)',
boxShadow: '0px 1px 2px 0px rgba(255, 255, 255, 0.25) inset',
boxShadow: 'var(--affine-button-inner-shadow)',
},
'&.processing:hover': {
background:

View File

@@ -52,10 +52,10 @@ export const Confirm = ({
{buttonDirection === 'row' ? (
<StyledRowButtonWrapper>
<Button
shape="round"
onClick={() => {
onCancel?.();
}}
size="large"
style={{ marginRight: '24px' }}
data-testid={cancelButtonTestId}
>
@@ -63,10 +63,10 @@ export const Confirm = ({
</Button>
<Button
type={confirmType}
shape="round"
onClick={() => {
onConfirm?.();
}}
size="large"
data-testid={confirmButtonTestId}
>
{confirmText}
@@ -76,7 +76,6 @@ export const Confirm = ({
<StyledColumnButtonWrapper>
<Button
type={confirmType}
shape="round"
onClick={() => {
onConfirm?.();
}}
@@ -86,7 +85,6 @@ export const Confirm = ({
{confirmText}
</Button>
<Button
shape="round"
onClick={() => {
onCancel?.();
}}

View File

@@ -11,7 +11,7 @@ export const ModalWrapper = styled('div')<{
width,
height,
minHeight,
backgroundColor: 'var(--affine-background-secondary-color)',
backgroundColor: 'var(--affine-background-overlay-panel-color)',
boxShadow: 'var(--affine-shadow-3)',
borderRadius: '12px',
position: 'relative',

View File

@@ -132,7 +132,7 @@ __metadata:
"@radix-ui/react-toast": ^1.1.4
"@toeverything/hooks": "workspace:*"
"@toeverything/plugin-infra": "workspace:*"
"@toeverything/theme": ^0.7.7
"@toeverything/theme": ^0.7.9
"@types/react": ^18.2.15
"@types/react-datepicker": ^4.11.2
"@types/react-dnd": ^3.0.2
@@ -10977,13 +10977,20 @@ __metadata:
languageName: unknown
linkType: soft
"@toeverything/theme@npm:0.7.7, @toeverything/theme@npm:^0.7.7":
"@toeverything/theme@npm:0.7.7":
version: 0.7.7
resolution: "@toeverything/theme@npm:0.7.7"
checksum: 5a449eb440c49c712069203d85acc73613a000324807ce2e42c3b441b74b74e54ba76292144b60e3900d54bf41a13f98923174fee527c20303ad6c68e26e6176
languageName: node
linkType: hard
"@toeverything/theme@npm:^0.7.9":
version: 0.7.9
resolution: "@toeverything/theme@npm:0.7.9"
checksum: ac7eeea49f9099e34e8aacbd327ef5e48cc9fc02c32a20309da3dbcb4363c8dda3d2c887cf0e8eb8bb0fa2c50e73f123332f7009d2926961ef7ecbbb921a856d
languageName: node
linkType: hard
"@toeverything/y-indexeddb@workspace:*, @toeverything/y-indexeddb@workspace:packages/y-indexeddb":
version: 0.0.0-use.local
resolution: "@toeverything/y-indexeddb@workspace:packages/y-indexeddb"