收口个人中心邀请弹窗组件

迁移社区二维码卡和邀请信息卡到 PlatformSubpanel

迁移邀请弹窗简单空态到 PlatformEmptyState

迁移邀请弹窗小标题到 PlatformFieldLabel

补充邀请弹窗公共组件断言并更新文档和 Hermes
This commit is contained in:
2026-06-10 12:17:45 +08:00
parent c1905d52ac
commit 66b73f5a1d
4 changed files with 67 additions and 18 deletions

View File

@@ -69,6 +69,7 @@
- 2026-06-10 追加:个人中心存档 / 玩过弹窗里的简单空态使用 `PlatformEmptyState surface="subpanel" size="inline"`,玩过弹窗的“可继续 / 玩过”分区标题使用 `PlatformFieldLabel variant="section"`,已玩作品白底按钮卡使用 `PlatformSubpanel as="button" surface="flat" radius="sm" padding="md" interactive``SaveArchiveCard` 因含图片遮罩和加载态暂不并入本轮。 - 2026-06-10 追加:个人中心存档 / 玩过弹窗里的简单空态使用 `PlatformEmptyState surface="subpanel" size="inline"`,玩过弹窗的“可继续 / 玩过”分区标题使用 `PlatformFieldLabel variant="section"`,已玩作品白底按钮卡使用 `PlatformSubpanel as="button" surface="flat" radius="sm" padding="md" interactive``SaveArchiveCard` 因含图片遮罩和加载态暂不并入本轮。
- 2026-06-10 追加:平台入口壳纯 Suspense fallback 使用 `PlatformSubpanel radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳;带恢复动作、错误语义或运行态遮罩的提示面板不和纯加载 fallback 同批迁移。 - 2026-06-10 追加:平台入口壳纯 Suspense fallback 使用 `PlatformSubpanel radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳;带恢复动作、错误语义或运行态遮罩的提示面板不和纯加载 fallback 同批迁移。
- 2026-06-10 追加:个人中心钱包账单弹窗的“暂无账单记录”使用 `PlatformEmptyState surface="subpanel" size="inline"`,账单行使用 `PlatformSubpanel as="div" surface="flat" radius="xs" padding="none"`;业务 JSX 只保留来源、时间、收支色值、余额右对齐和局部间距 / 阴影。 - 2026-06-10 追加:个人中心钱包账单弹窗的“暂无账单记录”使用 `PlatformEmptyState surface="subpanel" size="inline"`,账单行使用 `PlatformSubpanel as="div" surface="flat" radius="xs" padding="none"`;业务 JSX 只保留来源、时间、收支色值、余额右对齐和局部间距 / 阴影。
- 2026-06-10 追加:个人中心邀请弹窗里的社区二维码卡、邀请码展示卡、成功邀请容器和邀请用户行使用 `PlatformSubpanel`,简单空态使用 `PlatformEmptyState`,小标题使用 `PlatformFieldLabel variant="section"`外层弹窗、query 自动打开、复制邀请和提交邀请码状态机不随 UI chrome 收口改动。
- 2026-06-09 追加:抓大鹅结果页作品信息、发布封面和物品素材详情中的 section 字段标题迁移到 `PlatformFieldLabel variant="section"`;业务页不再重复拼 `text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]` - 2026-06-09 追加:抓大鹅结果页作品信息、发布封面和物品素材详情中的 section 字段标题迁移到 `PlatformFieldLabel variant="section"`;业务页不再重复拼 `text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]`
- 2026-06-09 追加:方洞结果页主信息、形状选项、洞口选项和历史生成标题迁移到 `PlatformFieldLabel variant="section"`;业务页只保留字段文案、图标和按钮布局,不再重复拼 section 标题 class。 - 2026-06-09 追加:方洞结果页主信息、形状选项、洞口选项和历史生成标题迁移到 `PlatformFieldLabel variant="section"`;业务页只保留字段文案、图标和按钮布局,不再重复拼 section 标题 class。
- 2026-06-09 追加:拼图结果页关卡详情的“关卡名称”和发布弹窗的“发布检查 / 封面关卡”标题迁移到 `PlatformFieldLabel variant="section"`;业务页保留 label 关联和弹窗布局,不再重复拼 section 标题 class。 - 2026-06-09 追加:拼图结果页关卡详情的“关卡名称”和发布弹窗的“发布检查 / 封面关卡”标题迁移到 `PlatformFieldLabel variant="section"`;业务页保留 label 关联和弹窗布局,不再重复拼 section 标题 class。
@@ -258,6 +259,7 @@
- 2026-06-10 验证补充:个人中心存档 / 玩过弹窗简单空态、分区标题和已玩作品按钮卡收口后,补跑 `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "profile played modal|profile page keeps save archives inside played stats panel"` - 2026-06-10 验证补充:个人中心存档 / 玩过弹窗简单空态、分区标题和已玩作品按钮卡收口后,补跑 `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "profile played modal|profile page keeps save archives inside played stats panel"`
- 2026-06-10 验证补充:平台入口壳纯 Suspense fallback 收口到 `PlatformSubpanel` 后,补跑 `npm run test -- src/components/common/PlatformSubpanel.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts` - 2026-06-10 验证补充:平台入口壳纯 Suspense fallback 收口到 `PlatformSubpanel` 后,补跑 `npm run test -- src/components/common/PlatformSubpanel.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts`
- 2026-06-10 验证补充:个人中心钱包账单空态和账单行收口后,补跑 `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "wallet ledger"``npm run test -- src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformSubpanel.test.tsx` - 2026-06-10 验证补充:个人中心钱包账单空态和账单行收口后,补跑 `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "wallet ledger"``npm run test -- src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformSubpanel.test.tsx`
- 2026-06-10 验证补充:个人中心邀请弹窗内部卡片、标题和空态收口后,补跑 `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "profile community shortcut|profile redeem invite"``npm run test -- src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformFieldLabel.test.tsx src/components/common/PlatformSubpanel.test.tsx`
- 2026-06-10 验证补充:个人中心兑换码 / 邀请码输入和充值 / 任务空态收口后,补跑 `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/common/PlatformTextField.test.tsx src/components/common/PlatformEmptyState.test.tsx -t "reward code|invite query|profile redeem invite|daily task"` - 2026-06-10 验证补充:个人中心兑换码 / 邀请码输入和充值 / 任务空态收口后,补跑 `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/common/PlatformTextField.test.tsx src/components/common/PlatformEmptyState.test.tsx -t "reward code|invite query|profile redeem invite|daily task"`
- 2026-06-10 验证补充:背包文书按钮收口到暗色 `PlatformSubpanel`、故事档案 QA 提示收口到 `PlatformStatusMessage surface="editorDark"` 后,补跑 `npm run test -- src/components/InventoryPanel.test.tsx src/components/common/PlatformSubpanel.test.tsx src/components/common/PlatformStatusMessage.test.tsx` - 2026-06-10 验证补充:背包文书按钮收口到暗色 `PlatformSubpanel`、故事档案 QA 提示收口到 `PlatformStatusMessage surface="editorDark"` 后,补跑 `npm run test -- src/components/InventoryPanel.test.tsx src/components/common/PlatformSubpanel.test.tsx src/components/common/PlatformStatusMessage.test.tsx`
- 2026-06-10 验证补充NPC 叙事提示和交易详情属性格收口后,补跑 `npm run test -- src/components/NpcModals.test.tsx src/components/common/PlatformSubpanel.test.tsx src/components/common/PlatformStatusMessage.test.tsx` - 2026-06-10 验证补充NPC 叙事提示和交易详情属性格收口后,补跑 `npm run test -- src/components/NpcModals.test.tsx src/components/common/PlatformSubpanel.test.tsx src/components/common/PlatformStatusMessage.test.tsx`

View File

@@ -68,11 +68,13 @@
- `PlatformEmptyState`:接收 `surface="soft" | "dashed" | "subpanel" | "editorDark"``size="compact" | "panel" | "inline"``tone="base" | "soft"``children``className`;根节点固定带 `platform-empty-state` 稳定类名,业务测试可断言公共空态接入。`soft + compact` 用于公开广场、排行和作品架内的轻量空态,`soft + panel` 用于创作中心作品架整块空态,`dashed + panel` 用于素材选择、历史资源等弹窗的大面积空态或读取态,`subpanel + inline` 用于视觉小说 runtime、个人中心充值 / 任务等白底子面板内的无操作空态,`editorDark + compact/inline` 用于 RPG 大编辑器、实体详情弹窗、营地编组、角色聊天和运行态设置弹窗等暗色面板里的纯展示空态 / 禁用提示。组件只承接外观,不内置业务文案。 - `PlatformEmptyState`:接收 `surface="soft" | "dashed" | "subpanel" | "editorDark"``size="compact" | "panel" | "inline"``tone="base" | "soft"``children``className`;根节点固定带 `platform-empty-state` 稳定类名,业务测试可断言公共空态接入。`soft + compact` 用于公开广场、排行和作品架内的轻量空态,`soft + panel` 用于创作中心作品架整块空态,`dashed + panel` 用于素材选择、历史资源等弹窗的大面积空态或读取态,`subpanel + inline` 用于视觉小说 runtime、个人中心充值 / 任务等白底子面板内的无操作空态,`editorDark + compact/inline` 用于 RPG 大编辑器、实体详情弹窗、营地编组、角色聊天和运行态设置弹窗等暗色面板里的纯展示空态 / 禁用提示。组件只承接外观,不内置业务文案。
- `PlatformEmptyState` 补充:个人中心存档弹窗和玩过弹窗里的简单“暂无存档 / 暂无玩过”也使用 `surface="subpanel" size="inline"`;玩过弹窗可通过 `tone="base"` 和局部 `text-left` 保留原有白底列表语境,不在业务 JSX 重复写 `rounded-xl bg-zinc-50 px-4 py-* text-sm` - `PlatformEmptyState` 补充:个人中心存档弹窗和玩过弹窗里的简单“暂无存档 / 暂无玩过”也使用 `surface="subpanel" size="inline"`;玩过弹窗可通过 `tone="base"` 和局部 `text-left` 保留原有白底列表语境,不在业务 JSX 重复写 `rounded-xl bg-zinc-50 px-4 py-* text-sm`
- `PlatformEmptyState` 补充:个人中心钱包账单弹窗里的“暂无账单记录”使用 `surface="subpanel" size="inline"`;业务组件只保留外边距和纵向留白,不再手写白底空态边框、字号和居中文案。 - `PlatformEmptyState` 补充:个人中心钱包账单弹窗里的“暂无账单记录”使用 `surface="subpanel" size="inline"`;业务组件只保留外边距和纵向留白,不再手写白底空态边框、字号和居中文案。
- `PlatformEmptyState` 补充:个人中心邀请弹窗里的“已填写邀请码 / 暂无成功邀请”使用 `surface="subpanel"`;业务组件保留面板分支和邀请状态机,不再为无操作提示手写白底空态。
- `PlatformTextField`:接收 `variant="input" | "textarea"``surface="platform" | "editorDark"``size="xs" | "sm" | "md" | "lg"``density="default" | "compact" | "roomy"``tone="warm" | "rose" | "emerald" | "sky"``className` 和原生 input / textarea props统一承接平台白底与 RPG 暗色弹窗里的圆角输入框、文本域、禁用态、密度、字号 / 行高和焦点色,暗色 surface 根节点固定带 `platform-text-field--editor-dark` 稳定类名。`PlatformSelectField` 复用同一套输入 chrome 承接下拉框。业务页继续持有 `value``onChange``aria-label``rows``placeholder``option` 等语义,不再重复拼 `rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/86 px-3 py-3``rounded-[0.85rem] bg-white/90 px-3 py-2``bg-white/90 px-4 py-3`、暗色 `border-white/10 bg-black/30 px-4 py-3``focus:border-* focus:ring-*`。抓大鹅结果页作品信息、封面描述、素材名称和批量物品名称,方洞结果页主信息表单和形状 / 洞口选项字段,拼图 / 敲木鱼结果页作品信息字段,视觉小说结果页的音乐生成、作品信息、开场、运行配置、角色、场景、阶段和世界观普通文本 / 下拉字段,以及视觉小说 / 抓大鹅 / 汪汪声浪 / 宝贝识物 / 拼消消 / 跳一跳创作工作台普通输入字段已先迁移;自定义选择弹窗角色名字 / 背景补充 / 生成模式 / 世界描述和角色聊天草稿等暗色字段使用 `surface="editorDark"`。通用创作图片输入面板的提示词文本域也使用该 Module只通过局部 class 保留高度和底部浮动上传按钮避让。认证图形验证码答案、短信 / 密码登录、重置密码、绑定手机号、邀请码和账号安全表单字段,以及个人中心兑换码 / 邀请码输入使用 `surface="platform"`,业务层只保留认证 / 兑换流程、受控值、原生属性和校验提示。 - `PlatformTextField`:接收 `variant="input" | "textarea"``surface="platform" | "editorDark"``size="xs" | "sm" | "md" | "lg"``density="default" | "compact" | "roomy"``tone="warm" | "rose" | "emerald" | "sky"``className` 和原生 input / textarea props统一承接平台白底与 RPG 暗色弹窗里的圆角输入框、文本域、禁用态、密度、字号 / 行高和焦点色,暗色 surface 根节点固定带 `platform-text-field--editor-dark` 稳定类名。`PlatformSelectField` 复用同一套输入 chrome 承接下拉框。业务页继续持有 `value``onChange``aria-label``rows``placeholder``option` 等语义,不再重复拼 `rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/86 px-3 py-3``rounded-[0.85rem] bg-white/90 px-3 py-2``bg-white/90 px-4 py-3`、暗色 `border-white/10 bg-black/30 px-4 py-3``focus:border-* focus:ring-*`。抓大鹅结果页作品信息、封面描述、素材名称和批量物品名称,方洞结果页主信息表单和形状 / 洞口选项字段,拼图 / 敲木鱼结果页作品信息字段,视觉小说结果页的音乐生成、作品信息、开场、运行配置、角色、场景、阶段和世界观普通文本 / 下拉字段,以及视觉小说 / 抓大鹅 / 汪汪声浪 / 宝贝识物 / 拼消消 / 跳一跳创作工作台普通输入字段已先迁移;自定义选择弹窗角色名字 / 背景补充 / 生成模式 / 世界描述和角色聊天草稿等暗色字段使用 `surface="editorDark"`。通用创作图片输入面板的提示词文本域也使用该 Module只通过局部 class 保留高度和底部浮动上传按钮避让。认证图形验证码答案、短信 / 密码登录、重置密码、绑定手机号、邀请码和账号安全表单字段,以及个人中心兑换码 / 邀请码输入使用 `surface="platform"`,业务层只保留认证 / 兑换流程、受控值、原生属性和校验提示。
- `PlatformTextField` 补充:个人中心昵称弹窗输入框使用 `surface="editorDark" size="lg" density="roomy"`,业务组件保留外层原生 `label` / sr-only “新昵称”、`autoFocus``maxLength`、Enter 提交和保存状态;局部 class 只保留暗色弹窗里的 `bg-white/10`、文字色和焦点边框,不再手写 input chrome。 - `PlatformTextField` 补充:个人中心昵称弹窗输入框使用 `surface="editorDark" size="lg" density="roomy"`,业务组件保留外层原生 `label` / sr-only “新昵称”、`autoFocus``maxLength`、Enter 提交和保存状态;局部 class 只保留暗色弹窗里的 `bg-white/10`、文字色和焦点边框,不再手写 input chrome。
- `PlatformTextField` 补充:`PlatformTagEditor` 内部新增标签输入框使用 `density="compact" size="xs"` 复用同一输入 chrome标签编辑器只保留新增输入状态、解析、Enter / Escape 行为和按钮组合,不再手写输入框边框、白底、字号、焦点色或禁用态。 - `PlatformTextField` 补充:`PlatformTagEditor` 内部新增标签输入框使用 `density="compact" size="xs"` 复用同一输入 chrome标签编辑器只保留新增输入状态、解析、Enter / Escape 行为和按钮组合,不再手写输入框边框、白底、字号、焦点色或禁用态。
- `PlatformFieldLabel`:接收 `variant="field" | "section" | "form" | "pill" | "accentPill"``children``className``field` 用于视觉小说等结果页的普通字段名,`section` 用于平台白底面板内小标题,`form` 用于创作工作台、通用创作输入面板和认证表单普通字段标题,`pill` / `accentPill` 用于汪汪声浪等工作台里的胶囊字段标题。业务页只传字段文案和必要的局部 class不再重复写 `text-xs font-bold text-[var(--platform-text-soft)]``text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]``mb-2 block text-sm font-black`、普通胶囊或 rose 强调胶囊 class。视觉小说结果页、抓大鹅结果页作品 / 封面 / 素材字段标题、方洞结果页主信息 / 形状 / 洞口 / 历史图片字段标题、拼图结果页关卡详情 / 发布弹窗字段标题、拼消消创作工作台作品标题 / 简介 / 主题词、跳一跳创作工作台主题、大鱼素材弹窗 prompt、RPG 发布弹窗发布检查 / 封面设置、汪汪声浪轻配置编辑器、宝贝识物工作台、通用创作图片输入面板主图 / 提示词标题,以及认证表单中的手机号 / 验证码 / 密码 / 邀请码标题已先迁移。认证和提示词字段继续保留外层原生 `label` 关联,不把可访问命名交给装饰性标题组件。 - `PlatformFieldLabel`:接收 `variant="field" | "section" | "form" | "pill" | "accentPill"``children``className``field` 用于视觉小说等结果页的普通字段名,`section` 用于平台白底面板内小标题,`form` 用于创作工作台、通用创作输入面板和认证表单普通字段标题,`pill` / `accentPill` 用于汪汪声浪等工作台里的胶囊字段标题。业务页只传字段文案和必要的局部 class不再重复写 `text-xs font-bold text-[var(--platform-text-soft)]``text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]``mb-2 block text-sm font-black`、普通胶囊或 rose 强调胶囊 class。视觉小说结果页、抓大鹅结果页作品 / 封面 / 素材字段标题、方洞结果页主信息 / 形状 / 洞口 / 历史图片字段标题、拼图结果页关卡详情 / 发布弹窗字段标题、拼消消创作工作台作品标题 / 简介 / 主题词、跳一跳创作工作台主题、大鱼素材弹窗 prompt、RPG 发布弹窗发布检查 / 封面设置、汪汪声浪轻配置编辑器、宝贝识物工作台、通用创作图片输入面板主图 / 提示词标题,以及认证表单中的手机号 / 验证码 / 密码 / 邀请码标题已先迁移。认证和提示词字段继续保留外层原生 `label` 关联,不把可访问命名交给装饰性标题组件。
- `PlatformFieldLabel` 补充:个人中心玩过弹窗内的“可继续 / 玩过”分区标题使用 `variant="section"`;业务组件只传分区文案和 `mb-2 block` 局部布局,不再手写 `text-xs font-black text-zinc-500` - `PlatformFieldLabel` 补充:个人中心玩过弹窗内的“可继续 / 玩过”分区标题使用 `variant="section"`;业务组件只传分区文案和 `mb-2 block` 局部布局,不再手写 `text-xs font-black text-zinc-500`
- `PlatformFieldLabel` 补充:个人中心邀请弹窗里的“邀请码 / 成功邀请”小标题使用 `variant="section"`;业务组件只保留必要的居中或深色文本局部 class不再手写同类小标题字体。
- `PlatformSegmentedTabs`:接收 `items``activeId``onChange``columns="one" | "two" | "three" | "four" | "threeToSix"``gap="sm" | "md"``radius="md" | "lg" | "xl"``size="sm" | "md" | "compact" | "choice" | "tab"``surface="default" | "soft" | "transparent"``tone="neutral" | "warm" | "rose" | "underline"``frame="panel" | "bare"``semantics="segment" | "tabs"``ariaLabel``truncateLabels``disabled``className``itemClassName`;普通分段统一写入 `aria-pressed`Tab 语义统一写入 `role="tablist"` / `role="tab"` / `aria-selected`,并承载禁用阻断、白底选中态、空闲 hover、焦点 ring、响应式列数、裸分段外壳、下划线选中态和 label 截断。拼图结果页、抓大鹅结果页、抓大鹅素材配置、抓大鹅创作 / 结果页难度选择、视觉小说结果页、creative-agent 模板确认弹窗和认证入口短信 / 密码登录切换已先迁移。后续白底结果页 Tab、弹窗分段选择、四选一配置项或认证 / 设置类下划线 Tab 只传选项、当前值和变更回调,不再重复 `grid + border + bg-white/62 + button aria-pressed` 或本地 `role="tab"` 下划线按钮。 - `PlatformSegmentedTabs`:接收 `items``activeId``onChange``columns="one" | "two" | "three" | "four" | "threeToSix"``gap="sm" | "md"``radius="md" | "lg" | "xl"``size="sm" | "md" | "compact" | "choice" | "tab"``surface="default" | "soft" | "transparent"``tone="neutral" | "warm" | "rose" | "underline"``frame="panel" | "bare"``semantics="segment" | "tabs"``ariaLabel``truncateLabels``disabled``className``itemClassName`;普通分段统一写入 `aria-pressed`Tab 语义统一写入 `role="tablist"` / `role="tab"` / `aria-selected`,并承载禁用阻断、白底选中态、空闲 hover、焦点 ring、响应式列数、裸分段外壳、下划线选中态和 label 截断。拼图结果页、抓大鹅结果页、抓大鹅素材配置、抓大鹅创作 / 结果页难度选择、视觉小说结果页、creative-agent 模板确认弹窗和认证入口短信 / 密码登录切换已先迁移。后续白底结果页 Tab、弹窗分段选择、四选一配置项或认证 / 设置类下划线 Tab 只传选项、当前值和变更回调,不再重复 `grid + border + bg-white/62 + button aria-pressed` 或本地 `role="tab"` 下划线按钮。
- `PlatformStatGrid`:接收 `items``columns="two" | "three" | "four" | "twoToFour"``density="compact" | "default"``order="valueFirst" | "labelFirst"``surface="soft" | "plain"``textAlign="left" | "center"``className``itemClassName`;统一承载平台结果页里的统计小卡、状态 chip、白底摘要卡、label/value 排版和响应式列数。拼消消结果页素材摘要、方洞结果页封面状态 chip、抓大鹅结果页难度摘要、creative-agent 模板确认摘要和自定义世界实体目录世界页档案规模已先迁移,业务页只传统计项数组和少量布局参数,不再重复写 `grid + rounded + bg-white/* + text-xl/text-xs` - `PlatformStatGrid`:接收 `items``columns="two" | "three" | "four" | "twoToFour"``density="compact" | "default"``order="valueFirst" | "labelFirst"``surface="soft" | "plain"``textAlign="left" | "center"``className``itemClassName`;统一承载平台结果页里的统计小卡、状态 chip、白底摘要卡、label/value 排版和响应式列数。拼消消结果页素材摘要、方洞结果页封面状态 chip、抓大鹅结果页难度摘要、creative-agent 模板确认摘要和自定义世界实体目录世界页档案规模已先迁移,业务页只传统计项数组和少量布局参数,不再重复写 `grid + rounded + bg-white/* + text-xl/text-xs`
- `PlatformPillBadge`:接收 `tone="muted" | "neutral" | "neutralSolid" | "lightOverlay" | "success" | "warning" | "danger" | "cool" | "profile" | "profileAccent" | "darkSoft" | "darkNeutral" | "darkSky" | "darkEmerald" | "darkAmber" | "darkRose"``size="xxs" | "xs" | "sm"`、可选 `icon``children``className` 和原生 span props统一承接单个状态 / 标签 chip 的圆角、边框、底色、字号和图标间距,并通过 `platformPillBadgeModel.ts``getPlatformPillBadgeClassName` 给复制类交互按钮复用同一视觉 chrome。`xxs` 用于实体目录卡片等密集元信息 chip`muted` 用于平台白底柔和选择态和地图节点当前状态,`lightOverlay` 用于主动作按钮内部的泥点消耗等浅色叠层小胶囊,`danger` 用于删除 / 选中危险态,`profile` / `profileAccent` 用于个人中心玫瑰色信息 / 分类 chip`dark*` 用于 RPG 暗色弹窗和角色详情里的纯展示 chip。宝贝识物结果页发布状态、主题标签与占位资源 overlay宝贝识物 / 拼图 / 抓大鹅 / 视觉小说工作台 BETA chip、汪汪声浪轻配置 chip、汪汪声浪结果页草稿 chip、汪汪声浪预览 VS chip、敲木鱼结果页飘字 chip、creative-agent 顶部阶段 / 过程计数 / 条目 meta chip、通用音频输入面板限制标签、自定义世界实体目录批量选择 / 生成中 / 开局 CG / 可扮演角色元信息 badge、RPG 首页公开作品卡 / 搜索结果 / 充值商品 / 移动端创建入口 / 桌面发现区 chip、RPG 世界详情静态元信息 chip、RPG 角色身份 / 等级 / 技能出手方式 / 技能详情与状态标签 / 背景故事解锁状态 / 好感等级 / 角色资产工作室动作状态 / 角色编辑技能动作状态 / 角色资源应用状态 / 场景角色选择状态 / 地标当前连接状态 / 地图节点方向标签 / 地图场景切换方向标签 / 营地编组状态数值 / 作品封面来源状态 / 开局物品标签、NPC 交易数量 / 赠礼好感和背包工坊材料需求等暗色展示 chip、抓大鹅批量新增 / 批量重生成物品名称预览 chip、抓大鹅 / RPG / 拼图 / 方洞结果页自动保存状态、抓大鹅结果页当前难度 badge、拼图结果页关卡生成中 overlay / 列表 badge、大鱼吃小鱼结果页终局 / 发布校验成功 badge、拼图图库详情页题材标签、自定义世界作品卡二级 badge、生成失败 chip以及个人中心泥点账单余额、玩过总时长和玩过作品类型 chip 已先迁移。后续作品卡状态、结果页标签、个人中心轻量信息、按钮内消耗标签和轻量配置 chip 优先使用该 Module多项数值 / 标签摘要仍使用 `PlatformStatGrid`,可交互标签编辑仍使用 `PlatformTagEditor`,可点击复制 / 分享 chip 使用 `CopyCodeButton` / `CopyFeedbackButton actionAppearance="pill"` - `PlatformPillBadge`:接收 `tone="muted" | "neutral" | "neutralSolid" | "lightOverlay" | "success" | "warning" | "danger" | "cool" | "profile" | "profileAccent" | "darkSoft" | "darkNeutral" | "darkSky" | "darkEmerald" | "darkAmber" | "darkRose"``size="xxs" | "xs" | "sm"`、可选 `icon``children``className` 和原生 span props统一承接单个状态 / 标签 chip 的圆角、边框、底色、字号和图标间距,并通过 `platformPillBadgeModel.ts``getPlatformPillBadgeClassName` 给复制类交互按钮复用同一视觉 chrome。`xxs` 用于实体目录卡片等密集元信息 chip`muted` 用于平台白底柔和选择态和地图节点当前状态,`lightOverlay` 用于主动作按钮内部的泥点消耗等浅色叠层小胶囊,`danger` 用于删除 / 选中危险态,`profile` / `profileAccent` 用于个人中心玫瑰色信息 / 分类 chip`dark*` 用于 RPG 暗色弹窗和角色详情里的纯展示 chip。宝贝识物结果页发布状态、主题标签与占位资源 overlay宝贝识物 / 拼图 / 抓大鹅 / 视觉小说工作台 BETA chip、汪汪声浪轻配置 chip、汪汪声浪结果页草稿 chip、汪汪声浪预览 VS chip、敲木鱼结果页飘字 chip、creative-agent 顶部阶段 / 过程计数 / 条目 meta chip、通用音频输入面板限制标签、自定义世界实体目录批量选择 / 生成中 / 开局 CG / 可扮演角色元信息 badge、RPG 首页公开作品卡 / 搜索结果 / 充值商品 / 移动端创建入口 / 桌面发现区 chip、RPG 世界详情静态元信息 chip、RPG 角色身份 / 等级 / 技能出手方式 / 技能详情与状态标签 / 背景故事解锁状态 / 好感等级 / 角色资产工作室动作状态 / 角色编辑技能动作状态 / 角色资源应用状态 / 场景角色选择状态 / 地标当前连接状态 / 地图节点方向标签 / 地图场景切换方向标签 / 营地编组状态数值 / 作品封面来源状态 / 开局物品标签、NPC 交易数量 / 赠礼好感和背包工坊材料需求等暗色展示 chip、抓大鹅批量新增 / 批量重生成物品名称预览 chip、抓大鹅 / RPG / 拼图 / 方洞结果页自动保存状态、抓大鹅结果页当前难度 badge、拼图结果页关卡生成中 overlay / 列表 badge、大鱼吃小鱼结果页终局 / 发布校验成功 badge、拼图图库详情页题材标签、自定义世界作品卡二级 badge、生成失败 chip以及个人中心泥点账单余额、玩过总时长和玩过作品类型 chip 已先迁移。后续作品卡状态、结果页标签、个人中心轻量信息、按钮内消耗标签和轻量配置 chip 优先使用该 Module多项数值 / 标签摘要仍使用 `PlatformStatGrid`,可交互标签编辑仍使用 `PlatformTagEditor`,可点击复制 / 分享 chip 使用 `CopyCodeButton` / `CopyFeedbackButton actionAppearance="pill"`
@@ -83,6 +85,7 @@
- `PlatformSubpanel` 补充:个人中心玩过弹窗里的已玩作品按钮卡使用 `as="button" surface="flat" radius="sm" padding="md" interactive`,业务组件只保留作品标题 / 副标题 / 类型胶囊 / 作品号 / 最近游玩 / 时长内容和粉色 hover 边框,不再手写白底按钮卡 chrome。 - `PlatformSubpanel` 补充:个人中心玩过弹窗里的已玩作品按钮卡使用 `as="button" surface="flat" radius="sm" padding="md" interactive`,业务组件只保留作品标题 / 副标题 / 类型胶囊 / 作品号 / 最近游玩 / 时长内容和粉色 hover 边框,不再手写白底按钮卡 chrome。
- `PlatformSubpanel` 补充:平台入口壳纯 Suspense fallback 使用 `radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳,业务层只保留居中布局、提示文案和局部内边距;带恢复动作、错误语义或运行态遮罩的提示面板不并入这一类。 - `PlatformSubpanel` 补充:平台入口壳纯 Suspense fallback 使用 `radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳,业务层只保留居中布局、提示文案和局部内边距;带恢复动作、错误语义或运行态遮罩的提示面板不并入这一类。
- `PlatformSubpanel` 补充:个人中心钱包账单行使用 `as="div" surface="flat" radius="xs" padding="none"`,业务组件只保留来源、时间、收入 / 支出色值、余额右对齐和局部 `px-3 py-3 shadow-sm`;后续同类白底数据行优先从该组合扩展。 - `PlatformSubpanel` 补充:个人中心钱包账单行使用 `as="div" surface="flat" radius="xs" padding="none"`,业务组件只保留来源、时间、收入 / 支出色值、余额右对齐和局部 `px-3 py-3 shadow-sm`;后续同类白底数据行优先从该组合扩展。
- `PlatformSubpanel` 补充:个人中心邀请弹窗里的社区二维码卡、邀请码展示卡、成功邀请容器和邀请用户行使用 `surface="flat" | "soft"` 的白底子面板;复制按钮、奖励说明卡和弹窗状态机不并入本轮。
- `PlatformSubpanel` 补充:当前 Interface 额外支持 `padding="xs"``radius="xs"``surface="dark"`,用于 RPG 暗色编辑器 / 运行态里的非交互小信息卡。任务目标、区域、进度、描述、角色维度、角色形象状态、自定义选择弹窗当前角色、地图场景切换当前 / 前往摘要、营地编组分区、同行者卡、营地气氛小卡、角色聊天状态和聊天总结这类只展示信息的小卡走该组合;暗色 HUD、动作按钮、可点击卡片和强玩法品牌面板仍保留业务布局。 - `PlatformSubpanel` 补充:当前 Interface 额外支持 `padding="xs"``radius="xs"``surface="dark"`,用于 RPG 暗色编辑器 / 运行态里的非交互小信息卡。任务目标、区域、进度、描述、角色维度、角色形象状态、自定义选择弹窗当前角色、地图场景切换当前 / 前往摘要、营地编组分区、同行者卡、营地气氛小卡、角色聊天状态和聊天总结这类只展示信息的小卡走该组合;暗色 HUD、动作按钮、可点击卡片和强玩法品牌面板仍保留业务布局。
- `PlatformSubpanel` 补充:当前 Interface 额外支持 `surface="darkSky" | "darkEmerald" | "darkAmber" | "darkRose"`,用于 RPG 暗色编辑器 / 运行态中带业务色强调的结构化信息面板;实体详情私聊提示、队友收束、玩家等级进度、角色面板等级 / 收束状态、任务奖励好感度 / 货币 / 经验数值卡、RPG 大编辑器上传封面中提示、地图场景切换目标场景面板,以及 `CharacterInfoShared.MultiplierContributionList` 状态标签外壳已迁移,后续同类 sky / emerald / amber / rose 暗色信息壳不再手写 `border-*-400/18 bg-*-500/8` - `PlatformSubpanel` 补充:当前 Interface 额外支持 `surface="darkSky" | "darkEmerald" | "darkAmber" | "darkRose"`,用于 RPG 暗色编辑器 / 运行态中带业务色强调的结构化信息面板;实体详情私聊提示、队友收束、玩家等级进度、角色面板等级 / 收束状态、任务奖励好感度 / 货币 / 经验数值卡、RPG 大编辑器上传封面中提示、地图场景切换目标场景面板,以及 `CharacterInfoShared.MultiplierContributionList` 状态标签外壳已迁移,后续同类 sky / emerald / amber / rose 暗色信息壳不再手写 `border-*-400/18 bg-*-500/8`
- `PlatformSubpanel` 补充RPG 大编辑器里的标题型暗色信息块通过本地 `EditorInfoPanel` 适配到 `surface="dark" radius="md" padding="md"`;场景幕角色槽位的当前角色 / 可选角色面板、幕背景预览面板和预设背景面板已迁移。业务 JSX 只保留标题、内容和局部 grid不再重复拼 `rounded-2xl border border-white/8 bg-black/20 px-4 py-4` - `PlatformSubpanel` 补充RPG 大编辑器里的标题型暗色信息块通过本地 `EditorInfoPanel` 适配到 `surface="dark" radius="md" padding="md"`;场景幕角色槽位的当前角色 / 可选角色面板、幕背景预览面板和预设背景面板已迁移。业务 JSX 只保留标题、内容和局部 grid不再重复拼 `rounded-2xl border border-white/8 bg-black/20 px-4 py-4`
@@ -143,6 +146,7 @@
18.3.1. 个人中心存档 / 玩过弹窗里的简单空态、分区标题和已玩作品白底按钮卡分别迁移到 `PlatformEmptyState``PlatformFieldLabel``PlatformSubpanel``SaveArchiveCard` 带图片遮罩和加载视觉,仍保留专用实现,后续需要单独视觉验收后再决定是否收口。 18.3.1. 个人中心存档 / 玩过弹窗里的简单空态、分区标题和已玩作品白底按钮卡分别迁移到 `PlatformEmptyState``PlatformFieldLabel``PlatformSubpanel``SaveArchiveCard` 带图片遮罩和加载视觉,仍保留专用实现,后续需要单独视觉验收后再决定是否收口。
18.3.2. 平台入口壳中的纯 Suspense fallback 迁移到 `PlatformSubpanel`;只处理无按钮、无错误态、无运行态层级语义的加载提示,`CreationResultRecoveryPanel`、详情错误提示和玩法 runtime overlay 后续单独评估。 18.3.2. 平台入口壳中的纯 Suspense fallback 迁移到 `PlatformSubpanel`;只处理无按钮、无错误态、无运行态层级语义的加载提示,`CreationResultRecoveryPanel`、详情错误提示和玩法 runtime overlay 后续单独评估。
18.3.3. 个人中心钱包账单弹窗里的空态和账单行分别迁移到 `PlatformEmptyState``PlatformSubpanel`;账单展示只保留收支内容、余额和时间,不在业务 JSX 重复白底列表行 chrome。 18.3.3. 个人中心钱包账单弹窗里的空态和账单行分别迁移到 `PlatformEmptyState``PlatformSubpanel`;账单展示只保留收支内容、余额和时间,不在业务 JSX 重复白底列表行 chrome。
18.3.4. 个人中心邀请弹窗内部的二维码卡、邀请码卡、成功邀请列表、邀请用户行、小标题和简单空态分别迁移到 `PlatformSubpanel``PlatformFieldLabel``PlatformEmptyState`外层弹窗、query 自动打开、复制邀请、提交邀请码和社区面板信息架构不随本轮改变。
18.4. 平台白底分段 Tab / 二选一 / 四选一配置项迁移到 `PlatformSegmentedTabs`;拼图结果页、抓大鹅结果页、抓大鹅素材配置、抓大鹅创作 / 结果页难度选择、视觉小说结果页和 creative-agent 模板确认弹窗已先迁移。后续同类控件只传选项、当前 id、变更回调、列数、尺寸、调性和外壳形态不再在业务 JSX 中重复容器边框、`bg-white/62`、选中态和 `aria-pressed` 18.4. 平台白底分段 Tab / 二选一 / 四选一配置项迁移到 `PlatformSegmentedTabs`;拼图结果页、抓大鹅结果页、抓大鹅素材配置、抓大鹅创作 / 结果页难度选择、视觉小说结果页和 creative-agent 模板确认弹窗已先迁移。后续同类控件只传选项、当前 id、变更回调、列数、尺寸、调性和外壳形态不再在业务 JSX 中重复容器边框、`bg-white/62`、选中态和 `aria-pressed`
18.4.1. `PlatformSegmentedTabs` 支持 `semantics="tabs"``tone="underline"``size="tab"``columns="one"`,用于承接认证入口短信 / 密码登录切换这类真实 Tab 语义;业务页不再维护本地 `LoginTabButton``role="tab"``aria-selected` 和下划线选中态。 18.4.1. `PlatformSegmentedTabs` 支持 `semantics="tabs"``tone="underline"``size="tab"``columns="one"`,用于承接认证入口短信 / 密码登录切换这类真实 Tab 语义;业务页不再维护本地 `LoginTabButton``role="tab"``aria-selected` 和下划线选中态。
18.5. 平台只读信息块迁移到 `PlatformInfoBlock`;错误弹窗和生成完成弹窗的来源、错误和状态展示、分享弹窗正文,以及汪汪声浪预览卡场景 / 形象 / 难度 / 声浪信息行已先迁移。后续弹窗、详情页或预览卡里只是展示短标签 + 只读正文,或无标签纯只读正文时,优先使用该 Module横向信息行通过 `labelClassName` / `valueClassName` 保留标签和值排版,不在业务 JSX 中重复白底信息块 chrome。 18.5. 平台只读信息块迁移到 `PlatformInfoBlock`;错误弹窗和生成完成弹窗的来源、错误和状态展示、分享弹窗正文,以及汪汪声浪预览卡场景 / 形象 / 难度 / 声浪信息行已先迁移。后续弹窗、详情页或预览卡里只是展示短标签 + 只读正文,或无标签纯只读正文时,优先使用该 Module横向信息行通过 `labelClassName` / `valueClassName` 保留标签和值排版,不在业务 JSX 中重复白底信息块 chrome。
@@ -260,6 +264,8 @@
- `npm run test -- src/components/common/CreativeImageInputPanel.test.tsx src/components/common/PlatformFieldLabel.test.tsx` - `npm run test -- src/components/common/CreativeImageInputPanel.test.tsx src/components/common/PlatformFieldLabel.test.tsx`
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "profile nickname modal"` - `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "profile nickname modal"`
- `npm run test -- src/components/common/PlatformTextField.test.tsx` - `npm run test -- src/components/common/PlatformTextField.test.tsx`
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "profile community shortcut|profile redeem invite"`
- `npm run test -- src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformFieldLabel.test.tsx src/components/common/PlatformSubpanel.test.tsx`
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "profile played modal|profile page keeps save archives inside played stats panel"` - `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "profile played modal|profile page keeps save archives inside played stats panel"`
- `npm run test -- src/components/common/PlatformSubpanel.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts` - `npm run test -- src/components/common/PlatformSubpanel.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts`
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "wallet ledger"` - `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "wallet ledger"`

