feat(core): new all docs header (#12182)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a new grouped document explorer with a masonry layout, advanced filtering, and multi-select capabilities.
  - Added a floating toolbar for batch actions, such as deleting multiple documents.
  - Implemented a feature flag to enable the new "All Docs" page, allowing gradual rollout.
  - Added a new navigation component with links for Docs, Collections, and Tags.
  - Introduced a display menu button supporting additional menu properties.

- **Enhancements**
  - Redesigned navigation headers across document, collection, and tag pages for improved consistency and usability.
  - Added new display and view toggling options for document lists.
  - Improved styling and responsiveness for explorer and header components.
  - Updated context to support dynamic view switching in the document explorer.

- **Bug Fixes**
  - Updated context and prop types to enhance state management and user interactions.

- **Refactor**
  - Replaced legacy page list views with a modern, grouped explorer interface.
  - Simplified and modularized header components and styles for better maintainability.
  - Removed workspace-specific controls from document headers to focus on explorer functionality.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
CatsJuice
2025-05-09 09:38:48 +00:00
parent 5f5de8e89d
commit 7013f9b804
21 changed files with 755 additions and 544 deletions
@@ -1,9 +1,11 @@
import { createContext, type Dispatch, type SetStateAction } from 'react';
import type { DocListItemView } from './docs-view/doc-list-item';
import type { ExplorerPreference } from './types';
export type DocExplorerContextType = ExplorerPreference & {
view: 'list' | 'grid' | 'masonry';
view: DocListItemView;
setView: Dispatch<SetStateAction<DocListItemView>>;
groups: Array<{ key: string; items: string[] }>;
collapsed: string[];
selectMode?: boolean;
@@ -17,6 +19,7 @@ export type DocExplorerContextType = ExplorerPreference & {
export const DocExplorerContext = createContext<DocExplorerContextType>({
view: 'list',
setView: () => {},
groups: [],
collapsed: [],
selectedDocIds: [],
@@ -1,4 +1,10 @@
import { Button, Divider, Menu, MenuSub } from '@affine/component';
import {
Button,
Divider,
Menu,
type MenuProps,
MenuSub,
} from '@affine/component';
import type {
GroupByParams,
OrderByParams,
@@ -92,12 +98,14 @@ export const ExplorerDisplayMenuButton = ({
style,
className,
preference,
menuProps,
onChange,
}: {
style?: React.CSSProperties;
className?: string;
preference: ExplorerPreference;
onChange?: (preference: ExplorerPreference) => void;
menuProps?: Omit<MenuProps, 'items' | 'children'>;
}) => {
const t = useI18n();
return (
@@ -105,6 +113,7 @@ export const ExplorerDisplayMenuButton = ({
items={
<ExplorerDisplayMenu preference={preference} onChange={onChange} />
}
{...menuProps}
>
<Button
className={className}
@@ -0,0 +1,20 @@
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';
export const container = style({
display: 'flex',
gap: 12,
alignItems: 'center',
fontSize: 18,
lineHeight: '26px',
fontWeight: 600,
});
export const item = style({
color: cssVarV2.text.secondary,
selectors: {
'&[data-active="true"]': {
color: cssVarV2.text.primary,
},
},
});
@@ -0,0 +1,47 @@
import { WorkbenchLink } from '@affine/core/modules/workbench';
import { useI18n } from '@affine/i18n';
import * as styles from './navigation.css';
const items = [
{
value: 'docs',
label: 'com.affine.docs.header',
testId: 'workspace-docs-button',
to: '/all',
},
{
value: 'collections',
label: 'com.affine.collections.header',
testId: 'workspace-collections-button',
to: '/collection',
},
{
value: 'tags',
label: 'Tags',
testId: 'workspace-tags-button',
to: '/tag',
},
] as const;
type NavigationKey = (typeof items)[number]['value'];
export const ExplorerNavigation = ({ active }: { active: NavigationKey }) => {
const t = useI18n();
return (
<div className={styles.container}>
{items.map(item => (
<WorkbenchLink
key={item.value}
data-testid={item.testId}
data-active={active === item.value}
to={item.to}
className={styles.item}
>
{t[item.label]()}
</WorkbenchLink>
))}
</div>
);
};