修复分类 chip 条叠字:分段页签子项补内容宽度下限
- 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:新增两条声明级断言, 钉住「子项不换行 + 容器横向可滚 + 子项有不低于内容宽度的下限」
This commit is contained in:
+3
-1
@@ -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"
|
||||
/>
|
||||
<PlatformTextField
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import { PlatformResourceFilterBar } from './PlatformResourceFilterBar';
|
||||
import { PlatformSegmentedTabs } from './PlatformSegmentedTabs';
|
||||
|
||||
const CATEGORY_ITEMS = [
|
||||
{ id: 'all', label: '全部' },
|
||||
{ id: 'character', label: '角色与对象' },
|
||||
];
|
||||
|
||||
/**
|
||||
* 分段页签的子项宽度下限是「不叠字」的唯一判据:grid 的轨道按容器等分、scroll 的
|
||||
* flex 子项默认可收缩,两者都会把中文标签压到内容宽度以下,标签虽然 nowrap,
|
||||
* 文字仍会画出自己的盒子压到相邻项上。这条规则一旦被删掉就要失败。
|
||||
*/
|
||||
function segmentedTabsStylesheet() {
|
||||
return readFileSync(
|
||||
resolve(process.cwd(), 'packages/shared/src/components/styles.css'),
|
||||
'utf8',
|
||||
);
|
||||
}
|
||||
|
||||
describe('PlatformResourceFilterBar', () => {
|
||||
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(
|
||||
<PlatformResourceFilterBar
|
||||
ariaLabel="素材筛选"
|
||||
categoryItems={CATEGORY_ITEMS}
|
||||
activeCategoryId="all"
|
||||
onCategoryChange={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
// 分类条是 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(
|
||||
<PlatformSegmentedTabs
|
||||
items={CATEGORY_ITEMS}
|
||||
activeId="all"
|
||||
onChange={() => {}}
|
||||
columns="two"
|
||||
/>,
|
||||
);
|
||||
|
||||
const row = screen
|
||||
.getByRole('button', { name: '角色与对象' })
|
||||
.closest('div');
|
||||
expect(row?.className).toContain('platform-segmented-tabs');
|
||||
expect(row?.className).toContain('grid-cols-2');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -191,6 +191,7 @@ export function PlatformSegmentedTabs<TId extends string = string>({
|
||||
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',
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user