View File

@@ -3178,6 +3178,9 @@ test('profile community shortcut shows reward subtitle and invited users', async
expect(screen.getByAltText('玩家社区 QQ 群二维码')).toBeTruthy(); expect(screen.getByAltText('玩家社区 QQ 群二维码')).toBeTruthy();
expect(screen.getByText('微信群')).toBeTruthy(); expect(screen.getByText('微信群')).toBeTruthy();
expect(screen.getByText('QQ群')).toBeTruthy(); expect(screen.getByText('QQ群')).toBeTruthy();
expect(screen.getByText('微信群').parentElement?.className).toContain(
'border-[var(--platform-subpanel-border)]',
);
expect(screen.queryByText('成功邀请')).toBeNull(); expect(screen.queryByText('成功邀请')).toBeNull();
expect(screen.queryByText('被邀请玩家')).toBeNull(); expect(screen.queryByText('被邀请玩家')).toBeNull();
}); });
@@ -3283,7 +3286,8 @@ test('profile redeem invite query modal submits code after login', async () => {
); );
}); });
expect(onRechargeSuccess).toHaveBeenCalledTimes(1); expect(onRechargeSuccess).toHaveBeenCalledTimes(1);
expect(await screen.findByText('已填写')).toBeTruthy(); const redeemedState = await screen.findByText('已填写邀请码');
expect(redeemedState.className).toContain('platform-empty-state');
expect(screen.queryByRole('region', { name: '次级入口' })).toBeNull(); expect(screen.queryByRole('region', { name: '次级入口' })).toBeNull();
}); });

