mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
feat: modify pivot style & add operation menu to pivot item (#1726)
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
|
||||
import { StyledCollapseItem } from '../shared-styles';
|
||||
|
||||
export const EmptyItem = () => {
|
||||
const { t } = useTranslation();
|
||||
return <StyledCollapseItem disable={true}>{t('No item')}</StyledCollapseItem>;
|
||||
};
|
||||
|
||||
export default EmptyItem;
|
||||
@@ -1,5 +1,4 @@
|
||||
import { MuiCollapse } from '@affine/component';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { EdgelessIcon, PageIcon } from '@blocksuite/icons';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useRouter } from 'next/router';
|
||||
@@ -8,13 +7,13 @@ import { useMemo } from 'react';
|
||||
import { workspacePreferredModeAtom } from '../../../../atoms';
|
||||
import type { FavoriteListProps } from '../index';
|
||||
import { StyledCollapseItem } from '../shared-styles';
|
||||
import EmptyItem from './empty-item';
|
||||
export const FavoriteList = ({
|
||||
pageMeta,
|
||||
openPage,
|
||||
showList,
|
||||
}: FavoriteListProps) => {
|
||||
const router = useRouter();
|
||||
const { t } = useTranslation();
|
||||
const record = useAtomValue(workspacePreferredModeAtom);
|
||||
|
||||
const favoriteList = useMemo(
|
||||
@@ -60,9 +59,7 @@ export const FavoriteList = ({
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{favoriteList.length === 0 && (
|
||||
<StyledCollapseItem disable={true}>{t('No item')}</StyledCollapseItem>
|
||||
)}
|
||||
{favoriteList.length === 0 && <EmptyItem />}
|
||||
</MuiCollapse>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import {
|
||||
IconButton,
|
||||
MenuItem,
|
||||
MuiClickAwayListener,
|
||||
PureMenu,
|
||||
} from '@affine/component';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import {
|
||||
CopyIcon,
|
||||
DeleteTemporarilyIcon,
|
||||
MoreVerticalIcon,
|
||||
MoveToIcon,
|
||||
PenIcon,
|
||||
PlusIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { toast } from '../../../../utils';
|
||||
|
||||
export const OperationButton = ({
|
||||
onAdd,
|
||||
onDelete,
|
||||
}: {
|
||||
onAdd: () => void;
|
||||
onDelete: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const copyUrl = useCallback(() => {
|
||||
const workspaceId = router.query.workspaceId;
|
||||
navigator.clipboard.writeText(window.location.href);
|
||||
toast(t('Copied link to clipboard'));
|
||||
}, [router.query.workspaceId, t]);
|
||||
|
||||
return (
|
||||
<MuiClickAwayListener
|
||||
onClickAway={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
ref={ref => setAnchorEl(ref)}
|
||||
size="small"
|
||||
className="operation-button"
|
||||
onClick={event => {
|
||||
event.stopPropagation();
|
||||
setOpen(!open);
|
||||
}}
|
||||
>
|
||||
<MoreVerticalIcon />
|
||||
</IconButton>
|
||||
<PureMenu
|
||||
anchorEl={anchorEl}
|
||||
placement="bottom-start"
|
||||
open={open && anchorEl !== null}
|
||||
zIndex={11111}
|
||||
>
|
||||
<MenuItem
|
||||
icon={<PlusIcon />}
|
||||
onClick={() => {
|
||||
onAdd();
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
{t('Add a subpage inside')}
|
||||
</MenuItem>
|
||||
<MenuItem icon={<MoveToIcon />} disabled={true}>
|
||||
{t('Move to')}
|
||||
</MenuItem>
|
||||
<MenuItem icon={<PenIcon />} disabled={true}>
|
||||
{t('Rename')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={<DeleteTemporarilyIcon />}
|
||||
onClick={() => {
|
||||
onDelete();
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
{t('Move to Trash')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={<CopyIcon />}
|
||||
disabled={true}
|
||||
// onClick={() => {
|
||||
// const workspaceId = router.query.workspaceId;
|
||||
// navigator.clipboard.writeText(window.location.href);
|
||||
// toast(t('Copied link to clipboard'));
|
||||
// }}
|
||||
>
|
||||
{t('Copy Link')}
|
||||
</MenuItem>
|
||||
</PureMenu>
|
||||
</div>
|
||||
</MuiClickAwayListener>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MuiCollapse, TreeView } from '@affine/component';
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { ArrowDownSmallIcon, FolderIcon } from '@blocksuite/icons';
|
||||
import { ArrowDownSmallIcon, PivotsIcon } from '@blocksuite/icons';
|
||||
import type { PageMeta } from '@blocksuite/store';
|
||||
import { nanoid } from '@blocksuite/store';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
@@ -9,6 +9,7 @@ import { useCallback, useMemo, useState } from 'react';
|
||||
import { useBlockSuiteWorkspaceHelper } from '../../../../hooks/use-blocksuite-workspace-helper';
|
||||
import { usePageMetaHelper } from '../../../../hooks/use-page-meta';
|
||||
import type { RemWorkspace } from '../../../../shared';
|
||||
import EmptyItem from '../favorite/empty-item';
|
||||
import { StyledCollapseButton, StyledListItem } from '../shared-styles';
|
||||
import type { TreeNode } from './types';
|
||||
import { flattenToTree } from './utils';
|
||||
@@ -197,6 +198,11 @@ export const Pivot = ({
|
||||
|
||||
const [showPivot, setShowPivot] = useState(true);
|
||||
|
||||
const isPivotEmpty = useMemo(
|
||||
() => allMetas.filter(meta => !meta.trash).length === 0,
|
||||
[allMetas]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledListItem>
|
||||
@@ -208,7 +214,7 @@ export const Pivot = ({
|
||||
>
|
||||
<ArrowDownSmallIcon />
|
||||
</StyledCollapseButton>
|
||||
<FolderIcon />
|
||||
<PivotsIcon />
|
||||
{t('Pivots')}
|
||||
</StyledListItem>
|
||||
|
||||
@@ -220,11 +226,15 @@ export const Pivot = ({
|
||||
overflowY: 'auto',
|
||||
}}
|
||||
>
|
||||
<PivotInternal
|
||||
currentWorkspace={currentWorkspace}
|
||||
openPage={openPage}
|
||||
allMetas={allMetas}
|
||||
/>
|
||||
{isPivotEmpty ? (
|
||||
<EmptyItem />
|
||||
) : (
|
||||
<PivotInternal
|
||||
currentWorkspace={currentWorkspace}
|
||||
openPage={openPage}
|
||||
allMetas={allMetas}
|
||||
/>
|
||||
)}
|
||||
</MuiCollapse>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
import { IconButton } from '@affine/component';
|
||||
import {
|
||||
ArrowDownSmallIcon,
|
||||
EdgelessIcon,
|
||||
// DeleteTemporarilyIcon,
|
||||
// PlusIcon,
|
||||
MoreVerticalIcon,
|
||||
PageIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import { ArrowDownSmallIcon, EdgelessIcon, PageIcon } from '@blocksuite/icons';
|
||||
import type { PageMeta } from '@blocksuite/store';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
import { workspacePreferredModeAtom } from '../../../../atoms';
|
||||
import { StyledCollapseButton, StyledCollapseItem } from '../shared-styles';
|
||||
import { OperationButton } from './OperationButton';
|
||||
import type { TreeNode } from './types';
|
||||
|
||||
export const TreeNodeRender: TreeNode['render'] = (
|
||||
node,
|
||||
{ onAdd, onDelete, collapsed, setCollapsed },
|
||||
{ isOver, onAdd, onDelete, collapsed, setCollapsed },
|
||||
extendProps
|
||||
) => {
|
||||
const { openPage, pageMeta } = extendProps as {
|
||||
@@ -37,6 +30,7 @@ export const TreeNodeRender: TreeNode['render'] = (
|
||||
}
|
||||
openPage(node.id);
|
||||
}}
|
||||
isOver={isOver}
|
||||
active={active}
|
||||
>
|
||||
<StyledCollapseButton
|
||||
@@ -51,37 +45,7 @@ export const TreeNodeRender: TreeNode['render'] = (
|
||||
</StyledCollapseButton>
|
||||
{record[pageMeta.id] === 'edgeless' ? <EdgelessIcon /> : <PageIcon />}
|
||||
<span>{node.title || 'Untitled'}</span>
|
||||
<IconButton
|
||||
size="small"
|
||||
className="operation-button"
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MoreVerticalIcon />
|
||||
</IconButton>
|
||||
|
||||
{/*<IconButton*/}
|
||||
{/* onClick={e => {*/}
|
||||
{/* e.stopPropagation();*/}
|
||||
{/* onAdd();*/}
|
||||
{/* }}*/}
|
||||
{/* size="small"*/}
|
||||
{/* className="operation-button"*/}
|
||||
{/*>*/}
|
||||
{/* <PlusIcon />*/}
|
||||
{/*</IconButton>*/}
|
||||
{/*<IconButton*/}
|
||||
{/* onClick={e => {*/}
|
||||
{/* e.stopPropagation();*/}
|
||||
|
||||
{/* onDelete();*/}
|
||||
{/* }}*/}
|
||||
{/* size="small"*/}
|
||||
{/* className="operation-button"*/}
|
||||
{/*>*/}
|
||||
{/* <DeleteTemporarilyIcon />*/}
|
||||
{/*</IconButton>*/}
|
||||
<OperationButton onAdd={onAdd} onDelete={onDelete} />
|
||||
</StyledCollapseItem>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { displayFlex, styled, textEllipsis } from '@affine/component';
|
||||
import { alpha, displayFlex, styled, textEllipsis } from '@affine/component';
|
||||
|
||||
export const StyledListItem = styled('div')<{
|
||||
active?: boolean;
|
||||
@@ -53,10 +53,11 @@ export const StyledCollapseButton = styled('button')<{
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledCollapseItem = styled('button')<{
|
||||
export const StyledCollapseItem = styled('div')<{
|
||||
disable?: boolean;
|
||||
active?: boolean;
|
||||
}>(({ disable = false, active = false, theme }) => {
|
||||
isOver?: boolean;
|
||||
}>(({ disable = false, active = false, theme, isOver }) => {
|
||||
return {
|
||||
width: '100%',
|
||||
height: '32px',
|
||||
@@ -70,6 +71,7 @@ export const StyledCollapseItem = styled('button')<{
|
||||
? theme.colors.primaryColor
|
||||
: theme.colors.textColor,
|
||||
cursor: disable ? 'not-allowed' : 'pointer',
|
||||
background: isOver ? alpha(theme.colors.primaryColor, 0.06) : '',
|
||||
|
||||
span: {
|
||||
flexGrow: '1',
|
||||
@@ -83,7 +85,7 @@ export const StyledCollapseItem = styled('button')<{
|
||||
color: active ? theme.colors.primaryColor : theme.colors.iconColor,
|
||||
},
|
||||
'.operation-button': {
|
||||
display: 'none',
|
||||
visibility: 'hidden',
|
||||
},
|
||||
|
||||
':hover': disable
|
||||
@@ -91,7 +93,7 @@ export const StyledCollapseItem = styled('button')<{
|
||||
: {
|
||||
backgroundColor: theme.colors.hoverBackground,
|
||||
'.operation-button': {
|
||||
display: 'flex',
|
||||
visibility: 'visible',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ export const StyledSliderBar = styled('div')<{ show: boolean }>(
|
||||
flexShrink: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
overflow: 'hidden',
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user