fix(core): adjust sidebar explorer empty status (#7657)

Close AF-1126,AF-1132
This commit is contained in:
CatsJuice
2024-07-31 02:41:53 +00:00
parent 083123cdfb
commit ede576061d
15 changed files with 116 additions and 238 deletions

View File

@@ -1,4 +1,5 @@
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { globalStyle, style } from '@vanilla-extract/css';
export const dropdownBtn = style({
display: 'inline-flex',
@@ -124,8 +125,8 @@ export const button = style({
// changeable
height: '28px',
background: cssVar('white'),
borderColor: cssVar('borderColor'),
color: cssVar('textPrimaryColor'),
borderColor: cssVarV2('layer/border'),
color: cssVarV2('text/primary'),
selectors: {
'&.text-bold': {
fontWeight: 600,

View File

@@ -1,4 +1,5 @@
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';
export const content = style({
@@ -6,8 +7,8 @@ export const content = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 6,
padding: '9px 20px 25px 21px',
gap: 4,
padding: '12px 0px',
});
export const iconWrapper = style({
width: 36,
@@ -16,21 +17,24 @@ export const iconWrapper = style({
alignItems: 'center',
justifyContent: 'center',
borderRadius: '50%',
backgroundColor: cssVar('hoverColor'),
backgroundColor: cssVarV2('button/emptyIconBackground'),
});
export const icon = style({
fontSize: 20,
color: cssVar('iconSecondary'),
color: cssVarV2('icon/secondary'),
});
export const message = style({
fontSize: cssVar('fontSm'),
textAlign: 'center',
color: cssVar('black30'),
color: cssVarV2('text/tertiary'),
userSelect: 'none',
fontWeight: 400,
lineHeight: '22px',
});
export const newButton = style({
padding: '0 8px',
height: '28px',
fontSize: cssVar('fontXs'),
marginTop: 8,
padding: '4px 8px',
height: '30px',
fontSize: cssVar('fontSm'),
});

View File

@@ -0,0 +1,49 @@
import { Button } from '@affine/component';
import clsx from 'clsx';
import {
forwardRef,
type HTMLAttributes,
type Ref,
type SVGProps,
} from 'react';
import * as styles from './empty-layout.css';
interface ExplorerGroupEmptyProps extends HTMLAttributes<HTMLDivElement> {
icon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
message: string;
messageTestId?: string;
actionText?: string;
onActionClick?: () => void;
}
export const ExplorerGroupEmpty = forwardRef(function ExplorerGroupEmpty(
{
icon: Icon,
message,
messageTestId,
actionText,
children,
className,
onActionClick,
...attrs
}: ExplorerGroupEmptyProps,
ref: Ref<HTMLDivElement>
) {
return (
<div className={clsx(styles.content, className)} ref={ref} {...attrs}>
<div className={styles.iconWrapper}>
<Icon className={styles.icon} />
</div>
<div data-testid={messageTestId} className={styles.message}>
{message}
</div>
{actionText ? (
<Button className={styles.newButton} onClick={onActionClick}>
{actionText}
</Button>
) : null}
{children}
</div>
);
});

View File

@@ -1,39 +1,6 @@
import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const content = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 6,
padding: '9px 20px 25px 21px',
});
export const iconWrapper = style({
width: 36,
height: 36,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '50%',
backgroundColor: cssVar('hoverColor'),
});
export const icon = style({
fontSize: 20,
color: cssVar('iconSecondary'),
});
export const message = style({
fontSize: cssVar('fontSm'),
textAlign: 'center',
color: cssVar('black30'),
userSelect: 'none',
});
export const newButton = style({
padding: '0 8px',
height: '28px',
fontSize: cssVar('fontXs'),
});
export const draggedOverHighlight = style({
selectors: {
'&[data-dragged-over="true"]': {

View File

@@ -1,5 +1,4 @@
import {
Button,
type DropTargetDropEvent,
type DropTargetOptions,
useDropTarget,
@@ -9,6 +8,7 @@ import { useI18n } from '@affine/i18n';
import { FolderIcon } from '@blocksuite/icons/rc';
import clsx from 'clsx';
import { ExplorerGroupEmpty } from '../../layouts/empty-layout';
import * as styles from './empty.css';
export const FolderEmpty = ({
@@ -32,22 +32,16 @@ export const FolderEmpty = ({
const t = useI18n();
return (
<div
className={clsx(styles.content, styles.draggedOverHighlight, className)}
<ExplorerGroupEmpty
className={clsx(styles.draggedOverHighlight, className)}
ref={dropTargetRef}
>
<div className={styles.iconWrapper}>
<FolderIcon className={styles.icon} />
</div>
<div
data-testid="slider-bar-organize-empty-message"
className={styles.message}
>
{t['com.affine.rootAppSidebar.organize.empty-folder']()}
</div>
<Button className={styles.newButton} onClick={onClickCreate}>
{t['com.affine.rootAppSidebar.organize.empty-folder.add-pages']()}
</Button>
</div>
icon={FolderIcon}
message={t['com.affine.rootAppSidebar.organize.empty-folder']()}
messageTestId="slider-bar-organize-empty-message"
actionText={t[
'com.affine.rootAppSidebar.organize.empty-folder.add-pages'
]()}
onActionClick={onClickCreate}
/>
);
};

View File

@@ -814,7 +814,11 @@ export const ExplorerFolderNodeFolder = ({
operations={finalOperations}
canDrop={handleCanDrop}
childrenPlaceholder={
<FolderEmpty canDrop={handleCanDrop} onDrop={handleDropOnPlaceholder} />
<FolderEmpty
canDrop={handleCanDrop}
onDrop={handleDropOnPlaceholder}
onClickCreate={() => handleAddToFolder('doc')}
/>
}
dropEffect={handleDropEffect}
data-testid={`explorer-folder-${node.id}`}

View File

@@ -1,35 +0,0 @@
import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const content = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 6,
padding: '9px 20px 25px 21px',
});
export const iconWrapper = style({
width: 36,
height: 36,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '50%',
backgroundColor: cssVar('hoverColor'),
});
export const icon = style({
fontSize: 20,
color: cssVar('iconSecondary'),
});
export const message = style({
fontSize: cssVar('fontSm'),
textAlign: 'center',
color: cssVar('black30'),
userSelect: 'none',
});
export const newButton = style({
padding: '0 8px',
height: '28px',
fontSize: cssVar('fontXs'),
});

View File

@@ -1,8 +1,7 @@
import { Button } from '@affine/component';
import { useI18n } from '@affine/i18n';
import { ViewLayersIcon } from '@blocksuite/icons/rc';
import * as styles from './empty.css';
import { ExplorerGroupEmpty } from '../../layouts/empty-layout';
export const RootEmpty = ({
onClickCreate,
@@ -12,19 +11,12 @@ export const RootEmpty = ({
const t = useI18n();
return (
<div className={styles.content}>
<div className={styles.iconWrapper}>
<ViewLayersIcon className={styles.icon} />
</div>
<div
data-testid="slider-bar-collection-empty-message"
className={styles.message}
>
{t['com.affine.collections.empty.message']()}
</div>
<Button className={styles.newButton} onClick={onClickCreate}>
{t['com.affine.collections.empty.new-collection-button']()}
</Button>
</div>
<ExplorerGroupEmpty
icon={ViewLayersIcon}
message={t['com.affine.collections.empty.message']()}
messageTestId="slider-bar-collection-empty-message"
actionText={t['com.affine.collections.empty.new-collection-button']()}
onActionClick={onClickCreate}
/>
);
};

View File

@@ -5,10 +5,10 @@ import {
} from '@affine/component';
import type { AffineDNDData } from '@affine/core/types/dnd';
import { useI18n } from '@affine/i18n';
import { FolderIcon } from '@blocksuite/icons/rc';
import { FavoriteIcon } from '@blocksuite/icons/rc';
import { ExplorerGroupEmpty } from '../../layouts/empty-layout';
import { DropEffect, type ExplorerTreeNodeDropEffect } from '../../tree';
import * as styles from './empty.css';
export const RootEmpty = ({
onDrop,
@@ -34,16 +34,12 @@ export const RootEmpty = ({
);
return (
<div className={styles.content} ref={dropTargetRef}>
<div className={styles.iconWrapper}>
<FolderIcon className={styles.icon} />
</div>
<div
data-testid="slider-bar-favorites-empty-message"
className={styles.message}
>
{t['com.affine.rootAppSidebar.favorites.empty']()}
</div>
<ExplorerGroupEmpty
ref={dropTargetRef}
icon={FavoriteIcon}
message={t['com.affine.rootAppSidebar.favorites.empty']()}
messageTestId="slider-bar-favorites-empty-message"
>
{dropEffect && draggedOverDraggable && (
<DropEffect
position={{
@@ -56,6 +52,6 @@ export const RootEmpty = ({
})}
/>
)}
</div>
</ExplorerGroupEmpty>
);
};

View File

@@ -1,36 +0,0 @@
import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const content = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 6,
padding: '9px 20px 25px 21px',
position: 'relative',
});
export const iconWrapper = style({
width: 36,
height: 36,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '50%',
backgroundColor: cssVar('hoverColor'),
});
export const icon = style({
fontSize: 20,
color: cssVar('iconSecondary'),
});
export const message = style({
fontSize: cssVar('fontSm'),
textAlign: 'center',
color: cssVar('black30'),
userSelect: 'none',
});
export const newButton = style({
padding: '0 8px',
height: '28px',
fontSize: cssVar('fontXs'),
});

View File

@@ -1,8 +1,7 @@
import { Button } from '@affine/component';
import { useI18n } from '@affine/i18n';
import { FolderIcon } from '@blocksuite/icons/rc';
import * as styles from './empty.css';
import { ExplorerGroupEmpty } from '../../layouts/empty-layout';
export const RootEmpty = ({
onClickCreate,
@@ -12,19 +11,14 @@ export const RootEmpty = ({
const t = useI18n();
return (
<div className={styles.content}>
<div className={styles.iconWrapper}>
<FolderIcon className={styles.icon} />
</div>
<div
data-testid="slider-bar-organize-empty-message"
className={styles.message}
>
{t['com.affine.rootAppSidebar.organize.empty']()}
</div>
<Button className={styles.newButton} onClick={onClickCreate}>
{t['com.affine.rootAppSidebar.organize.empty.new-folders-button']()}
</Button>
</div>
<ExplorerGroupEmpty
icon={FolderIcon}
message={t['com.affine.rootAppSidebar.organize.empty']()}
messageTestId="slider-bar-organize-empty-message"
actionText={t[
'com.affine.rootAppSidebar.organize.empty.new-folders-button'
]()}
onActionClick={onClickCreate}
/>
);
};

View File

@@ -1,36 +0,0 @@
import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const content = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 6,
padding: '9px 20px 25px 21px',
position: 'relative',
});
export const iconWrapper = style({
width: 36,
height: 36,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '50%',
backgroundColor: cssVar('hoverColor'),
});
export const icon = style({
fontSize: 20,
color: cssVar('iconSecondary'),
});
export const message = style({
fontSize: cssVar('fontSm'),
textAlign: 'center',
color: cssVar('black30'),
userSelect: 'none',
});
export const newButton = style({
padding: '0 8px',
height: '28px',
fontSize: cssVar('fontXs'),
});

View File

@@ -1,30 +1,16 @@
import { Button } from '@affine/component';
import { useI18n } from '@affine/i18n';
import { TagIcon } from '@blocksuite/icons/rc';
import * as styles from './empty.css';
import { ExplorerGroupEmpty } from '../../layouts/empty-layout';
export const RootEmpty = ({
onClickCreate,
}: {
onClickCreate?: () => void;
}) => {
export const RootEmpty = () => {
const t = useI18n();
return (
<div className={styles.content}>
<div className={styles.iconWrapper}>
<TagIcon className={styles.icon} />
</div>
<div
data-testid="slider-bar-tags-empty-message"
className={styles.message}
>
{t['com.affine.rootAppSidebar.tags.empty']()}
</div>
<Button className={styles.newButton} onClick={onClickCreate}>
{t['com.affine.rootAppSidebar.tags.empty.new-tag-button']()}
</Button>
</div>
<ExplorerGroupEmpty
icon={TagIcon}
message={t['com.affine.rootAppSidebar.tags.empty']()}
messageTestId="slider-bar-tags-empty-message"
/>
);
};

View File

@@ -69,9 +69,7 @@ export const ExplorerTags = ({
</IconButton>
</CategoryDivider>
<Collapsible.Content>
<ExplorerTreeRoot
placeholder={<RootEmpty onClickCreate={handleCreateNewFavoriteDoc} />}
>
<ExplorerTreeRoot placeholder={<RootEmpty />}>
{tags.map(tag => (
<ExplorerTagNode
key={tag.id}

View File

@@ -1149,7 +1149,7 @@
"com.affine.rootAppSidebar.explorer.drop-effect.move": "Move",
"com.affine.rootAppSidebar.explorer.drop-effect.copy": "Copy",
"com.affine.rootAppSidebar.docs.no-subdoc": "No linked docs",
"com.affine.rootAppSidebar.favorites.empty": "You can add documents to your favourites",
"com.affine.rootAppSidebar.favorites.empty": "No Favorites",
"com.affine.rootAppSidebar.others": "Others",
"com.affine.rootAppSidebar.docs.references-loading": "Loading linked docs...",
"com.affine.search-tags.placeholder": "Type here ...",