继续收口运行态浮层暗色动作与行卡
统一运行态浮层里的标准暗色动作按钮到共享 PlatformActionButton 统一设置面板里的运行统计入口到共享 PlatformSubpanel 按钮壳 补充 PlatformUiKit 收口计划、共享决策记录与 quest offer 组件测试护栏
This commit is contained in:
@@ -2080,6 +2080,7 @@
|
||||
- 决策:白底 / 暗色面板里的轻量空态和普通 CTA 继续向共享组件收口。`PuzzleResultView.tsx` 的缺草稿提示、`RpgCreationAssetDebugPanel.tsx` 的空诊断提示、`VisualNovelEntityGrid` 的空实体列表、`AccountModal.tsx` 里账号安全分区的“无安全限制 / 无登录设备 / 无操作记录”以及 `LoginScreen.tsx` 的“当前登录入口暂不可用”都改为 `PlatformEmptyState`,`Match3DResultView.tsx` 的引用素材列表直接复用 `PlatformAssetPickerGrid` 自己的空态;`AdventureEntityModal.tsx` 的私聊按钮、`InventoryPanel.tsx` 的锻造 / 合成按钮、`RpgCreationRoleAssetStudioModalImpl.tsx`、`RpgCreationEntityEditorShared.tsx` 里的局部 `ActionButton` 包装层,以及 `RpgAdventurePanel.tsx` / `RpgAdventurePanelOverlays.tsx` 里标准 runtime CTA 都改为委托 `PlatformActionButton surface="editorDark"`。后续白底子面板里的只读空态优先使用 `PlatformEmptyState surface="subpanel"`;暗色编辑 / 运行面板里的普通动作优先使用 `PlatformActionButton surface="editorDark"`,若业务仍需 `stopPropagation`、tone 映射、运行态 icon 排版或局部字号,可保留薄包装层,但不要再直接写原生 `<button>` 基础 chrome。
|
||||
- 决策:`CustomWorldNpcVisualEditor.tsx` 的本地 `ActionButton` 和 `SkillEffectPreview.tsx` 的“重新预览”按钮也继续并入这条暗色按钮收口线,统一委托 `PlatformActionButton surface="editorDark"`;局部包装层只保留 `stopPropagation`、图标排布、`tone` 映射和极少量视觉微调。后续暗色编辑器里的局部动作按钮若只是普通 CTA,不再新增原生 `<button>` 实现,优先沿用“薄包装 + 共享按钮本体”模式。
|
||||
- 决策:RPG 创作侧标准 dark header / footer 动作也继续纳入同一条按钮收口线。`RpgCreationRoleAssetStudioModalImpl.tsx` 的 header“关闭”、`RpgCreationEntityEditorShared.tsx` 的 footer“取消”以及 `RpgCreationRoleAssetStudioFooter.tsx` 的“保存到当前角色”都改为委托 `PlatformActionButton surface="editorDark"`;局部壳层只保留布局、宽度/字号贴合和少量 tone 语义,不再为标准 dark close / cancel / save CTA 单独维护原生 `<button>` 基础 chrome。
|
||||
- 决策:RPG runtime overlay 里的标准 dark CTA 和可点击 dark row 也继续纳入这条收口线。`RpgAdventurePanelOverlays.tsx` 的 goal panel“知道了”、任务详情里的“领取任务 / 返回交付”、任务完成提示里的“打开任务日志”都改为委托 `PlatformActionButton surface="editorDark"`;设置面板里的“运行统计”入口改为 `PlatformSubpanel as="button" surface="dark"`。像素风 choice button、HUD launcher、奖励物品格和输入 composer 保持 runtime 专属语义,不继续硬并到普通平台按钮。
|
||||
- 验证方式:`npm run test -- src/components/common/PlatformAsyncStatePanel.test.tsx src/components/platform-entry/PlatformProfileReferralModal.test.tsx src/components/platform-entry/PlatformProfileWalletLedgerModal.test.tsx src/components/platform-entry/PlatformProfilePlayedWorksModal.test.tsx src/components/platform-entry/PlatformProfileTaskCenterModal.test.tsx src/components/platform-entry/PlatformProfileRechargeModal.test.tsx src/components/common/PlatformSegmentedTabs.test.tsx src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx`、`npm run test -- src/components/common/PlatformModalCloseButton.test.tsx src/components/PixelCloseButton.test.tsx src/components/CharacterChatModal.test.tsx src/components/MapModal.test.tsx`、`npm run test -- src/components/common/useMudPointConfirmController.test.tsx src/components/match3d-result/Match3DResultView.test.tsx src/components/unified-creation/workspaces/PuzzleCreationWorkspace.interaction.test.tsx src/components/unified-creation/workspaces/Match3DCreationWorkspace.interaction.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/platform-entry/PlatformProfileRechargeModal.test.tsx src/components/CustomWorldEntityEditorModal.test.tsx src/components/rpg-creation-result/RpgCreationResultActionBar.test.tsx src/components/unified-creation/shared/PuzzleHistoryAssetPickerDialog.test.tsx src/components/puzzle-result/PuzzleResultView.test.tsx`、`npm run test -- src/components/common/CopyFeedbackButton.test.tsx src/components/common/PlatformActionButton.test.tsx src/components/AdventureEntityModal.test.tsx src/components/InventoryPanel.test.tsx src/components/rpg-creation-result/RpgCreationAssetDebugPanel.test.tsx src/components/visual-novel-result/VisualNovelResultView.test.tsx src/components/common/PlatformEmptyState.test.tsx src/components/rpg-creation-asset-studio/RpgCreationRoleAssetStudioModal.test.tsx src/components/auth/AccountModal.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.npcChat.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.questOffer.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。
|
||||
|
||||
## 2026-05-26 敲木鱼发布后作品架与推荐流刷新口径
|
||||
|
||||
@@ -266,6 +266,7 @@
|
||||
21. 图片编辑面板中的白底胶囊开关迁移到 `PlatformPillSwitch`;通用创作图片面板和抓大鹅封面编辑的 `AI重绘` 已先迁移。后续同类开关只保留受控布尔值和状态变更回调,switch 输入语义、轨道、圆点、白底浮层和禁用态统一由 Module 承接。
|
||||
22. 设置面板、结果页运行配置和工作台白底配置项中的整行开关迁移到 `PlatformToggleRow`;视觉小说结果页、runtime 设置面板和拼消消创作工作台 AI 生成底图开关已先迁移。后续整行配置项只保留字段写回和可选点击动作,不再重复开关行 chrome、checkbox class 或状态 pill。
|
||||
22.1. RPG 创作侧标准 dark header / footer 动作继续向共享按钮收口:`RpgCreationRoleAssetStudioModalImpl.tsx` 的 header“关闭”、`RpgCreationEntityEditorShared.tsx` 的 footer“取消”、`RpgCreationRoleAssetStudioFooter.tsx` 的“保存到当前角色”都改为委托 `PlatformActionButton surface="editorDark"`。局部壳层只继续保留 `stopPropagation`、tone 映射、布局和极少量字号/宽度贴合;标准暗色编辑器里的 close / cancel / save CTA 不再各自手写原生 `<button>` 基础 chrome。
|
||||
22.2. RPG runtime overlay 里的标准 dark CTA 和可点击 dark row 继续向共享原子收口:`RpgAdventurePanelOverlays.tsx` 的 goal panel“知道了”、任务详情里的“领取任务 / 返回交付”、任务完成提示里的“打开任务日志”都改为委托 `PlatformActionButton surface="editorDark"`;设置面板里的“运行统计”入口改为 `PlatformSubpanel as="button" surface="dark"`。像素风 choice button、HUD launcher、奖励物品格和输入 composer 这类 runtime 专属控件继续保留独立语义,不并回普通平台按钮。
|
||||
|
||||
## 验证
|
||||
|
||||
|
||||
@@ -351,7 +351,11 @@ test('quest offer accept button reuses the shared accepted-quest follow-up chain
|
||||
expect(affinityRewardClassName).toContain('border-rose-300/18');
|
||||
expect(currencyRewardClassName).toContain('border-amber-300/18');
|
||||
expect(experienceRewardClassName).toContain('border-sky-400/18');
|
||||
await user.click(await screen.findByRole('button', { name: '领取任务' }));
|
||||
const acceptButton = await screen.findByRole('button', { name: '领取任务' });
|
||||
expect(acceptButton.className).toContain(
|
||||
'platform-action-button--editor-dark',
|
||||
);
|
||||
await user.click(acceptButton);
|
||||
|
||||
expect((await screen.findAllByText('任务进度:0/1')).length).toBeGreaterThan(
|
||||
0,
|
||||
@@ -452,7 +456,12 @@ test('adventure statistics panel reuses dark PlatformSubpanel chrome', async ()
|
||||
render(<QuestOfferHarness />);
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '打开设置' }));
|
||||
await user.click(await screen.findByRole('button', { name: /运行统计/u }));
|
||||
const statsEntryButton = await screen.findByRole('button', {
|
||||
name: /运行统计/u,
|
||||
});
|
||||
expect(statsEntryButton.className).toContain('bg-black/25');
|
||||
expect(statsEntryButton.className).toContain('border-white/10');
|
||||
await user.click(statsEntryButton);
|
||||
|
||||
const statsTitle = await screen.findByText('冒险统计');
|
||||
const statsDialog = statsTitle.closest('.pixel-modal-shell');
|
||||
@@ -496,9 +505,13 @@ test('quest completion notice reuses dark PlatformSubpanel chrome', async () =>
|
||||
|
||||
const noticeText = await screen.findByText('可前往任务日志领取奖励。');
|
||||
const noticeClassName = findNearestClassName(noticeText, 'bg-black/25');
|
||||
const openQuestLogButton = screen.getByRole('button', { name: '打开任务日志' });
|
||||
|
||||
expect(screen.getByText('奖励已准备')).toBeTruthy();
|
||||
expect(noticeClassName).toContain('border-emerald-400/15');
|
||||
expect(openQuestLogButton.className).toContain(
|
||||
'platform-action-button--editor-dark',
|
||||
);
|
||||
});
|
||||
|
||||
test('battle reward modal reuses dark PlatformSubpanel chrome', async () => {
|
||||
|
||||
@@ -1042,17 +1042,16 @@ export function RpgAdventurePanelOverlays({
|
||||
查看任务
|
||||
</PlatformActionButton>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
<PlatformActionButton
|
||||
surface="editorDark"
|
||||
tone="primary"
|
||||
size="xxs"
|
||||
shape="pill"
|
||||
onClick={closeGoalPanel}
|
||||
className="pixel-nine-slice pixel-pressable px-4 py-2 text-xs text-white"
|
||||
style={getNineSliceStyle(UI_CHROME.choiceButton, {
|
||||
paddingX: 14,
|
||||
paddingY: 8,
|
||||
})}
|
||||
className="px-4 py-2 text-xs"
|
||||
>
|
||||
知道了
|
||||
</button>
|
||||
</PlatformActionButton>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
@@ -1126,10 +1125,14 @@ export function RpgAdventurePanelOverlays({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
<PlatformSubpanel
|
||||
as="button"
|
||||
type="button"
|
||||
onClick={() => setIsStatsPanelOpen(true)}
|
||||
className="w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-3 text-left transition hover:border-white/20"
|
||||
surface="dark"
|
||||
radius="sm"
|
||||
padding="sm"
|
||||
className="w-full text-left transition hover:border-white/20"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div>
|
||||
@@ -1142,7 +1145,7 @@ export function RpgAdventurePanelOverlays({
|
||||
</div>
|
||||
<BarChart3 className="h-4 w-4 text-amber-200/75" />
|
||||
</div>
|
||||
</button>
|
||||
</PlatformSubpanel>
|
||||
|
||||
<PlatformActionButton
|
||||
surface="editorDark"
|
||||
@@ -1463,8 +1466,11 @@ export function RpgAdventurePanelOverlays({
|
||||
|
||||
{isPendingSelectedQuest && (
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
type="button"
|
||||
<PlatformActionButton
|
||||
surface="editorDark"
|
||||
tone="primary"
|
||||
size="xs"
|
||||
shape="pill"
|
||||
onClick={() => {
|
||||
const acceptedQuestId = onAcceptPendingNpcQuestOffer();
|
||||
if (!acceptedQuestId) return;
|
||||
@@ -1472,31 +1478,24 @@ export function RpgAdventurePanelOverlays({
|
||||
setSelectedRewardItemId(null);
|
||||
setSelectedBattleRewardItemId(null);
|
||||
}}
|
||||
className="pixel-nine-slice pixel-pressable px-4 py-2 text-xs text-white"
|
||||
style={getNineSliceStyle(UI_CHROME.choiceButton, {
|
||||
paddingX: 14,
|
||||
paddingY: 8,
|
||||
})}
|
||||
>
|
||||
领取任务
|
||||
</button>
|
||||
</PlatformActionButton>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isQuestReadyToClaim(selectedQuest) &&
|
||||
!isPendingSelectedQuest && (
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
type="button"
|
||||
<PlatformActionButton
|
||||
surface="editorDark"
|
||||
tone="ghost"
|
||||
size="xs"
|
||||
shape="pill"
|
||||
onClick={() => setSelectedQuestId(null)}
|
||||
className="pixel-nine-slice pixel-pressable px-4 py-2 text-xs text-white"
|
||||
style={getNineSliceStyle(UI_CHROME.choiceButton, {
|
||||
paddingX: 14,
|
||||
paddingY: 8,
|
||||
})}
|
||||
>
|
||||
返回交付
|
||||
</button>
|
||||
</PlatformActionButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -1548,8 +1547,11 @@ export function RpgAdventurePanelOverlays({
|
||||
: '可前往任务日志领取奖励。'}
|
||||
</PlatformSubpanel>
|
||||
<div className="flex justify-center">
|
||||
<button
|
||||
type="button"
|
||||
<PlatformActionButton
|
||||
surface="editorDark"
|
||||
tone="primary"
|
||||
size="xs"
|
||||
shape="pill"
|
||||
onClick={() => {
|
||||
questUi.acknowledgeQuestCompletion(
|
||||
completionNoticeQuest.id,
|
||||
@@ -1557,14 +1559,9 @@ export function RpgAdventurePanelOverlays({
|
||||
setCompletionNoticeQuestId(null);
|
||||
setIsQuestPanelOpen(true);
|
||||
}}
|
||||
className="pixel-nine-slice pixel-pressable px-4 py-2 text-xs text-white"
|
||||
style={getNineSliceStyle(UI_CHROME.choiceButton, {
|
||||
paddingX: 14,
|
||||
paddingY: 8,
|
||||
})}
|
||||
>
|
||||
打开任务日志
|
||||
</button>
|
||||
</PlatformActionButton>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
Reference in New Issue
Block a user