diff --git a/packages/frontend/core/src/modules/explorer/views/layouts/empty-node-children.css.ts b/packages/frontend/core/src/modules/explorer/views/layouts/empty-node-children.css.ts new file mode 100644 index 0000000000..cea695127d --- /dev/null +++ b/packages/frontend/core/src/modules/explorer/views/layouts/empty-node-children.css.ts @@ -0,0 +1,25 @@ +import { cssVar } from '@toeverything/theme'; +import { cssVarV2 } from '@toeverything/theme/v2'; +import { fallbackVar, style } from '@vanilla-extract/css'; + +import { levelIndent } from '../tree/node.css'; + +export const emptyChildren = style({ + fontSize: cssVar('fontSm'), + color: cssVarV2('text/disable'), + textAlign: 'left', + userSelect: 'none', + lineHeight: '22px', + padding: '4px 0px', + marginTop: 2, + // 48 = node.paddingLeft + node.collapsable.width + node.icon.width + node.icon.marginRight + // = 4 + 16 + 20 + 8 + // to align with node's content + paddingLeft: `calc(${fallbackVar(levelIndent, '20px')} + 48px)`, + selectors: { + '&[data-dragged-over="true"]': { + background: cssVarV2('layer/background/hoverOverlay'), + borderRadius: '4px', + }, + }, +}); diff --git a/packages/frontend/core/src/modules/explorer/views/layouts/empty-node-children.tsx b/packages/frontend/core/src/modules/explorer/views/layouts/empty-node-children.tsx new file mode 100644 index 0000000000..17fa7034fe --- /dev/null +++ b/packages/frontend/core/src/modules/explorer/views/layouts/empty-node-children.tsx @@ -0,0 +1,15 @@ +import clsx from 'clsx'; +import { forwardRef, type HTMLAttributes, type Ref } from 'react'; + +import { emptyChildren } from './empty-node-children.css'; + +export const EmptyNodeChildren = forwardRef(function EmptyNodeChildren( + { children, className, ...attrs }: HTMLAttributes, + ref: Ref +) { + return ( +
+ {children} +
+ ); +}); diff --git a/packages/frontend/core/src/modules/explorer/views/layouts/empty-layout.css.ts b/packages/frontend/core/src/modules/explorer/views/layouts/empty-section.css.ts similarity index 100% rename from packages/frontend/core/src/modules/explorer/views/layouts/empty-layout.css.ts rename to packages/frontend/core/src/modules/explorer/views/layouts/empty-section.css.ts diff --git a/packages/frontend/core/src/modules/explorer/views/layouts/empty-layout.tsx b/packages/frontend/core/src/modules/explorer/views/layouts/empty-section.tsx similarity index 80% rename from packages/frontend/core/src/modules/explorer/views/layouts/empty-layout.tsx rename to packages/frontend/core/src/modules/explorer/views/layouts/empty-section.tsx index 2ffdd11bdf..6a36542797 100644 --- a/packages/frontend/core/src/modules/explorer/views/layouts/empty-layout.tsx +++ b/packages/frontend/core/src/modules/explorer/views/layouts/empty-section.tsx @@ -7,9 +7,9 @@ import { type SVGProps, } from 'react'; -import * as styles from './empty-layout.css'; +import * as styles from './empty-section.css'; -interface ExplorerGroupEmptyProps extends HTMLAttributes { +interface ExplorerEmptySectionProps extends HTMLAttributes { icon: (props: SVGProps) => JSX.Element; message: string; messageTestId?: string; @@ -17,7 +17,7 @@ interface ExplorerGroupEmptyProps extends HTMLAttributes { onActionClick?: () => void; } -export const ExplorerGroupEmpty = forwardRef(function ExplorerGroupEmpty( +export const ExplorerEmptySection = forwardRef(function ExplorerEmptySection( { icon: Icon, message, @@ -27,7 +27,7 @@ export const ExplorerGroupEmpty = forwardRef(function ExplorerGroupEmpty( className, onActionClick, ...attrs - }: ExplorerGroupEmptyProps, + }: ExplorerEmptySectionProps, ref: Ref ) { return ( diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/collection/empty.css.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/collection/empty.css.tsx deleted file mode 100644 index 049d07b215..0000000000 --- a/packages/frontend/core/src/modules/explorer/views/nodes/collection/empty.css.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { cssVar } from '@toeverything/theme'; -import { fallbackVar, style } from '@vanilla-extract/css'; - -import { levelIndent } from '../../tree/node.css'; - -export const noReferences = style({ - fontSize: cssVar('fontSm'), - textAlign: 'left', - padding: '4px 0 4px 32px', - color: cssVar('black30'), - userSelect: 'none', - paddingLeft: `calc(${fallbackVar(levelIndent, '20px')} + 32px)`, - selectors: { - '&[data-dragged-over="true"]': { - background: cssVar('--affine-hover-color'), - borderRadius: '4px', - }, - }, -}); diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/collection/empty.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/collection/empty.tsx index 372eea2d9b..8c7241f5f7 100644 --- a/packages/frontend/core/src/modules/explorer/views/nodes/collection/empty.tsx +++ b/packages/frontend/core/src/modules/explorer/views/nodes/collection/empty.tsx @@ -2,7 +2,7 @@ import { type DropTargetDropEvent, useDropTarget } from '@affine/component'; import type { AffineDNDData } from '@affine/core/types/dnd'; import { useI18n } from '@affine/i18n'; -import * as styles from './empty.css'; +import { EmptyNodeChildren } from '../../layouts/empty-node-children'; export const Empty = ({ onDrop, @@ -17,8 +17,8 @@ export const Empty = ({ ); const t = useI18n(); return ( -
+ {t['com.affine.collection.emptyCollection']()} -
+ ); }; diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/doc/empty.css.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/doc/empty.css.tsx deleted file mode 100644 index 049d07b215..0000000000 --- a/packages/frontend/core/src/modules/explorer/views/nodes/doc/empty.css.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { cssVar } from '@toeverything/theme'; -import { fallbackVar, style } from '@vanilla-extract/css'; - -import { levelIndent } from '../../tree/node.css'; - -export const noReferences = style({ - fontSize: cssVar('fontSm'), - textAlign: 'left', - padding: '4px 0 4px 32px', - color: cssVar('black30'), - userSelect: 'none', - paddingLeft: `calc(${fallbackVar(levelIndent, '20px')} + 32px)`, - selectors: { - '&[data-dragged-over="true"]': { - background: cssVar('--affine-hover-color'), - borderRadius: '4px', - }, - }, -}); diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/doc/empty.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/doc/empty.tsx index 4882004756..2fe7f19be0 100644 --- a/packages/frontend/core/src/modules/explorer/views/nodes/doc/empty.tsx +++ b/packages/frontend/core/src/modules/explorer/views/nodes/doc/empty.tsx @@ -2,7 +2,7 @@ import { type DropTargetDropEvent, useDropTarget } from '@affine/component'; import type { AffineDNDData } from '@affine/core/types/dnd'; import { useI18n } from '@affine/i18n'; -import * as styles from './empty.css'; +import { EmptyNodeChildren } from '../../layouts/empty-node-children'; export const Empty = ({ onDrop, @@ -16,9 +16,10 @@ export const Empty = ({ [onDrop] ); const t = useI18n(); + return ( -
+ {t['com.affine.rootAppSidebar.docs.no-subdoc']()} -
+ ); }; diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/folder/empty.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/folder/empty.tsx index 097f7cc8d8..50ce705df0 100644 --- a/packages/frontend/core/src/modules/explorer/views/nodes/folder/empty.tsx +++ b/packages/frontend/core/src/modules/explorer/views/nodes/folder/empty.tsx @@ -5,22 +5,16 @@ import { } from '@affine/component'; import type { AffineDNDData } from '@affine/core/types/dnd'; 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'; +import { EmptyNodeChildren } from '../../layouts/empty-node-children'; +import { draggedOverHighlight } from './empty.css'; export const FolderEmpty = ({ - onClickCreate, - className, canDrop, onDrop, }: { - onClickCreate?: () => void; onDrop?: (data: DropTargetDropEvent) => void; canDrop?: DropTargetOptions['canDrop']; - className?: string; }) => { const { dropTargetRef } = useDropTarget( () => ({ @@ -32,16 +26,8 @@ export const FolderEmpty = ({ const t = useI18n(); return ( - + + {t['com.affine.rootAppSidebar.organize.empty-folder']()} + ); }; diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/folder/index.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/folder/index.tsx index e564ff96c0..6c0c783f79 100644 --- a/packages/frontend/core/src/modules/explorer/views/nodes/folder/index.tsx +++ b/packages/frontend/core/src/modules/explorer/views/nodes/folder/index.tsx @@ -814,11 +814,7 @@ export const ExplorerFolderNodeFolder = ({ operations={finalOperations} canDrop={handleCanDrop} childrenPlaceholder={ - handleAddToFolder('doc')} - /> + } dropEffect={handleDropEffect} data-testid={`explorer-folder-${node.id}`} diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/tag/empty.css.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/tag/empty.css.tsx deleted file mode 100644 index 049d07b215..0000000000 --- a/packages/frontend/core/src/modules/explorer/views/nodes/tag/empty.css.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { cssVar } from '@toeverything/theme'; -import { fallbackVar, style } from '@vanilla-extract/css'; - -import { levelIndent } from '../../tree/node.css'; - -export const noReferences = style({ - fontSize: cssVar('fontSm'), - textAlign: 'left', - padding: '4px 0 4px 32px', - color: cssVar('black30'), - userSelect: 'none', - paddingLeft: `calc(${fallbackVar(levelIndent, '20px')} + 32px)`, - selectors: { - '&[data-dragged-over="true"]': { - background: cssVar('--affine-hover-color'), - borderRadius: '4px', - }, - }, -}); diff --git a/packages/frontend/core/src/modules/explorer/views/nodes/tag/empty.tsx b/packages/frontend/core/src/modules/explorer/views/nodes/tag/empty.tsx index 127c62eb71..741fa39daa 100644 --- a/packages/frontend/core/src/modules/explorer/views/nodes/tag/empty.tsx +++ b/packages/frontend/core/src/modules/explorer/views/nodes/tag/empty.tsx @@ -2,7 +2,7 @@ import { type DropTargetDropEvent, useDropTarget } from '@affine/component'; import type { AffineDNDData } from '@affine/core/types/dnd'; import { useI18n } from '@affine/i18n'; -import * as styles from './empty.css'; +import { EmptyNodeChildren } from '../../layouts/empty-node-children'; export const Empty = ({ onDrop, @@ -17,8 +17,8 @@ export const Empty = ({ ); const t = useI18n(); return ( -
+ {t['com.affine.rootAppSidebar.tags.no-doc']()} -
+ ); }; diff --git a/packages/frontend/core/src/modules/explorer/views/sections/collections/empty.tsx b/packages/frontend/core/src/modules/explorer/views/sections/collections/empty.tsx index cdd5212a3c..2f292925b0 100644 --- a/packages/frontend/core/src/modules/explorer/views/sections/collections/empty.tsx +++ b/packages/frontend/core/src/modules/explorer/views/sections/collections/empty.tsx @@ -1,7 +1,7 @@ import { useI18n } from '@affine/i18n'; import { ViewLayersIcon } from '@blocksuite/icons/rc'; -import { ExplorerGroupEmpty } from '../../layouts/empty-layout'; +import { ExplorerEmptySection } from '../../layouts/empty-section'; export const RootEmpty = ({ onClickCreate, @@ -11,7 +11,7 @@ export const RootEmpty = ({ const t = useI18n(); return ( - )} - + ); }; diff --git a/packages/frontend/core/src/modules/explorer/views/sections/organize/empty.tsx b/packages/frontend/core/src/modules/explorer/views/sections/organize/empty.tsx index 393decad5f..0081b6d7de 100644 --- a/packages/frontend/core/src/modules/explorer/views/sections/organize/empty.tsx +++ b/packages/frontend/core/src/modules/explorer/views/sections/organize/empty.tsx @@ -1,7 +1,7 @@ import { useI18n } from '@affine/i18n'; import { FolderIcon } from '@blocksuite/icons/rc'; -import { ExplorerGroupEmpty } from '../../layouts/empty-layout'; +import { ExplorerEmptySection } from '../../layouts/empty-section'; export const RootEmpty = ({ onClickCreate, @@ -11,7 +11,7 @@ export const RootEmpty = ({ const t = useI18n(); return ( - { const t = useI18n(); return ( - { await deletePage.click(); await page.getByTestId('confirm-modal-confirm').click(); expect(await first.locator('[data-testid^="explorer-doc-"]').count()).toBe(0); - await first.hover(); + // position is a workaround for the hover issue when empty collection status's height > 26px (will cause scroll) + await first.hover({ position: { x: 10, y: 10 } }); await first.getByTestId('explorer-tree-node-operation-button').click(); const deleteCollection = page.getByText('Delete'); await deleteCollection.click();