继续收口编辑器空态与暗色动作按钮
视觉小说实体列表空态复用 PlatformEmptyState 角色素材工作室局部按钮改为委托 PlatformActionButton RPG大编辑器局部按钮改为委托 PlatformActionButton 更新 PlatformUiKit 收口文档与团队决策记录
This commit is contained in:
@@ -1055,7 +1055,11 @@ test('基本设定面板只编辑六个角色维度名称', async () => {
|
||||
expect(screen.queryByLabelText('正向信号')).toBeNull();
|
||||
expect(screen.queryByLabelText('战斗体现')).toBeNull();
|
||||
|
||||
await user.click(screen.getByRole('button', { name: /保存修改/u }));
|
||||
const saveButton = screen.getByRole('button', { name: /保存修改/u });
|
||||
expect(saveButton.className).toContain('platform-action-button--editor-dark');
|
||||
expect(saveButton.className).toContain('rounded-full');
|
||||
|
||||
await user.click(saveButton);
|
||||
|
||||
expect(savedProfileRef.current?.attributeSchema.slots[0]?.name).toBe('潮骨');
|
||||
});
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
import { buildProjectPixelStyleReferenceBoard } from '../asset-studio/projectPixelStyleReference';
|
||||
import { useAuthUi } from '../auth/AuthUiContext';
|
||||
import { CharacterAnimator } from '../CharacterAnimator';
|
||||
import { PlatformActionButton } from '../common/PlatformActionButton';
|
||||
import { PlatformMudPointConfirmDialog } from '../common/PlatformMudPointConfirmDialog';
|
||||
import {
|
||||
CORE_ACTIONS,
|
||||
@@ -206,16 +207,21 @@ function ActionButton({
|
||||
disabled?: boolean;
|
||||
tone?: 'default' | 'sky' | 'green';
|
||||
}) {
|
||||
const resolvedTone =
|
||||
tone === 'green' ? 'success' : tone === 'sky' ? 'primary' : 'ghost';
|
||||
const toneClassName =
|
||||
tone === 'green'
|
||||
? 'border-emerald-400/30 bg-emerald-500/10 text-emerald-100 hover:bg-emerald-500/20'
|
||||
? 'border-emerald-400/30 bg-emerald-500/10 text-emerald-100 hover:border-emerald-300/40 hover:bg-emerald-500/20 hover:text-white'
|
||||
: tone === 'sky'
|
||||
? 'border-sky-300/22 bg-sky-500/12 text-sky-50 hover:border-sky-200/40 hover:text-white'
|
||||
: 'border-white/12 bg-black/20 text-zinc-200 hover:border-white/22 hover:text-white';
|
||||
? 'border-sky-300/22 bg-sky-500/12 text-sky-50 hover:border-sky-200/40 hover:bg-sky-500/15 hover:text-white'
|
||||
: 'border-white/12 bg-black/20 text-zinc-200 hover:border-white/22 hover:bg-black/20 hover:text-white';
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
<PlatformActionButton
|
||||
surface="editorDark"
|
||||
tone={resolvedTone}
|
||||
shape="pill"
|
||||
align="start"
|
||||
onPointerDown={(event) => {
|
||||
event.stopPropagation();
|
||||
}}
|
||||
@@ -227,7 +233,12 @@ function ActionButton({
|
||||
onClick();
|
||||
}}
|
||||
disabled={disabled}
|
||||
className={`inline-flex items-center gap-2 rounded-full border px-4 py-2 text-sm font-semibold transition-colors ${toneClassName} ${disabled ? 'cursor-not-allowed opacity-45' : ''}`}
|
||||
className={[
|
||||
'py-2 font-semibold leading-tight disabled:opacity-45',
|
||||
toneClassName,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
>
|
||||
{icon ?? null}
|
||||
<span className="flex flex-col items-start leading-tight">
|
||||
@@ -236,7 +247,7 @@ function ActionButton({
|
||||
<span className="text-[11px] font-medium opacity-70">{subLabel}</span>
|
||||
) : null}
|
||||
</span>
|
||||
</button>
|
||||
</PlatformActionButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ import {
|
||||
import { useAuthUi } from '../auth/AuthUiContext';
|
||||
import { CharacterAnimator } from '../CharacterAnimator';
|
||||
import { PlatformAcknowledgeStatusDialog } from '../common/PlatformAcknowledgeStatusDialog';
|
||||
import { PlatformActionButton } from '../common/PlatformActionButton';
|
||||
import { PlatformAssetPickerGrid } from '../common/PlatformAssetPickerCard';
|
||||
import { PlatformEmptyState } from '../common/PlatformEmptyState';
|
||||
import { PlatformIconButton } from '../common/PlatformIconButton';
|
||||
@@ -1665,16 +1666,22 @@ function ActionButton({
|
||||
disabled?: boolean;
|
||||
className?: string;
|
||||
}) {
|
||||
const buttonTone =
|
||||
tone === 'sky' ? 'primary' : tone === 'rose' ? 'danger' : 'ghost';
|
||||
const toneClassName =
|
||||
tone === 'sky'
|
||||
? 'border-sky-300/22 bg-sky-500/12 text-sky-50 hover:border-sky-200/40 hover:text-white'
|
||||
? 'border-sky-300/22 bg-sky-500/12 text-sky-50 hover:border-sky-200/40 hover:bg-sky-500/18 hover:text-white'
|
||||
: tone === 'rose'
|
||||
? 'border-rose-300/22 bg-rose-500/12 text-rose-50 hover:border-rose-200/40 hover:text-white'
|
||||
? 'border-rose-300/22 bg-rose-500/12 text-rose-50 hover:border-rose-200/40 hover:bg-rose-500/16 hover:text-white'
|
||||
: 'border-white/12 bg-black/20 text-zinc-200 hover:border-white/22 hover:text-white';
|
||||
|
||||
return (
|
||||
<button
|
||||
<PlatformActionButton
|
||||
type="button"
|
||||
surface="editorDark"
|
||||
tone={buttonTone}
|
||||
size="sm"
|
||||
shape="pill"
|
||||
onPointerDown={(event) => {
|
||||
event.stopPropagation();
|
||||
}}
|
||||
@@ -1686,10 +1693,16 @@ function ActionButton({
|
||||
onClick();
|
||||
}}
|
||||
disabled={disabled}
|
||||
className={`rounded-full border px-4 py-2 text-sm font-semibold transition-colors ${toneClassName} ${disabled ? 'cursor-not-allowed opacity-45' : ''} ${className}`}
|
||||
className={[
|
||||
'py-2 font-semibold disabled:opacity-45',
|
||||
toneClassName,
|
||||
className,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
</PlatformActionButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ test('visual novel entity list items use interactive PlatformSubpanel shells', a
|
||||
expect(characterCard.className).toContain('rounded-[1.25rem]');
|
||||
});
|
||||
|
||||
test('visual novel empty entity list uses PlatformSubpanel shell', async () => {
|
||||
test('visual novel empty entity list uses PlatformEmptyState shell', async () => {
|
||||
const user = userEvent.setup();
|
||||
const emptyCharacterDraft = {
|
||||
...mockVisualNovelDraft,
|
||||
@@ -126,11 +126,17 @@ test('visual novel empty entity list uses PlatformSubpanel shell', async () => {
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '角色' }));
|
||||
|
||||
const emptyPanel = screen.getByText('暂无角色').closest('.platform-subpanel');
|
||||
const emptyPanel = screen
|
||||
.getByText('暂无角色')
|
||||
.closest('.platform-empty-state');
|
||||
|
||||
expect(emptyPanel?.className).toContain('platform-subpanel');
|
||||
expect(emptyPanel?.className).toContain('platform-empty-state');
|
||||
expect(emptyPanel?.className).toContain('bg-white/74');
|
||||
expect(emptyPanel?.className).toContain('rounded-[1.25rem]');
|
||||
expect(emptyPanel?.className).toContain('min-h-32');
|
||||
expect(emptyPanel?.className).toContain(
|
||||
'text-[var(--platform-text-soft)]',
|
||||
);
|
||||
});
|
||||
|
||||
test('visual novel result opens complex editors as a dialog', async () => {
|
||||
|
||||
@@ -1848,12 +1848,13 @@ function VisualNovelEntityGrid({
|
||||
</PlatformSubpanel>
|
||||
))}
|
||||
{items.length <= 0 ? (
|
||||
<PlatformSubpanel
|
||||
as="div"
|
||||
className="flex min-h-32 items-center justify-center rounded-[1.25rem] px-4 text-sm text-[var(--platform-text-soft)]"
|
||||
<PlatformEmptyState
|
||||
surface="subpanel"
|
||||
size="inline"
|
||||
className="flex min-h-32 items-center justify-center rounded-[1.25rem] p-4 font-normal"
|
||||
>
|
||||
{emptyText}
|
||||
</PlatformSubpanel>
|
||||
</PlatformEmptyState>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user