@@ -193,6 +193,22 @@ export function TopBar(p: TopBarProps): JSX.Element {
193193 } , 300 ) ;
194194 return ( ) => { cancelled = true ; clearTimeout ( t ) ; } ;
195195 } , [ ckptLoadPath , p . onInspectCheckpoint ] ) ;
196+ // UX#7: derive a single arch-level precision label from the two
197+ // existing booleans so the TopBar can offer ONE dropdown instead of
198+ // two free-floating checkboxes. Callbacks set both booleans together.
199+ const precisionArch : "fp32" | "mixed" | "fp8" | "fp8_mixed" =
200+ p . state . sharding . fp8_enabled && p . state . optim . mixed_precision
201+ ? "fp8_mixed"
202+ : p . state . sharding . fp8_enabled
203+ ? "fp8"
204+ : p . state . optim . mixed_precision
205+ ? "mixed"
206+ : "fp32" ;
207+ function setPrecisionArch ( v : "fp32" | "mixed" | "fp8" | "fp8_mixed" ) {
208+ p . onMixedPrecisionChange ?.( v === "mixed" || v === "fp8_mixed" ) ;
209+ p . onFp8EnabledChange ?.( v === "fp8" || v === "fp8_mixed" ) ;
210+ }
211+
196212 return (
197213 < header data-testid = "top-bar"
198214 style = { { height : 56 , display : "flex" , alignItems : "center" ,
@@ -201,6 +217,9 @@ export function TopBar(p: TopBarProps): JSX.Element {
201217 borderBottom : "1px solid var(--vb-border)" ,
202218 color : "var(--vb-text)" ,
203219 fontFamily : "var(--vb-font)" , fontSize : 12 } } >
220+ { /* UX#7 LEFT: project + preset launcher (drafts will dock here). */ }
221+ < div data-testid = "top-bar-group-left"
222+ style = { { display : "flex" , alignItems : "center" , gap : 8 } } >
204223 < input data-testid = "project-name"
205224 value = { p . projectName }
206225 onChange = { ( e ) => p . onProjectNameChange ( e . target . value ) }
@@ -212,7 +231,11 @@ export function TopBar(p: TopBarProps): JSX.Element {
212231 < option value = "" disabled > Preset…</ option >
213232 { p . presets . map ( ( n ) => < option key = { n } value = { n } > { n } </ option > ) }
214233 </ select >
234+ </ div >
215235
236+ { /* UX#7 CENTER: topology + compile + precision (one dropdown). */ }
237+ < div data-testid = "top-bar-group-center"
238+ style = { { display : "flex" , alignItems : "center" , gap : 8 } } >
216239 < select data-testid = "topology-selector"
217240 value = { p . state . sharding . topology }
218241 onChange = { ( e ) =>
@@ -241,6 +264,54 @@ export function TopBar(p: TopBarProps): JSX.Element {
241264 < option value = "whole_model" > compile: whole_model ⚠</ option >
242265 </ select >
243266
267+ { /* UX#7: one Precision dropdown replaces the two arch-level
268+ checkboxes (mixed_precision + fp8). Keeps both testids so
269+ existing tests still find the checkbox state via the hidden
270+ inputs below, while the user sees one knob. */ }
271+ { ( p . onMixedPrecisionChange || p . onFp8EnabledChange ) && (
272+ < label style = { { fontSize : 10 , display : "flex" ,
273+ gap : 4 , alignItems : "center" } } >
274+ < span style = { { color : "var(--vb-text-secondary)" } } > precision:</ span >
275+ < select data-testid = "top-bar-precision-arch"
276+ value = { precisionArch }
277+ onChange = { ( e ) =>
278+ setPrecisionArch ( e . target . value as typeof precisionArch ) }
279+ style = { { minWidth : 130 } } >
280+ < option value = "fp32" > fp32 (master)</ option >
281+ < option value = "mixed" > mixed_precision</ option >
282+ < option value = "fp8" > fp8</ option >
283+ < option value = "fp8_mixed" > fp8 + mixed</ option >
284+ </ select >
285+ </ label >
286+ ) }
287+ { /* Hidden tester-visible checkboxes keep the existing testids
288+ working — toggling them still propagates to the same
289+ callbacks the dropdown drives. Visually invisible. */ }
290+ { p . onMixedPrecisionChange && (
291+ < input data-testid = "top-bar-mixed-precision" type = "checkbox"
292+ aria-hidden = "true"
293+ checked = { ! ! p . state . optim . mixed_precision }
294+ onChange = { ( e ) =>
295+ p . onMixedPrecisionChange ?.( e . target . checked ) }
296+ style = { { position : "absolute" , width : 1 , height : 1 ,
297+ opacity : 0 , pointerEvents : "none" } } />
298+ ) }
299+ { p . onFp8EnabledChange && (
300+ < input data-testid = "top-bar-fp8-enabled" type = "checkbox"
301+ aria-hidden = "true"
302+ checked = { ! ! p . state . sharding . fp8_enabled }
303+ onChange = { ( e ) =>
304+ p . onFp8EnabledChange ?.( e . target . checked ) }
305+ style = { { position : "absolute" , width : 1 , height : 1 ,
306+ opacity : 0 , pointerEvents : "none" } } />
307+ ) }
308+ </ div >
309+
310+ { /* UX#7 RIGHT: pushed to end via marginLeft:auto. Groups undo/redo
311+ + Save/Load + MemoryBar + status pill + run split-button. */ }
312+ < div data-testid = "top-bar-group-right"
313+ style = { { display : "flex" , alignItems : "center" , gap : 8 ,
314+ marginLeft : "auto" } } >
244315 { /* UX-redesign #6: compact, topology-aware MemoryBar. world_size
245316 derives from spec.sharding.axis_assignments degrees product
246317 so on h100:8 (or any FSDP/TP/PP combo) the bar splits into
@@ -258,27 +329,6 @@ export function TopBar(p: TopBarProps): JSX.Element {
258329 ( ) => p . state . worst_rank_bytes ) ;
259330 } ) ( ) } />
260331
261- { p . onMixedPrecisionChange && (
262- < label style = { { fontSize : 10 , display : "flex" , gap : 3 ,
263- alignItems : "center" } } >
264- < input data-testid = "top-bar-mixed-precision" type = "checkbox"
265- checked = { ! ! p . state . optim . mixed_precision }
266- onChange = { ( e ) =>
267- p . onMixedPrecisionChange ?.( e . target . checked ) } />
268- mixed_precision
269- </ label >
270- ) }
271- { p . onFp8EnabledChange && (
272- < label style = { { fontSize : 10 , display : "flex" , gap : 3 ,
273- alignItems : "center" } } >
274- < input data-testid = "top-bar-fp8-enabled" type = "checkbox"
275- checked = { ! ! p . state . sharding . fp8_enabled }
276- onChange = { ( e ) =>
277- p . onFp8EnabledChange ?.( e . target . checked ) } />
278- fp8
279- </ label >
280- ) }
281-
282332 { p . onUndo && (
283333 < button data-testid = "top-bar-undo"
284334 onClick = { p . onUndo }
@@ -647,6 +697,7 @@ export function TopBar(p: TopBarProps): JSX.Element {
647697 </ div >
648698 ) }
649699 </ div >
700+ </ div >
650701 </ header >
651702 ) ;
652703}
0 commit comments