@@ -21,10 +21,15 @@ import { type ContextWindowSnapshot, formatContextWindowTokens } from "../../lib
2121import { cn } from "../../lib/utils" ;
2222import { formatUpcomingTimestamp } from "../../timestampFormat" ;
2323import { Tooltip , TooltipPopup , TooltipTrigger } from "../ui/tooltip" ;
24+ import { Button } from "../ui/button" ;
2425import { ThreadDetailsControl } from "./ThreadDetailsControl" ;
25- import { ContextWindowMeter } from "./ContextWindowMeter" ;
26+ import { ContextWindowMeter , ContextWindowSegments } from "./ContextWindowMeter" ;
2627import { ThreadDetailsSection } from "./ThreadDetailsSection" ;
2728
29+ // The canvas reserves the same icon, label, meter, percent and trailing columns in every row.
30+ const USAGE_ROW_CLASS =
31+ "grid grid-cols-[1rem_3.625rem_minmax(0,1fr)_1.875rem_2.75rem] items-center gap-x-2 ps-3 pe-2 text-meta" ;
32+
2833const PACE_LABEL : Record < LimitPace , string > = {
2934 ahead : "Ahead of pace" ,
3035 on : "On pace" ,
@@ -97,18 +102,13 @@ export function ThreadDetailsContext({
97102 }
98103 const maxTokens = usage . maxTokens != null && usage . maxTokens > 0 ? usage . maxTokens : null ;
99104 const used = maxTokens !== null ? Math . max ( 0 , Math . min ( 100 , usage . usedPercentage ?? 0 ) ) : null ;
100- const threshold = usage . autoCompactThreshold ?? null ;
101- const tick =
102- maxTokens !== null && threshold !== null && threshold > 0 && threshold < maxTokens
103- ? ( threshold / maxTokens ) * 100
104- : null ;
105105 const tokens =
106106 maxTokens !== null
107107 ? `${ formatContextWindowTokens ( usage . usedTokens ) } / ${ formatContextWindowTokens ( maxTokens ) } `
108108 : `${ formatContextWindowTokens ( usage . usedTokens ) } tokens` ;
109109 return (
110110 < ThreadDetailsSection title = "Context window" variant = "usage" >
111- < div className = "flex min-h-11 items-center gap-2 ps-3 pe-2 text-meta" >
111+ < div className = { cn ( USAGE_ROW_CLASS , "h-8" ) } >
112112 < ContextWindowMeter
113113 usage = { usage }
114114 side = "left"
@@ -117,54 +117,29 @@ export function ThreadDetailsContext({
117117 compactDisabledReason = { compactDisabledReason }
118118 trigger = {
119119 < ThreadDetailsControl
120- part = "heading "
120+ part = "usage "
121121 aria-label = { `Context: ${ tokens } ${ maxTokens !== null ? " tokens" : "" } ${ used !== null ? `, ${ Math . round ( used ) } % used` : " used" } ` }
122122 >
123123 < GaugeIcon className = "size-4 shrink-0" />
124- < span className = "flex min-w-0 flex-1 flex-col gap-1 text-meta" >
125- < span className = "flex items-center justify-between gap-2 text-foreground" >
126- < span > Context</ span >
127- { used !== null ? (
128- < span className = "tabular-nums text-muted-foreground" > { Math . round ( used ) } %</ span >
129- ) : null }
130- </ span >
131- < span className = "flex items-center gap-2" >
132- { used !== null ? (
133- < span className = "relative h-1 min-w-0 flex-1 rounded-full bg-muted-foreground/20" >
134- < span
135- className = { cn (
136- "absolute inset-y-0 left-0 rounded-full" ,
137- used >= 90 ? "bg-error" : used >= 80 ? "bg-warning" : "bg-foreground/80" ,
138- ) }
139- style = { { width : used > 0 ? `max(${ used } %, 2px)` : "0%" } }
140- />
141- { tick !== null ? (
142- < span
143- aria-hidden
144- className = "absolute -top-[3px] h-2.5 w-0.5 rounded-sm bg-muted-foreground"
145- style = { { left : `${ tick } %` } }
146- />
147- ) : null }
148- </ span >
149- ) : null }
150- < span className = "shrink-0 text-caption tabular-nums text-muted-foreground" >
151- { tokens }
152- </ span >
153- </ span >
124+ < span className = "flex h-6 items-center text-foreground" > Context</ span >
125+ { used !== null ? < ContextWindowSegments usage = { usage } /> : < span /> }
126+ < span className = "text-end tabular-nums text-muted-foreground" >
127+ { used !== null ? `${ Math . round ( used ) } %` : "" }
154128 </ span >
155129 </ ThreadDetailsControl >
156130 }
157131 />
158- < span className = "flex w-11 shrink-0 justify-end" >
132+ < span className = "flex justify-end" >
159133 { onCompact ? (
160- < ThreadDetailsControl
161- part = "icon"
134+ < Button
135+ size = "icon-xs"
136+ variant = "secondary"
162137 aria-label = "Compact context"
163138 disabled = { compactDisabled }
164139 onClick = { onCompact }
165140 >
166- < Minimize2Icon className = "size-3.5 " />
167- </ ThreadDetailsControl >
141+ < Minimize2Icon className = "size-[13px] " />
142+ </ Button >
168143 ) : null }
169144 </ span >
170145 </ div >
@@ -249,18 +224,21 @@ function UsageRow({
249224} ) {
250225 return (
251226 < Tooltip >
252- < div className = "flex h-8 items-center gap-2 ps-3 pe-2 text-meta" >
227+ < div className = { cn ( USAGE_ROW_CLASS , " h-8" ) } >
253228 < TooltipTrigger
254229 render = {
255230 < div
256231 tabIndex = { 0 }
257232 aria-label = { `${ label } : ${ ariaValue } ` }
258- className = "flex min-w-0 flex-1 cursor-default items-center gap-2 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
233+ className = { cn (
234+ "grid min-w-0 cursor-default grid-cols-subgrid items-center gap-x-2 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring" ,
235+ fill === null ? "col-span-5" : "col-span-4" ,
236+ ) }
259237 />
260238 }
261239 >
262240 < span className = "shrink-0 text-muted-foreground [&>svg]:size-4" > { icon } </ span >
263- < span className = "w-14.5 shrink-0 truncate" > { label } </ span >
241+ < span className = "truncate" > { label } </ span >
264242 { fill !== null ? (
265243 < span className = "relative h-1 min-w-0 flex-1 rounded-full bg-muted-foreground/20" >
266244 { fill > 0 ? (
@@ -284,21 +262,19 @@ function UsageRow({
284262 />
285263 ) : null }
286264 </ span >
287- ) : (
288- < span className = "flex-1" />
289- ) }
265+ ) : null }
290266 < span
291267 className = { cn (
292- "w-7.5 shrink-0 text-end tabular-nums text-muted-foreground" ,
293- fill === null && "w-auto " ,
268+ "text-end tabular-nums text-muted-foreground" ,
269+ fill === null && "col-span-3 " ,
294270 tone === "error" && "text-error-foreground" ,
295271 tone === "warning" && "text-warning-foreground" ,
296272 ) }
297273 >
298274 { value }
299275 </ span >
300276 </ TooltipTrigger >
301- < span className = "flex w-11 shrink-0 justify-end" > { trailing } </ span >
277+ { fill !== null ? < span className = "flex justify-end" > { trailing } </ span > : null }
302278 </ div >
303279 < TooltipPopup side = "left" sideOffset = { 16 } >
304280 < div className = "flex flex-col gap-0.5 text-muted-foreground" > { tooltip } </ div >
0 commit comments