# 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. ## 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` 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 has 32 pt icon/label rows, selected tint/ink and a divider. 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` | | 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: