* claim: #6709 * feat(view): OK and Cancel in the corner of the view while a dialog or sketch is open (#6709)
8.2 KiB
Layout-aware container audit
Shared container foundation (#4411) and compact composition (#2029), on top of
History #3953 and Assistant #3985. Interface preferences save Floating or Compact;
view.layout changes the same preference without changing the design.
Ownership
ui_kit::Container is the only production constructor for outer egui hosts in the
UI crate and the desktop/web apps. Surface declares purpose, not a second layout
setting. The shell publishes LayoutMode before drawing any page. Adaptive panels
and shell layout use Container::floating(); frames use the same policy. There is
one definition of floating/compact chrome and workspace gaps in ui_kit/container.rs.
Compact joins the workspace and ribbon, puts Browser flush beneath it with a square
join and content-hugging height, and opens feature/palette sheets at their edge without
card gaps or shadows. Tool sheets remain draggable in either layout; compact sheets
round all four corners when detached and square only the right corners at their right dock. Contacts declare which edges meet; the container rounds only
exposed convex corners and collapses adjoining outlines into one stroke. Stacked
headers cover the viewport without reserving a blank column beneath them.
Floating keeps its card chrome; both layouts retain tool drag offsets.
Menus, system windows, notifications and canvas content retain their existing roles.
The shell still owns ordering, viewport reservations and shared-column geometry.
A container does not infer geometry from a title or panel ID. Browser and History
share a column width; Assistant remains outermost on either side. Tool sheets may overlap Browser and History,
but cannot enter Assistant’s reserved rail or cover the ribbon/workspace selector. Those relationships
must survive the compact composition. Existing Panel, Window, Confirm and
Menu are content compositions over the universal container, not alternative hosts.
The low-level window builder is visible only inside the UI kit: feature and platform
windows use the shared composition, including its header and fixed outer frame.
Inventory and migration
| Surfaces | Owners / composition | Container policy |
|---|---|---|
| Browser, vertical History and Browser/History shared column | browser, timeline_left, lib |
Adaptive panel; shared shell placement, resizing and fold state remain with owners |
| Horizontal History | timeline |
Adaptive panel surface; floating strip or bottom dock |
| Assistant sheet and folded strip | agent_chat/panel → Panel |
Adaptive feature surface; left/right position, resize, drag targets and native pop-out retained |
| Feature forms, Parameters, material review, Redefine Sketch Plane | dialogs, params_dialog, material_card_review, sketch_attachment_ui → Panel |
Adaptive feature surface; bounded anchors and pinned actions retained |
| Sketch options | sketch_palette → Panel |
Adaptive palette surface, preserving transparency |
| Application bar, workspace and ribbon | toolbar, shell |
Chrome hosts; adaptive card geometry comes from the shared policy |
| Render settings | render_workspace |
Panel host; existing right dock retained |
| Preferences, managers, About, update/install/recovery/crash/issue prompts | Window, Confirm |
System windows and modal sheets retain modality; these are not workspace sidebars |
| BOM, Messages, mouse gestures, 3D mouse calibration | respective modules → Window::show_body |
Shared header, tokenised frame and bounded body; native egui title bars/resize highlights and legacy report/width helpers removed |
| Web stored-files and web recovery windows | apps/solidcraft-web → Window::show_body |
Same shared composition; recovery requires an explicit choice and cannot be dismissed through the header |
| File/workspace/document/Help/context/overflow menus, radial menu, Select Other and inline rename | respective owners → Menu / container popup |
Anchored transient hosts; never consume workspace dock space |
| Search, completions, colour and library popovers | shortcut_box, kit fields/choice/colour/table |
Anchored popup containers; editor focus and completion semantics retained |
| Dimension values, canvas placement values, canvas feedback and History resize seam | dim_view, sketch_dims, canvas, timeline_left |
Model/control-anchored overlays; retain their coordinates rather than becoming docks |
| Status and loading/progress messages | viewport, open_meshing |
Notification surfaces independent of layout |
| Navigation bar | viewport |
Shared navigation surface; shell still computes its available canvas bounds |
| OK and Cancel in the view's corner | view_confirm |
Navigation surface in its own area; the viewport layout reserves its corner and the shell counts it as covered |
| Home, model viewport, Render canvas and native Assistant window content | home, lib, agent_chat/panel |
Central content hosts, not floating workspace panels |
| Loading input shield | file_load |
Explicit input shield; must remain interactive while CAD input is blocked |
The compass, geometry previews, drag handles, selection outlines, dimension lines, charts and thumbnails are drawn content, not independent card hosts. Giving them workspace docks would be incorrect. egui-managed tooltips and widget internals remain with their owning shared widget. OS file/program/colour pickers and native viewport creation remain host services, not in-app panels.
Enforcement for additions
cargo xtask ui-containers is the mandatory repository gate, implemented once in
xtask/src/ui_containers.rs. The fast CI job runs it and its regression tests before
approval for heavy UI tests; cargo xtask ci runs it too. Draft PRs retain the repository’s
normal CI policy. It recursively parses Rust source and examples under every crate and
app, so new packages and nested modules are included automatically. The sole constructor
implementation exception is the exact ui_kit/container.rs path.
The gate rejects raw Area, Panel, Window, Modal, CentralPanel, Popup and SubMenu constructors, imported/module/type aliases and re-exports, constructor function references, qualified default constructors, struct literals, macro-hidden hosts and popup shortcuts. Host APIs are default-denied except for explicit popup-state operations, so new egui constructors are rejected automatically. Private raw host/module imports are rejected too, preventing aliases from escaping into another source file. It also rejects raw outer popup/window frames and custom outer shadows. Invalid Rust fails closed. Read-only state queries, content-only frames, and test-only fixtures remain valid; there are no per-feature allowances. This enforces the construction boundary; surface purpose and hand-painted content still need ordinary review.
New workspace panels must declare an adaptive Surface and use this policy for
host choice and outer chrome. Do not introduce another layout bool, raw host,
shadow or mode-specific frame in the feature module. Body groups, message bubbles,
field backgrounds and image frames are content; they may use local zero-shadow
frames or existing kit controls. Add new surface policies in the universal module
and test both modes and themes. Never add a per-file allowance to bypass the guard.
Retired implementation cleanup
The old report-window builder, window-width enum, heading-band colours and
caller-coloured icon API have been removed. Theme palettes and built-in theme
files no longer carry procedural command-icon colours; SVG artwork has one
palette authority. Only marker/pointer colours remain in the native glyph palette.
Older theme exports discard retired colour names at import so active overrides
still work; these names do not create renderer tokens or appear in new exports.
Unused History height state and superseded click/preview/modifier helpers are
also removed. The remaining frame helpers implement dragging and bounded
anchors used by current Panel compositions, rather than a second host or style.
Buttons and editors use shared kit controls too, including Assistant code-block
actions. The control guard scans all UI feature modules, even without a kit import,
so adding a new module cannot silently bypass the shared controls.