unify Semi UI workspace command hierarchy
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
import { Tag, Typography } from '@douyinfe/semi-ui';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
export function PageHeader({
|
||||
title,
|
||||
description,
|
||||
status,
|
||||
statusColor = 'blue',
|
||||
meta,
|
||||
actions
|
||||
}: {
|
||||
title: string;
|
||||
description: string;
|
||||
status?: string;
|
||||
statusColor?: React.ComponentProps<typeof Tag>['color'];
|
||||
meta?: ReactNode;
|
||||
actions?: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<header className="v2-page-heading">
|
||||
<div className="v2-page-heading-copy">
|
||||
<div>
|
||||
<Title heading={2}>{title}</Title>
|
||||
{status ? <Tag color={statusColor} size="small">{status}</Tag> : null}
|
||||
</div>
|
||||
<Text type="secondary">{description}</Text>
|
||||
</div>
|
||||
{meta || actions ? <div className="v2-page-heading-aside">{meta}{actions}</div> : null}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { Button, Typography } from '@douyinfe/semi-ui';
|
||||
import { expect, test } from 'vitest';
|
||||
import { WorkspaceCommandBar } from './WorkspaceCommandBar';
|
||||
|
||||
test('renders a compact Semi workspace command hierarchy', () => {
|
||||
const view = render(<WorkspaceCommandBar
|
||||
className="custom-command"
|
||||
ariaLabel="测试工作区操作"
|
||||
title="测试工作区"
|
||||
description="说明当前任务和数据范围"
|
||||
status="12 条"
|
||||
meta={<Typography.Text type="tertiary">刚刚更新</Typography.Text>}
|
||||
actions={<Button theme="solid">执行</Button>}
|
||||
/>);
|
||||
|
||||
expect(screen.getByRole('heading', { name: '测试工作区', level: 5 })).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('测试工作区操作')).toHaveClass('v2-workspace-command-bar', 'custom-command');
|
||||
expect(screen.getByText('12 条').closest('.semi-tag')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: '执行' })).toHaveClass('semi-button');
|
||||
expect(view.container.querySelector('.v2-workspace-command-copy')).toHaveTextContent('说明当前任务和数据范围');
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Tag, Typography } from '@douyinfe/semi-ui';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
const { Text, Title } = Typography;
|
||||
|
||||
export function WorkspaceCommandBar({
|
||||
title,
|
||||
description,
|
||||
status,
|
||||
statusColor = 'blue',
|
||||
meta,
|
||||
actions,
|
||||
className = '',
|
||||
ariaLabel
|
||||
}: {
|
||||
title: ReactNode;
|
||||
description: ReactNode;
|
||||
status?: string;
|
||||
statusColor?: React.ComponentProps<typeof Tag>['color'];
|
||||
meta?: ReactNode;
|
||||
actions?: ReactNode;
|
||||
className?: string;
|
||||
ariaLabel?: string;
|
||||
}) {
|
||||
const rootClassName = ['v2-workspace-command-bar', className].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<header className={rootClassName} aria-label={ariaLabel}>
|
||||
<div className="v2-workspace-command-copy">
|
||||
<Title heading={5}>{title}</Title>
|
||||
<Text type="tertiary">{description}</Text>
|
||||
</div>
|
||||
{status || meta || actions ? <div className="v2-workspace-command-actions">
|
||||
{status ? <Tag color={statusColor} type="light" size="small">{status}</Tag> : null}
|
||||
{meta ? <span className="v2-workspace-command-meta">{meta}</span> : null}
|
||||
{actions}
|
||||
</div> : null}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user