feat(core): add context menu for navigation and explorer (#13216)

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

* **New Features**
* Introduced a customizable context menu component for desktop
interfaces, enabling right-click menus in various UI elements.
* Added context menu support to document list items and navigation tree
nodes, allowing users to access additional operations via right-click.
* **Improvements**
* Enhanced submenu and menu item components to support both dropdown and
context menu variants based on context.
* Updated click handling in workbench links to prevent unintended
actions on non-left mouse button clicks.
* **Chores**
* Added `@radix-ui/react-context-menu` as a dependency to relevant
frontend packages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
EYHN
2025-07-16 12:40:10 +08:00
committed by GitHub
parent d44771dfe9
commit cdff5c3117
12 changed files with 247 additions and 106 deletions
@@ -1,5 +1,6 @@
import {
Checkbox,
ContextMenu,
DragHandle as DragHandleIcon,
Tooltip,
useDraggable,
@@ -29,7 +30,7 @@ import { PagePreview } from '../../page-list/page-content-preview';
import { DocExplorerContext } from '../context';
import { quickActions } from '../quick-actions.constants';
import * as styles from './doc-list-item.css';
import { MoreMenuButton } from './more-menu';
import { MoreMenuButton, MoreMenuContent } from './more-menu';
import { CardViewProperties, ListViewProperties } from './properties';
export type DocListItemView = 'list' | 'grid' | 'masonry';
@@ -314,38 +315,46 @@ export const ListViewDoc = ({ docId }: DocListItemProps) => {
const t = useI18n();
const docsService = useService(DocsService);
const doc = useLiveData(docsService.list.doc$(docId));
const contextValue = useContext(DocExplorerContext);
const showMoreOperation = useLiveData(contextValue.showMoreOperation$);
if (!doc) {
return null;
}
return (
<li className={styles.listViewRoot}>
<DragHandle id={docId} className={styles.listDragHandle} />
<Select id={docId} className={styles.listSelect} />
<DocIcon id={docId} className={styles.listIcon} />
<div className={styles.listBrief}>
<DocTitle
id={docId}
className={styles.listTitle}
data-testid="doc-list-item-title"
<ContextMenu
asChild
disabled={!showMoreOperation}
items={<MoreMenuContent docId={docId} />}
>
<li className={styles.listViewRoot}>
<DragHandle id={docId} className={styles.listDragHandle} />
<Select id={docId} className={styles.listSelect} />
<DocIcon id={docId} className={styles.listIcon} />
<div className={styles.listBrief}>
<DocTitle
id={docId}
className={styles.listTitle}
data-testid="doc-list-item-title"
/>
<DocPreview id={docId} className={styles.listPreview} />
</div>
<div className={styles.listSpace} />
<ListViewProperties docId={docId} />
{quickActions.map(action => {
return (
<Tooltip key={action.key} content={t.t(action.name)}>
<action.Component doc={doc} />
</Tooltip>
);
})}
<MoreMenuButton
docId={docId}
contentOptions={listMoreMenuContentOptions}
/>
<DocPreview id={docId} className={styles.listPreview} />
</div>
<div className={styles.listSpace} />
<ListViewProperties docId={docId} />
{quickActions.map(action => {
return (
<Tooltip key={action.key} content={t.t(action.name)}>
<action.Component doc={doc} />
</Tooltip>
);
})}
<MoreMenuButton
docId={docId}
contentOptions={listMoreMenuContentOptions}
/>
</li>
</li>
</ContextMenu>
);
};