Skip to content

Commit 0d40616

Browse files
committed
fix(usage): correct the grid floor, tooltip height estimate, and Other row slot
Three findings from review. A grid track minimum is a hard floor, so `minmax(320px, 1fr)` made the source section wider than its column on a narrow viewport and overflowed instead of collapsing. `min(320px, 100%)` caps the floor at the width actually available. The tooltip height estimate used font sizes where it needed line boxes. The type scale pairs no line-height with a size, so a line occupies the ambient 1.5 — a 10px date line is 15px, an 11px row is 16.5 — and the estimate came in ~1.5px under the real box. Since it is what the clamp measures against and the chart clips its overflow, an underestimate cuts the bottom off the box rather than moving it up. Now derived from the line boxes, every part rounded up, with a test that fails if any of the three constants drops below the rendered height. The `Other` row drew its disclosure chevron bare at 14px while the rows above reserved the 16px arrow or the 30px menu slot, pulling its figure out of the column. It now centres in the same slot the rest of the list reserves.
1 parent 16ba7d1 commit 0d40616

4 files changed

Lines changed: 64 additions & 13 deletions

File tree

apps/sim/components/charts/chart-tooltip.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,24 @@ describe('estimateTooltipHeight', () => {
9191
it('reserves a row even when told there are none', () => {
9292
expect(estimateTooltipHeight(0, false)).toBe(estimateTooltipHeight(1, false))
9393
})
94+
95+
/**
96+
* The estimate is what the clamp measures against, and the chart clips its overflow,
97+
* so it must never come in under the real box — an underestimate cuts the bottom off
98+
* rather than moving the box up. Measured here against the box model the tooltip's
99+
* own class string implies: `border` + `py-1.5`, a `text-micro` date with `mb-1`,
100+
* and one `text-xs` row per value, every line at the ambient 1.5 line-height.
101+
*/
102+
it('never comes in under the box the tooltip actually renders', () => {
103+
const chrome = 2 + 6 + 6
104+
const dateLine = 10 * 1.5 + 4
105+
const rowLine = 11 * 1.5
106+
107+
for (const rows of [1, 2, 5]) {
108+
expect(estimateTooltipHeight(rows, true)).toBeGreaterThanOrEqual(
109+
chrome + dateLine + rows * rowLine
110+
)
111+
expect(estimateTooltipHeight(rows, false)).toBeGreaterThanOrEqual(chrome + rows * rowLine)
112+
}
113+
})
94114
})

apps/sim/components/charts/chart-tooltip.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,35 @@ export function estimateTooltipWidth(longestRowLength: number): number {
5858
return Math.min(220, Math.max(80, 7 * longestRowLength + 24))
5959
}
6060

61+
/** Border plus the `py-1.5` the tooltip's own class string sets. */
62+
const TOOLTIP_CHROME_HEIGHT = 2 + 12
63+
6164
/**
62-
* Height of the box {@link ChartTooltip} renders, from its own box model: the border
63-
* and `py-1.5` chrome, the optional date header and its margin, and one line per row.
65+
* The `text-micro` date's line box plus its `mb-1`.
66+
*
67+
* The type scale pairs no line-height with a font size, so a line occupies the
68+
* ambient 1.5 rather than the font size itself — 15px for 10px `text-micro`, not 10.
69+
*/
70+
const TOOLTIP_DATE_HEIGHT = 15 + 4
71+
72+
/** One `text-xs` row's line box: 11px at the ambient 1.5, rounded up from 16.5. */
73+
const TOOLTIP_ROW_HEIGHT = 17
74+
75+
/**
76+
* Height of the box {@link ChartTooltip} renders, from its own box model.
77+
*
6478
* Estimated rather than measured because the position is computed in the same render
6579
* that mounts the tooltip — reading a real height would need a second paint, which
66-
* shows up as the tooltip visibly jumping under the cursor.
80+
* shows up as the tooltip visibly jumping under the cursor. Every part rounds up:
81+
* this is what {@link positionChartTooltip} clamps against and the chart clips its
82+
* overflow, so an underestimate cuts the bottom off the box rather than moving it.
6783
*/
6884
export function estimateTooltipHeight(rowCount: number, hasDate: boolean): number {
69-
const chrome = 2 + 12
70-
const dateLine = hasDate ? 14 + 4 : 0
71-
return chrome + dateLine + Math.max(1, rowCount) * 16
85+
return (
86+
TOOLTIP_CHROME_HEIGHT +
87+
(hasDate ? TOOLTIP_DATE_HEIGHT : 0) +
88+
Math.max(1, rowCount) * TOOLTIP_ROW_HEIGHT
89+
)
7290
}
7391

7492
interface ChartTooltipProps {

apps/sim/ee/organization-usage/components/usage-consumers.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,19 @@ export function UsageConsumers({
278278
? formatChartCompactNumber(breakdown.other.tokens)
279279
: breakdown.other.credits.toLocaleString()}
280280
</span>
281-
{onExpandOther ? (
282-
<ChevronDown className={disclosureChevronClass} />
283-
) : (
284-
trailingSlot && (
285-
<span className={cn(trailingSlot, 'flex-shrink-0')} aria-hidden='true' />
286-
)
281+
{/*
282+
Centred in the slot the rows above reserve rather than sized to the
283+
glyph: with a navigable or action-bearing list the reserved slot is
284+
wider than the chevron, and drawing it bare pulled this row's figure
285+
out of the column.
286+
*/}
287+
{trailingSlot && (
288+
<span
289+
className={cn(trailingSlot, 'flex flex-shrink-0 items-center justify-center')}
290+
aria-hidden='true'
291+
>
292+
{onExpandOther && <ChevronDown className={disclosureChevronClass} />}
293+
</span>
287294
)}
288295
</OtherRow>
289296
)

apps/sim/ee/organization-usage/components/usage-monitoring.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,13 @@ export function UsageMonitoring({
469469
about how wide this actually is. Same rule as `RESOURCE_LIST_GRID`.
470470
*/}
471471
<UsageSection dimension='source' unit='credits'>
472-
<div className='grid grid-cols-[repeat(auto-fit,minmax(320px,1fr))] gap-x-6 gap-y-7'>
472+
{/*
473+
`min(320px, 100%)` rather than a bare `320px`: a track minimum is a
474+
hard floor, so on a column narrower than the minimum the grid would
475+
be wider than its container and overflow. Capping the floor at the
476+
available width collapses it to one column instead.
477+
*/}
478+
<div className='grid grid-cols-[repeat(auto-fit,minmax(min(320px,100%),1fr))] gap-x-6 gap-y-7'>
473479
<UsageConsumers
474480
dimension='source'
475481
breakdown={breakdown.data}

0 commit comments

Comments
 (0)