# SolidCraft UI kit `crates/ui-egui/src/ui_kit/` contains the tokenised controls used by feature dialogs, preferences, manager cards, prompts, context menus and the sketch palette. Import through `crate::ui_kit::{...}`. Most controls are crate-visible; the container API is public so platform apps use the same hosts. ## Stage bars `StageBar` composes two clipped, horizontally scrollable rows inside the shell's shared floating `Container` (`Surface::Chrome`). Its 36 pt first row contains numbered stage chips with the current workspace accent, shared primary/normal buttons and the existing command-search editor. The second row fills the remaining card height. The feature supplies labels, enabled reasons and command dispatch; the kit owns chip geometry, row spacing, typography and colour. Stage selection is navigation; the kit never invents completion badges. The shared compact workspace card is 104 × 88 pt; its icon, label and caption are centred vertically. The stage bar is 88 pt high with an 8 pt gap from that card. Its 36 pt header and 52 pt tools band share a 1 pt divider. Tools use 8 pt side padding, icon-text segments, icon-label actions and an information chip, all with `theme::Tokens` colours in both themes. Render retains its Inspector controls outside the bar. `Panel::workspace` gives paired floating docks the same bounded vertical span and limits each dock to half the available width with an 8 pt gap. Content clips inside the allocated host, so a small window cannot grow a dock into the stage bar or Shots strip. Docks without usable space are omitted. Render's default outer widths are 266 pt for Browser and 305 pt for Inspector, retaining the shared minimum/maximum resize rules. Its compass is 110 pt; the 48 pt Shots strip clears the docks by 8 pt. ## Composition and rules - Every outer host uses `ui_kit::Container` with a semantic `Surface`. The shell publishes the layout once per frame; `Container::floating()` and `frame()` own adaptive placement policy and chrome. `Panel`, `Window`, `Confirm` and `Menu` compose it. Raw egui hosts and outer shadows are rejected recursively, including platform apps. The mandatory `cargo xtask ui-containers` gate runs in fast CI and scans new crates/apps automatically, including macro bodies and alias chains. See the [container audit and migration inventory](ui-container-audit.md). - Colours, typography, dimensions and spacing come from `theme::Tokens`. - Sliders only via `ui_kit::slider`; `Slider` options change behaviour, never appearance. Raw sliders and duplicate track/thumb painters are forbidden in the UI and apps. - `scope(ui, add)` supplies form styling. `row(ui, label, add)` aligns labels and controls at `control_height` (28 pt). Wide manager rows use a 104 pt label basis with a 10 pt gutter, derived from the compact 70 pt basis and spacing tokens. Compact rows retain their 8 pt gutter. Labels widen from the appropriate basis to at most 1.6 times that width and never exceed half the row. - `expr_row`, `hint_row`, `text_row` and `choice_row` compose `row` with the existing expression, hinted expression, plain text and dropdown controls. They preserve row order, labels, focus IDs and completion; callers keep Enter/change ownership and explicit dropdown IDs. `count_row` composes `row` with `count_field` for pattern quantities. - `Panel::workspace` owns grip-based left/right placement and bounded width resizing for floating workspace cards, including in Compact ribbon layouts. It reuses the 40 pt Panel/Window header and padded body, with no second top inset below the ribbon. Persistent workspace cards omit the close action. `Panel::workspace_with_header` lets tree cards compose the shared `tree_header` (title, compact lens and quiet search action). Its tree policy shares the full dock height and lets rows own their 8 pt side insets; header navigation retains a separate title grip. `Panel::bottom_strip` uses `Container::bottom_strip_rect`, the same placement as Design History. `Container::navigation_card` supplies the shared Navigation surface for anchored HUDs. Register measured card rectangles and reserved edges with `shell::register_panel` so fitting and pointer shielding agree. Feature modules provide content, never outer chrome. - `Panel` owns bounded windows, feature/palette composition, scrolling bodies, pinned actions, compute status and keyboard routing. `wide()` uses three card widths. `feature_frame` and `palette_frame` retain docked/floating surfaces. `FeatureOptions::apply_label` adds Apply; `Panel::actions` supplies custom labels. With `DialogButtons::Top` published (Preferences › Interface › Dialog buttons), `feature` puts the actions in the header row through `HeaderActions` instead of a footer: the same buttons, enabled states, keyboard and handles, each as wide as its bold label, with Cancel standing in for the close button and the compute status in the title's place. `body_rows` caps a manager's scrolling body independently of its position; short viewports still keep the header and actions visible. - `Window` composes the shared Panel frame with a 40 pt icon/title/close header, padded content and optional 48 pt footer. `show_with_left` pins a left action beside the right-aligned buttons. `show_pages` accepts declarative `WindowPage` entries (icon, i18n label key, optional group heading, stable handle, scroll policy and draw callback). Its 188 pt soft page list (150 pt below a 700 pt window width) has 32 pt icon/label rows, selected tint/ink and a divider. Page windows use the navigation board's border/radius and the shared menu shadow; other windows retain their shared card surface. Preferences has nine grouped pages; legacy control-channel page names remain aliases. `page_rows` opts into a taller body while preserving viewport bounds. `actions`, `anchor`/`placed`, `cards`, `fields` and `keep_open_on_escape` retain existing window behavior. Empty action labels omit the footer. - `Confirm` is an input-blocking modal using the same card frame and footer controls. It shows a 36 pt icon disc in warning, danger or info tone, a title, caller-supplied message and optional monospace `detail`, above a 52 pt footer. Glyphs use the construction ramp for warning, the shared shaded danger treatment for danger, and base blue for info; the disc keeps its tint. `actions(primary, cancel, left_ghost)` places the optional third action at the left. Danger uses `form_error` with a contrast-selected on-colour; other primaries use blue. Enter invokes the selected answer (primary by default) when valid; Esc cancels. It retains close, answer and message scenario handles. The old `Prompt` element is removed. - Callers supply data and enabled state, then dispatch existing commands. Editors leave their established completion, Enter, Tab and commit ownership unchanged. - Every text input uses the kit's shared `text_input` policy: symmetric horizontal `form_inset`, zero vertical margin and centred galley alignment. Font metrics therefore centre both mono and proportional text within the allocated field, including invalid and attached Library fields, without per-caller offsets. Canvas placement editors retain their native line-height plus `space_4` hit target so nearby sketch picks are not intercepted; alignment stays shared. - Scenario handles and accessible labels are API. Consolidated options preserve the former geometry, wrapping, native metadata and publication keys. Preference compositions use `settings_heading`, shared disclosure `settings_section` headings and `settings_pair` for responsive controls beside one specimen. `option_card` supplies the shared illustrated radio control. `settings_form` and `settings_block_hint` define aligned label grids; `theme_rail` keeps the import tile fixed beside a scrollbar-free scrolling row. `PreferenceFigure` owns theme swatches, orbit pivots, quality, anti-aliasing, contact shading and up-axis figures. `layout_preview` follows the four workspace choices without opening another viewport. Scale, palette, autosave, mouse and live-axis specimens share tokens and the gallery; live bars show actual calibrated input and introduce no repaint timer. ## Elements Module names below describe implementation locations, not caller import paths. Every inline element/variant has one entry in the light/dark `gallery::ELEMENTS` table. Panel/Window/Confirm compositions also have dedicated geometry and interaction tests. | Module / element | Use and options | Main tokens | | --- | --- | --- | | assistant: `assistant_header`, `assistant_controls`, `assistant_badge`, `assistant_bubble`, `assistant_prose`, `assistant_tool_frame/row/detail/status`, `AssistantToolState`, `assistant_approval/actions`, `assistant_composer/footer`, `assistant_input`, `assistant_send`, `assistant_empty`, `assistant_banner`, `AssistantTone` | Shared Assistant presentation: 40 pt header, 22 pt state pill, right-aligned user messages limited to 86% width, unboxed assistant prose, bordered tool groups and command detail, tinted approval heading, rounded focused composer with one unframed growing editor and pinned footer, centred setup copy and semantic notices. Closures preserve existing permission choices, protocol routing, queue actions and scenario handles. | `form_header_height/close_size`, `font_label/small/body`, `dialog_body/footer/rule`, `control_fill/border/radius`, `form_ink/dim/primary/success/error`, `accent_soft/selected_ink`, `warning`, radii and spacing | | history: `HistoryChip`, `HistoryStyle`, `history_drop_bar`, `history_marker`, `HistorySeam`, `history_seam` | One painter family for bottom chips, 38 pt vertical icon chips and single-line 26 pt name rows (the browser's shared `TREE_ROW_HEIGHT`). Selected items use the active tab tint/ink/border; all variants retain multi-tone feature artwork using one shared kind-to-accent rule (Sketch green, Surface orange, Mesh yellow, Form purple, solids base blue); rolled-back items have 42% opacity; a reference row (a sketch listed under another feature, #6489) has its name in secondary text. Error/warning badges, suppression strikes, horizontal/vertical drop bars and rollback line/hollow circle are shared. No connector lines. | `control_height`, `space_2/3/4/6/8/10/12/14/16/24`, radii, typography, `TabAccent`, `timeline_item`, `control_border`, `text/dim`, `form_error/fill` | | tree: `tree_row`, `Row`, `TreeAction` | Shared Browser rows with disclosure, visibility, activation, selection, appearance swatches, optional subtitle and trailing actions. Compact scene rows are 28 pt, with inline right-aligned summaries, circular swatches, trailing eyes and full-width selection tint. Actions use quiet icons and can appear on hover. Disabled actions retain their reasons and cannot select or fold the row. Browser automation records the same row geometry. | `TREE_ROW_HEIGHT`, `font_label/small`, spacing, control radius/border, `text/dim`, workspace selection tint | | search: `CommandSearch`, `MenuItem::search_row` | Ribbon search composition: one persistent ribbon editor expands from 28 to 40 pt and to 520 pt wide with its right edge anchored, magnifier and S/Esc keycap, 38 pt two-line menu row with 26 pt icon tile, accent bold substring, path, shortcut/kind keycap, counts, JSON detail box and footer. The ordinary 30 pt menu row cannot fit a second line; this variant keeps its enabled/selected states and scenario IDs. Ranking and dispatch stay with the caller. | `form_card_width × 2 − space_8` (520 pt), `control_height`, `space_2/3/4/6/8/10/12/14/16/24`, `radius_xl/control_radius`, `control_fill`, `dialog_body/footer/rule/border`, `form_ink/dim/primary/error/error_fill/success/success_fill`, `selected_ink`, `accent_soft`, typography | | menu: `Menu`, `MenuItem` | Shared popup, 30 pt rows, 28 pt icon column, clipped labels, right-aligned mono shortcuts, submenu chevrons, checked/unchecked and document swatches, inert 40% disabled rows and danger ink; headings and separators; ribbon drag/pin targets retained | `dialog_body/border/rule`, `radius_xl`, `control_height/radius`, `form_ink/dim/primary/error`, `accent_soft`, typography and spacing | | radial: `radial_menu` | Eight rounded annular sectors, parallel 4 pt gaps, 9 pt circular corner joins, tab-accent artwork and hover, centre label/key; existing hold/flick/release dispatch | `dialog_body/border`, `form_ink/dim`, `TabAccent`, icon palette, font/spacing tokens | | panel: `Window`, `WindowPage` | Shared card frame, header, optional page list, bounded content and footer with a left action | `form_header/footer_height`, `form_card_width`, `form_label_width`, `control_height`, `dialog_footer/rule`, `selected_bg/ink`, spacing | | confirm: `Confirm`, `Tone` | Modal warning/danger/info, title/message, mono detail and ghost/cancel/primary actions | `warning`, `form_error/fill`, `accent_soft`, `form_primary`, `on_accent`, `tab_on_fill_dark`, `font_subtitle`, spacing | | metrics: `row_height`, `table_row_height`, `header_height` | Shared control/header heights | `control_height`, `space_8`, `form_header_height` | | layout: `scope`, `row` | Form styling and aligned label/control columns | `form_label_width`, `form_gap_y`, `control_*`, `font_label`, `dialog_label`, `space_4/8` | | `caption` | Dim caption aligned beneath a control | `font_small`, `text_dim`, label-column tokens | | `figure_rows`, `FigureSlot` | A caller-painted figure in the label column beside a stack of captioned expression fields (the Hole dialog's section); the caller gets each field's rect and hover/focus state to draw leaders and light the part it sizes. Fields keep their `dialog: