继续收口轻量共享按钮
将 PlatformTagEditor 标签删除入口改为复用共享图标按钮 将角色选择页重复返回按钮收口到共享暗色动作按钮壳 补充 PlatformUiKit 收口计划与共享决策记录
This commit is contained in:
@@ -23,7 +23,18 @@ test('renders tags and removes a tag', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '删除标签 山海' }));
|
||||
const removeButton = screen.getByRole('button', { name: '删除标签 山海' });
|
||||
|
||||
expect(removeButton.className).toContain('platform-icon-button');
|
||||
expect(removeButton.className).toContain('h-3.5');
|
||||
expect(removeButton.className).toContain('w-3.5');
|
||||
expect(removeButton.className).toContain('border-0');
|
||||
expect(removeButton.className).toContain('bg-transparent');
|
||||
expect(removeButton.className).toContain('p-0');
|
||||
expect(removeButton.className).toContain('opacity-70');
|
||||
expect(removeButton.getAttribute('title')).toBe('删除标签');
|
||||
|
||||
fireEvent.click(removeButton);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(['机关']);
|
||||
});
|
||||
|
||||
@@ -131,20 +131,18 @@ export function PlatformTagEditor({
|
||||
].join(' ')}
|
||||
>
|
||||
{tag}
|
||||
<button
|
||||
type="button"
|
||||
<PlatformIconButton
|
||||
disabled={disabled}
|
||||
label={`删除标签 ${tag}`}
|
||||
title="删除标签"
|
||||
onClick={() =>
|
||||
onChange(
|
||||
normalizedTags.filter((currentTag) => currentTag !== tag),
|
||||
)
|
||||
}
|
||||
className="rounded-full opacity-70 transition hover:opacity-100 disabled:opacity-45"
|
||||
aria-label={`删除标签 ${tag}`}
|
||||
title="删除标签"
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
className="h-3.5 w-3.5 border-0 bg-transparent p-0 opacity-70 shadow-none transition hover:translate-y-0 hover:bg-transparent disabled:opacity-45"
|
||||
icon={<X className="h-3.5 w-3.5" />}
|
||||
/>
|
||||
</span>
|
||||
))}
|
||||
{normalizedTags.length <= 0 ? (
|
||||
|
||||
@@ -103,6 +103,7 @@ afterEach(() => {
|
||||
|
||||
test('custom world character selection stays stable when character ids are empty', async () => {
|
||||
const user = userEvent.setup();
|
||||
const handleBack = vi.fn();
|
||||
const handleConfirm = vi.fn();
|
||||
const consoleErrorSpy = vi
|
||||
.spyOn(console, 'error')
|
||||
@@ -201,11 +202,21 @@ test('custom world character selection stays stable when character ids are empty
|
||||
],
|
||||
},
|
||||
} as unknown as CustomWorldProfile}
|
||||
onBack={() => {}}
|
||||
onBack={handleBack}
|
||||
onConfirm={handleConfirm}
|
||||
/>,
|
||||
);
|
||||
|
||||
const backButton = screen.getByRole('button', {name: '返回'});
|
||||
expect(backButton.className).toContain('platform-action-button--editor-dark');
|
||||
expect(backButton.className).toContain('rounded-full');
|
||||
expect(backButton.className).toContain('px-3');
|
||||
expect(backButton.className).toContain('py-1.5');
|
||||
expect(backButton.className).toContain('text-[11px]');
|
||||
|
||||
await user.click(backButton);
|
||||
expect(handleBack).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(screen.getByText(/潮骨:/u)).toBeTruthy();
|
||||
expect(screen.queryByText(/力量:/u)).toBeNull();
|
||||
|
||||
@@ -235,7 +246,9 @@ test('custom world character selection stays stable when character ids are empty
|
||||
expect(duplicateKeyCalls).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('custom world character selection falls back instead of rendering a blank screen when profile characters are malformed', () => {
|
||||
test('custom world character selection falls back instead of rendering a blank screen when profile characters are malformed', async () => {
|
||||
const user = userEvent.setup();
|
||||
const handleBack = vi.fn();
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
vi.mocked(buildCustomWorldPlayableCharacters).mockImplementation(() => {
|
||||
throw new TypeError('profile.playableNpcs is not iterable');
|
||||
@@ -268,7 +281,7 @@ test('custom world character selection falls back instead of rendering a blank s
|
||||
],
|
||||
},
|
||||
} as unknown as CustomWorldProfile}
|
||||
onBack={() => {}}
|
||||
onBack={handleBack}
|
||||
onConfirm={() => {}}
|
||||
/>,
|
||||
);
|
||||
@@ -276,4 +289,7 @@ test('custom world character selection falls back instead of rendering a blank s
|
||||
expect(screen.getByText('选择你的角色')).toBeTruthy();
|
||||
expect(screen.getAllByText('兜底侠').length).toBeGreaterThan(0);
|
||||
expect(screen.getByRole('button', { name: /进入营地/u })).toBeTruthy();
|
||||
|
||||
await user.click(screen.getByRole('button', {name: '返回'}));
|
||||
expect(handleBack).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
import { getNineSliceStyle, UI_CHROME } from '../../uiAssets';
|
||||
import { CharacterAnimator } from '../CharacterAnimator';
|
||||
import { CharacterDetailModal } from '../CharacterDetailModal';
|
||||
import { PlatformActionButton } from '../common/PlatformActionButton';
|
||||
import { ResolvedAssetImage } from '../ResolvedAssetImage';
|
||||
import { CharacterDraftModal } from '../SelectionCustomizationModals';
|
||||
|
||||
@@ -215,6 +216,21 @@ function getCharacterCardStyle(index: number, progress: number) {
|
||||
};
|
||||
}
|
||||
|
||||
function CharacterSelectBackButton({onBack}: {onBack: () => void}) {
|
||||
return (
|
||||
<PlatformActionButton
|
||||
surface="editorDark"
|
||||
tone="ghost"
|
||||
size="xxs"
|
||||
shape="pill"
|
||||
onClick={onBack}
|
||||
className="px-3 py-1.5 text-[11px]"
|
||||
>
|
||||
返回
|
||||
</PlatformActionButton>
|
||||
);
|
||||
}
|
||||
|
||||
export function RpgEntryCharacterSelectView({
|
||||
worldType,
|
||||
customWorldProfile,
|
||||
@@ -344,13 +360,7 @@ export function RpgEntryCharacterSelectView({
|
||||
if (!selectedCharacter || !selectedCharacterMeta) {
|
||||
return (
|
||||
<div className="flex h-full min-h-0 flex-col items-center justify-center gap-4 text-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onBack}
|
||||
className="rounded-full border border-white/10 bg-black/18 px-3 py-1.5 text-[11px] text-zinc-300 transition-colors hover:text-white"
|
||||
>
|
||||
返回
|
||||
</button>
|
||||
<CharacterSelectBackButton onBack={onBack} />
|
||||
<div className="text-sm text-zinc-300">角色数据暂不可用</div>
|
||||
</div>
|
||||
);
|
||||
@@ -360,13 +370,7 @@ export function RpgEntryCharacterSelectView({
|
||||
<>
|
||||
<div className="flex h-full min-h-0 flex-col">
|
||||
<div className="mb-3 flex justify-start">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onBack}
|
||||
className="rounded-full border border-white/10 bg-black/18 px-3 py-1.5 text-[11px] text-zinc-300 transition-colors hover:text-white"
|
||||
>
|
||||
返回
|
||||
</button>
|
||||
<CharacterSelectBackButton onBack={onBack} />
|
||||
</div>
|
||||
<div className="mb-4 text-center">
|
||||
<div className="text-2xl font-black text-white sm:text-[2rem]">选择你的角色</div>
|
||||
|
||||
Reference in New Issue
Block a user