View File

@@ -3893,9 +3893,13 @@ function ProfileReferralModal({
{panel === 'community' ? ( {panel === 'community' ? (
<div className="mt-5 grid grid-cols-2 gap-3"> <div className="mt-5 grid grid-cols-2 gap-3">
{COMMUNITY_QR_CODES.map((qrCode) => ( {COMMUNITY_QR_CODES.map((qrCode) => (
<div <PlatformSubpanel
as="div"
key={qrCode.label} key={qrCode.label}
className="rounded-xl border border-zinc-200 bg-zinc-50 p-2.5 text-center" surface="flat"
radius="xs"
padding="none"
className="p-2.5 text-center"
> >
<div className="aspect-square overflow-hidden rounded-lg border border-zinc-200 bg-white p-1.5"> <div className="aspect-square overflow-hidden rounded-lg border border-zinc-200 bg-white p-1.5">
<img <img
@@ -3909,7 +3913,7 @@ function ProfileReferralModal({
<div className="mt-2 text-sm font-bold text-zinc-700"> <div className="mt-2 text-sm font-bold text-zinc-700">
{qrCode.label} {qrCode.label}
</div> </div>
</div> </PlatformSubpanel>
))} ))}
</div> </div>
) : panel === 'redeem' ? ( ) : panel === 'redeem' ? (
@@ -3919,9 +3923,14 @@ function ProfileReferralModal({
<div className="h-11 animate-pulse rounded-xl bg-zinc-100" /> <div className="h-11 animate-pulse rounded-xl bg-zinc-100" />
</div> </div>
) : center?.hasRedeemedCode ? ( ) : center?.hasRedeemedCode ? (
<div className="mt-5 rounded-xl bg-zinc-50 px-4 py-5 text-center text-sm font-semibold text-zinc-600"> <PlatformEmptyState
surface="subpanel"
size="inline"
tone="base"
className="mt-5"
>
</div> </PlatformEmptyState>
) : ( ) : (
<form <form
className="mt-5 space-y-3" className="mt-5 space-y-3"
@@ -3961,14 +3970,23 @@ function ProfileReferralModal({
</div> </div>
) : ( ) : (
<div className="mt-5 space-y-3"> <div className="mt-5 space-y-3">
<div className="rounded-xl bg-zinc-50 px-4 py-4 text-center"> <PlatformSubpanel
<div className="text-[11px] font-bold text-zinc-500"> as="div"
surface="flat"
radius="xs"
padding="md"
className="text-center"
>
<PlatformFieldLabel
variant="section"
className="block text-[11px] text-zinc-500"
>
</div> </PlatformFieldLabel>
<div className="mt-1 text-3xl font-black tracking-[0.16em] text-[#ff4056]"> <div className="mt-1 text-3xl font-black tracking-[0.16em] text-[#ff4056]">
{center?.inviteCode ?? '--------'} {center?.inviteCode ?? '--------'}
</div> </div>
</div> </PlatformSubpanel>
<div className="rounded-xl border border-amber-200 bg-amber-50 px-3.5 py-3 text-sm font-semibold leading-6 text-amber-900"> <div className="rounded-xl border border-amber-200 bg-amber-50 px-3.5 py-3 text-sm font-semibold leading-6 text-amber-900">
<div> <div>
{`邀请一个用户注册,双方都可以获得${center?.rewardPoints ?? 30}泥点。`} {`邀请一个用户注册,双方都可以获得${center?.rewardPoints ?? 30}泥点。`}
@@ -3988,14 +4006,29 @@ function ProfileReferralModal({
actionFullWidth actionFullWidth
className="gap-2 rounded-xl" className="gap-2 rounded-xl"
/> />
<div className="rounded-xl bg-zinc-50 px-3.5 py-3"> <PlatformSubpanel
<div className="text-xs font-black text-zinc-900"></div> as="div"
surface="flat"
radius="xs"
padding="none"
className="px-3.5 py-3"
>
<PlatformFieldLabel
variant="section"
className="block text-zinc-900"
>
</PlatformFieldLabel>
{center?.invitedUsers?.length ? ( {center?.invitedUsers?.length ? (
<div className="mt-3 max-h-44 space-y-2 overflow-y-auto pr-1"> <div className="mt-3 max-h-44 space-y-2 overflow-y-auto pr-1">
{center.invitedUsers.map((user) => ( {center.invitedUsers.map((user) => (
<div <PlatformSubpanel
as="div"
key={`${user.userId}-${user.boundAt}`} key={`${user.userId}-${user.boundAt}`}
className="flex items-center gap-3 rounded-lg bg-white px-2.5 py-2" surface="soft"
radius="xs"
padding="none"
className="flex items-center gap-3 px-2.5 py-2"
> >
<ProfileReferralUserAvatar <ProfileReferralUserAvatar
name={user.displayName} name={user.displayName}
@@ -4006,15 +4039,19 @@ function ProfileReferralModal({
{user.displayName || '玩家'} {user.displayName || '玩家'}
</div> </div>
</div> </div>
</div> </PlatformSubpanel>
))} ))}
</div> </div>
) : ( ) : (
<div className="mt-3 rounded-lg bg-white px-3 py-3 text-center text-xs font-semibold text-zinc-500"> <PlatformEmptyState
surface="subpanel"
size="compact"
className="mt-3 text-center text-xs font-semibold leading-normal"
>
</div> </PlatformEmptyState>
)} )}
</div> </PlatformSubpanel>
</div> </div>
)} )}