From 4f3516a5d9e1da6c921467ac76d3ca6cc5af7505 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Fri, 11 Sep 2026 14:54:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=86=E7=B1=BB=20chip=20?= =?UTF-8?q?=E6=9D=A1=E5=8F=A0=E5=AD=97=EF=BC=9A=E5=88=86=E6=AE=B5=E9=A1=B5?= =?UTF-8?q?=E7=AD=BE=E5=AD=90=E9=A1=B9=E8=A1=A5=E5=86=85=E5=AE=B9=E5=AE=BD?= =?UTF-8?q?=E5=BA=A6=E4=B8=8B=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - packages/shared/src/components/PlatformSegmentedTabs.tsx:容器补 `platform-segmented-tabs` 稳定钩子类,供共享样式表精确命中子项(不依赖 Tailwind 任意值扫描) - packages/shared/src/components/styles.css:新增 `.platform-segmented-tabs > button` 的 `min-width: max-content`,给每个子项一个「内容宽度」下限;放不下时由容器横向滚动兜底 - apps/ai-game-creator-shell/src/view/project-development/ResourceClassificationPanel.tsx: 「资源分类与标签」的 6 类分类条由 `columns="threeToSix"` 改为 `layout="scroll"` + `frame="bare"` + `surface="transparent"`,与 `@` 面板和资源画布的分类条同一条既有形态 - packages/shared/src/components/PlatformResourceFilterBar.test.tsx:新增两条声明级断言, 钉住「子项不换行 + 容器横向可滚 + 子项有不低于内容宽度的下限」 --- .../ResourceClassificationPanel.tsx | 4 +- .../PlatformResourceFilterBar.test.tsx | 57 +++++++++++++++++++ .../src/components/PlatformSegmentedTabs.tsx | 1 + packages/shared/src/components/styles.css | 10 ++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/apps/ai-game-creator-shell/src/view/project-development/ResourceClassificationPanel.tsx b/apps/ai-game-creator-shell/src/view/project-development/ResourceClassificationPanel.tsx index 6dc83a914..3a70afbdd 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/ResourceClassificationPanel.tsx +++ b/apps/ai-game-creator-shell/src/view/project-development/ResourceClassificationPanel.tsx @@ -214,8 +214,10 @@ export function ResourceClassificationPanel({ items={RESOURCE_CLASSIFICATION_CATEGORY_OPTIONS} activeId={category} onChange={setCategory} - columns="threeToSix" + layout="scroll" gap="sm" + frame="bare" + surface="transparent" size="compact" /> { test('renders a controlled search box, category tabs and tag chips', () => { render( @@ -93,4 +109,45 @@ describe('PlatformResourceFilterBar', () => { expect(screen.queryByRole('group', { name: '素材筛选标签' })).toBeNull(); expect(screen.getByRole('button', { name: '全部' })).toBeTruthy(); }); + + test('never lets a category chip shrink below its label width', () => { + const { container } = render( + {}} + />, + ); + + // 分类条是 scroll 布局:容器横向可滚,标签不换行。 + const row = container.querySelector('.platform-segmented-tabs'); + expect(row).not.toBeNull(); + expect(row?.className).toContain('overflow-x-auto'); + for (const button of row?.querySelectorAll('button') ?? []) { + expect(button.className).toContain('whitespace-nowrap'); + } + + // 单靠 nowrap 不够:子项必须有不低于内容宽度的下限,否则文字会画出盒子压到相邻项。 + expect(segmentedTabsStylesheet()).toMatch( + /\.platform-segmented-tabs\s*>\s*button\s*\{[^}]*min-width:\s*max-content/s, + ); + }); + + test('grid 布局的分段页签同样带宽度下限钩子', () => { + render( + {}} + columns="two" + />, + ); + + const row = screen + .getByRole('button', { name: '角色与对象' }) + .closest('div'); + expect(row?.className).toContain('platform-segmented-tabs'); + expect(row?.className).toContain('grid-cols-2'); + }); }); diff --git a/packages/shared/src/components/PlatformSegmentedTabs.tsx b/packages/shared/src/components/PlatformSegmentedTabs.tsx index 34852d475..cd2eadb1f 100644 --- a/packages/shared/src/components/PlatformSegmentedTabs.tsx +++ b/packages/shared/src/components/PlatformSegmentedTabs.tsx @@ -191,6 +191,7 @@ export function PlatformSegmentedTabs({ role={semantics === 'tabs' ? 'tablist' : undefined} aria-label={semantics === 'tabs' ? ariaLabel : undefined} className={[ + 'platform-segmented-tabs', layout === 'scroll' ? 'flex min-w-0 items-center overflow-x-auto scrollbar-hide' : 'grid', diff --git a/packages/shared/src/components/styles.css b/packages/shared/src/components/styles.css index a3c7bcc59..9b1cd337a 100644 --- a/packages/shared/src/components/styles.css +++ b/packages/shared/src/components/styles.css @@ -519,6 +519,16 @@ display: none; } +/* 分段页签的子项不得被压到内容宽度以下。中文标签(例如「角色与对象」需要一个 + `1.5rem 内边距 + 4 个字`的宽度)在窄容器里一旦被压扁,标签虽然 `nowrap`,文字仍会 + 画出自己的盒子压到相邻项上——现场表现就是「后几项挤成一团、文字互相重叠」。 + `min-width: max-content` 给每个子项一个「内容宽度」下限:放得下就照原样排,放不下 + 就由容器横向滚动兜底,任何情况下都不叠字。grid 与 scroll 两条 layout 都需要它: + grid 的轨道按容器等分,scroll 的 flex 子项默认可收缩,两者都会压到内容宽度以下。 */ +.platform-segmented-tabs > button { + min-width: max-content; +} + .platform-category-chip { display: inline-flex; min-height: 2.25rem;