继续收口平台空态与动作按钮

作品架异步状态切换复用 PlatformAsyncStatePanel
复制反馈动作外观改为组合 PlatformActionButton
结果页与调试面板空态继续收口到 PlatformEmptyState
暗色私聊与工坊按钮改为复用 PlatformActionButton
更新 PlatformUiKit 收口文档与团队决策记录
This commit is contained in:
2026-06-11 01:41:15 +08:00
parent 0a4ccdf45c
commit 06bf03a28c
15 changed files with 202 additions and 130 deletions

View File

@@ -105,15 +105,19 @@ test('can opt into platform action button chrome', () => {
actionSurface="platform"
actionShape="pill"
actionFullWidth
aria-label="复制错误详情"
title="复制错误详情"
/>,
);
const button = screen.getByRole('button', { name: '复制错' });
const button = screen.getByRole('button', { name: '复制错误详情' });
expect(button.className).toContain('platform-button--primary');
expect(button.className).toContain('w-full');
expect(button.className).toContain('rounded-full');
expect(button.className).toContain('disabled:cursor-not-allowed');
expect(button.getAttribute('title')).toBe('复制错误详情');
expect(button.textContent).toContain('复制报错');
});
test('can opt into shared pill action chrome', () => {

View File

@@ -2,12 +2,12 @@ import { Check, Copy } from 'lucide-react';
import type { ButtonHTMLAttributes, ReactNode } from 'react';
import {
getPlatformActionButtonClassName,
type PlatformActionButtonSize,
type PlatformActionButtonShape,
type PlatformActionButtonSurface,
type PlatformActionButtonTone,
} from './platformActionButtonModel';
import { PlatformActionButton } from './PlatformActionButton';
import {
getPlatformPillBadgeClassName,
type PlatformPillBadgeSize,
@@ -105,38 +105,53 @@ export function CopyFeedbackButton({
: typeof idleLabel === 'string'
? idleLabel
: undefined);
const resolvedAriaLabel = ariaLabel ?? accessibleLabel;
const resolvedTitle =
title ?? (typeof accessibleLabel === 'string' ? accessibleLabel : undefined);
const content = (
<>
{showIcon ? icon : null}
{showLabel ? <span className={labelClassName}>{label}</span> : null}
</>
);
if (actionSurface) {
return (
<PlatformActionButton
surface={actionSurface}
tone={actionTone}
size={actionSize}
shape={actionShape}
fullWidth={actionFullWidth}
className={className}
{...buttonProps}
aria-label={resolvedAriaLabel}
title={resolvedTitle}
>
{content}
</PlatformActionButton>
);
}
return (
<button
type="button"
className={[
actionSurface
? getPlatformActionButtonClassName({
surface: actionSurface,
tone: actionTone,
size: actionSize,
shape: actionShape,
fullWidth: actionFullWidth,
actionAppearance === 'pill'
? getPlatformPillBadgeClassName({
tone: actionPillTone,
size: actionPillSize,
})
: actionAppearance === 'pill'
? getPlatformPillBadgeClassName({
tone: actionPillTone,
size: actionPillSize,
})
: null,
: null,
className,
]
.filter(Boolean)
.join(' ')}
{...buttonProps}
aria-label={ariaLabel ?? accessibleLabel}
title={
title ??
(typeof accessibleLabel === 'string' ? accessibleLabel : undefined)
}
aria-label={resolvedAriaLabel}
title={resolvedTitle}
>
{showIcon ? icon : null}
{showLabel ? <span className={labelClassName}>{label}</span> : null}
{content}
</button>
);
}