Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,17 @@ const TD_CLASS =
* `w-full + max-w-0` 让它先塌到 0 (打破"按最长内容取列宽"的默认行为) 再领走
* 其余列分完后剩下的空间, 内层的 truncate 由此生效 (见 #3393 的同一段分析)。
* pl-3 是列间距, 否则相邻两列的数字会贴到一起; 首列自身取 pl-0。
*
* `overflow-hidden` 是最后一道单元格边界: 模型行还有不可收缩的色块与 agent 标签,
* 即使浏览器在边界宽度下给首列算出异常小的宽度, 它们也不能穿透到数字列 (#3546)。
* 表本身另有明确的最小宽度, 空间不足时由外层 overflow-x-auto 横向滚动, 而不是
* 继续把首列压到不可读。
*/
const FIRST_COL_CLASS = 'w-full max-w-0 pl-0';
const FIRST_COL_CLASS = 'w-full max-w-0 overflow-hidden pl-0';

/** 数字列保持完整可读所需的最小表宽; 低于该宽度时交给 Card 的横向滚动容器。 */
const AGENT_TABLE_CLASS = 'w-full min-w-[520px] border-collapse';
const MODEL_TABLE_CLASS = 'w-full min-w-[720px] border-collapse';

function Swatch({ rank }: { rank: number }): React.JSX.Element {
return (
Expand Down Expand Up @@ -92,7 +101,7 @@ export function UsageAgentTable({ rows }: { rows: AgentTokenRow[] }): React.JSX.
/>
))}
</div>
<table className="w-full border-collapse">
<table className={AGENT_TABLE_CLASS}>
<thead>
<tr>
<th className={cn(TH_CLASS, FIRST_COL_CLASS, 'text-left')}>
Expand Down Expand Up @@ -140,7 +149,7 @@ export function UsageModelTable({ rows }: { rows: ModelTokenRow[] }): React.JSX.
const { t } = useTranslation();

return (
<table className="w-full border-collapse">
<table className={MODEL_TABLE_CLASS}>
<thead>
<tr>
<th className={cn(TH_CLASS, FIRST_COL_CLASS, 'text-left')}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// @vitest-environment jsdom

import React from 'react';
import { render } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';

import { UsageAgentTable, UsageModelTable } from '../UsageBreakdownTables';

vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string) => key,
}),
}));

describe('UsageBreakdownTables responsive layout', () => {
it('keeps the agent table wide enough for numeric columns to scroll instead of overlap', () => {
const { container } = render(
<UsageAgentTable
rows={[
{
agentKind: 'claude-code',
tokens: 1_000,
share: 1,
todayTokens: 100,
cacheHitRate: 0.5,
modelCount: 1,
},
]}
/>,
);

const table = container.querySelector('table');
expect(table?.className).toContain('min-w-[520px]');
expect(table?.querySelector('tbody td')?.className).toContain('overflow-hidden');
});
Comment thread
dashhuang marked this conversation as resolved.

it('keeps the wider model table scrollable and clips first-column decorations at its boundary', () => {
const { container } = render(
<UsageModelTable
rows={[
{
key: 'codex:very-long-model-name',
agentKind: 'codex',
model: 'very-long-model-name-that-must-not-overlap-token-columns',
tokens: 1_000,
share: 1,
inputTokens: 400,
outputTokens: 300,
cacheReadTokens: 200,
cacheCreateTokens: 100,
cacheHitRate: 0.5,
},
]}
/>,
);

const table = container.querySelector('table');
expect(table?.className).toContain('min-w-[720px]');
expect(table?.querySelector('tbody td')?.className).toContain('overflow-hidden');
});
});
Loading