抽取项目页浮层菜单组件

新增 PlatformFloatingMenu 与菜单项测试

项目卡片更多菜单复用平台浮层菜单

更新 TRACKING 记录组件收口验证
This commit is contained in:
2026-06-14 00:50:05 +08:00
parent 8b4175dc7d
commit 304d6806f0
5 changed files with 103 additions and 17 deletions

View File

@@ -0,0 +1,31 @@
/* @vitest-environment jsdom */
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, expect, it, vi } from 'vitest';
import {
PlatformFloatingMenu,
PlatformFloatingMenuItem,
} from './PlatformFloatingMenu';
describe('PlatformFloatingMenu', () => {
it('renders menu items with accessible menu semantics', async () => {
const onRename = vi.fn();
const user = userEvent.setup();
render(
<PlatformFloatingMenu>
<PlatformFloatingMenuItem onClick={onRename}>
</PlatformFloatingMenuItem>
</PlatformFloatingMenu>,
);
expect(screen.getByRole('menu')).toBeTruthy();
await user.click(screen.getByRole('menuitem', { name: '重命名' }));
expect(onRename).toHaveBeenCalledOnce();
});
});

View File

@@ -0,0 +1,54 @@
import type { ButtonHTMLAttributes, ReactNode } from 'react';
type PlatformFloatingMenuProps = {
children: ReactNode;
className?: string;
};
type PlatformFloatingMenuItemProps = Omit<
ButtonHTMLAttributes<HTMLButtonElement>,
'children'
> & {
icon?: ReactNode;
children: ReactNode;
};
/**
* 平台浮层菜单原语。
* 用于卡片角标、画布局部菜单等轻量动作集合,统一 role 与菜单项 chrome。
*/
export function PlatformFloatingMenu({
children,
className,
}: PlatformFloatingMenuProps) {
return (
<div
className={['platform-floating-menu', className].filter(Boolean).join(' ')}
role="menu"
>
{children}
</div>
);
}
export function PlatformFloatingMenuItem({
icon,
children,
className,
type = 'button',
...buttonProps
}: PlatformFloatingMenuItemProps) {
return (
<button
{...buttonProps}
type={type}
className={['platform-floating-menu__item', className]
.filter(Boolean)
.join(' ')}
role="menuitem"
>
{icon}
<span>{children}</span>
</button>
);
}