Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Reference test editor: user-interface specification

Status: draft specification for the reference test editor. The editor replicates the spatial layout, tool set, property sections and keyboard bindings of the Figma design editor (UI3) as documented in nuif:research:figma-ui3-editor-layout and nuif:research:figma-tools-and-keyboard-shortcuts, without branding, icons, logos, typography or colour values taken from that product. The feature set is limited to what conformance testing, import and export require. Anything not listed here is out of scope; additions require an RFC.

Implementation status: the native application implements the complete interactive surface for currently executable profile-zero properties: native document import/save and PNG export; bounded import and reported export through the declared SVG, HTML/CSS, DTCG, Penpot, static React JSX and static Svelte adapter profiles; history; pages/layers/components browsing; canvas selection, insertion, captured freeform-child movement, Stack/Flex reorder and bounded resizing; subtree duplicate/delete; responsive evaluation-width presets; zoom and interface visibility; a default pixel grid and rulers; command routing; and atomic name, position, sizing-intent, stack/flex spacing/alignment, bounded explicit Grid, solid-fill and pinned-text inspection. Freeform movement previews the selection outline, commits one position operation on release, snaps to whole pixels by default and suspends snapping while Control is held. A Stack/Flex child drag derives the effective axis from resolved sibling geometry, chooses a same-parent insertion point by sibling centres and commits one Move; unchanged order creates no history. Grid, Constraint, cross-parent and instance-child reorder fail closed instead of guessing semantics. Freeform children expose eight resize handles; managed-layout children expose only east, south and south-east handles because leading-edge anchoring would require an ineffective position edit. A resize previews resolved geometry and commits the changed fixed-size axes plus any freeform leading-edge position as one atomic transaction. Shift preserves the starting aspect ratio for corner drags, Control suspends whole-pixel snapping, and roots and non-finite, non-positive or greater-than-1,000,000 px dimensions fail without mutation. Canvas transforms require the Move tool. Grid authoring exposes positive fixed-pixel and fractional track lists, row/column sparse auto-flow, atomic one-based item position and positive spans; it cannot create implicit tracks or exceed profile-zero resource bounds. Each document edit lowers to an invertible protocol operation and is covered by the pointer/AccessKit/replay trial. Foreign imports open a new session after confirmation rather than mutating the current document. Sections below whose data is not in profile zero remain specification targets, not inert or simulated controls—most notably multi-selection, persisted aspect-ratio constraints, managed-layout leading-edge resize, cross-parent/tree drag and Grid/Constraint reorder, component authoring, in-editor token editing, advanced paints/effects, arbitrary foreign formats and non-PNG rendering export.

Native packages whose required capability set is not fully supported open structurally in a persistent read-only mode. Selection, inspection, static snapshot and byte-exact copying remain available, while driver and save-boundary mutations fail with the exact missing identifiers. This avoids silently carrying opaque resources onto a document revision they were not validated against.

Purpose and constraints

  1. The editor is a client of nuif-api. Every gesture lowers to protocol operations before any document mutation (apps/editor/ARCHITECTURE.md).
  2. The editor is a test instrument. Its state is NUIF state plus ephemeral selection, viewport and panel state.
  3. Automated test iterations use the CLI and the in-process session driver, not the GUI. The GUI exists to author fixtures by hand, to inspect import and export results, and to prove that a human-authored fixture and a replayed operation log converge (roadmap phase 5 exit).
  4. Layout conventions replicated here are user-interface conventions, not protected expression; names, marks, icons and visual assets are not reproduced (nuif:research:design-editor-ui-conventions-synthesis).

Regions

┌──────────────────────────────────────────────────────────────────────────────┐
│ [A] Top bar: document name · page selector · Minimize UI                     │
├───────────────┬───────────────────────────────────────────┬──────────────────┤
│ [B] Left      │ [C] Canvas                                │ [D] Right panel  │
│ panel         │  rulers · infinite canvas · zoom          │  zoom % · Export │
│  Pages        │  marquee · snapping · smart guides        │  ┌ Design ────┐  │
│  Layers       │  measurement overlay                      │  │ sections   │  │
│  Components   │      ┌───────────────────────────────┐    │  │ (resizable)│  │
│  (resizable)  │      │ [E] Toolbar (floating, bottom) │    │  └────────────┘  │
│               │      │ Move Hand Frame Shapes Pen Text│    │  Diagnostics     │
│               │      └───────────────────────────────┘    │                  │
└───────────────┴───────────────────────────────────────────┴──────────────────┘

Minimize UI collapses A and B; D reappears while a selection exists. Hide UI hides A, B, D and E. Panels B and D are resizable; widths persist per session only. Panel pixel widths are not specified by evidence and are chosen by implementation.

Left panel [B]

  • Pages: ordered list of surfaces (NUIF Surface entities); add, rename, reorder, delete.
  • Layers: containment tree of the current page; expand and collapse; drag to reparent and reorder; rename inline; visibility and lock toggles; multi-selection synchronized with the canvas.
  • Components: local component definitions of the document; drag to instantiate.

Excluded: team libraries, asset search, remote components.

Canvas [C]

  • Infinite canvas with independently toggled pixel rulers and a document-aligned background grid. The profile-zero authoring unit is px and is shown in the top bar, status bar and numeric inspector labels. The page background colour comes from the surface.
  • Interaction grammar (bindings in the table below): marquee selection from empty space; additive and subtractive selection; hierarchical traversal (child, parent, next and previous sibling); deep selection; duplicate by modifier drag; pan by Space drag or Hand tool; zoom by modifier scroll and by shortcuts (fit, selection, 100 %).
  • Snapping to objects and pixel grid with smart guides; suspended while the declared modifier is held. Measurement overlay to the hovered entity while the declared modifier is held.
  • Every canvas gesture emits one transaction: move in freeform becomes a transform edit; drag inside a stack becomes a reorder; resize becomes a sizing-intent edit or a fixed size according to the parent family (docs/whitepaper/03-protocol-and-portability.md).

Excluded: comments, cursors of other users, presentation mode, prototype links.

Toolbar [E]

Floating strip centred at the bottom of the canvas. Tools, in order, with their group menus:

GroupToolsEmits
MoveMove (V), Hand (H)selection and transform transactions; Hand emits nothing
RegionFrame (F)Insert of a Container
ShapeRectangle (R), Ellipse (O), Line (L)Insert of a Shape
VectorPen (P)Insert of a Shape(Path) and path edits
TextText (T)Insert of a Text entity
Actionscommand palette (Cmd/Ctrl K) listing every operation and command by namethe selected operation

The command palette is the keyboard route to every operation and to Import, Export, Validate and Snapshot. Excluded tools: Scale, Section, Slice, Polygon, Star, Arrow, Pencil, Comment, Dev Mode toggle, drawing and illustration tools, AI actions.

Right panel [D]

One tab, Design. Sections appear in this order for a container with a stack or flex family; sections absent for the selected kind are hidden.

  1. Header: entity name; Create component; Detach instance (for instances).
  2. Position: alignment row (six alignments and two distributions for multi-selection); X, Y; rotation; flip horizontal and vertical; constraints (freeform children only).
  3. Layout family: family selector (freeform, stack, flex, grid, constraint); flow direction and wrap; gap; padding uniform or per side; alignment grid. Grid containers additionally expose row/column sparse auto-flow and explicit column/row track lists using compact 120px 1fr syntax. Their children expose one atomic position field (auto or one-based column row) and positive column/row spans. This section replaces the product’s auto-layout section and exposes NUIF families directly.
  4. Sizing: W, H; per-axis intent (fixed, intrinsic, fill, fit-content, percentage); min and max; aspect ratio; clip content. Values are plain numbers or token references (see Tokens).
  5. Appearance: opacity; corner radius uniform or per corner; blend mode; visibility.
  6. Fill: ordered list of solid colour and linear or radial gradient paints; image fill for Image entities.
  7. Stroke: colour, weight, alignment, per-side, dash pattern, cap, join.
  8. Effects: drop shadow, inner shadow, layer blur, background blur.
  9. Typography (Text entities): font family from the pinned font set, weight, size, line height, letter spacing, alignment, text sizing behaviour.
  10. Component (definitions): parameters of kind boolean, enum variant, text, instance swap. Instance: parameter values and override reset.
  11. States: named interaction states (default, hover, pressed, focused, disabled) with per-state property overrides. This section exists because the v0 fixture requires state metadata; no prototype player is included.
  12. Tokens: every numeric or colour control accepts a token reference chosen from the document’s token set; a bound control shows the token name and a detach action. Token sets are edited in a dialog opened from the command palette (DTCG-compatible).
  13. Export: format (PNG, SVG, PDF, nuif-text-0, nuif-cbor-0, adapter targets), scale, suffix; Export opens the fidelity report.

Diagnostics: a collapsible list under the sections showing validation, fidelity and layout diagnostics for the selection, produced by nuif-api; each entry links to the entity.

Excluded: Prototype and Inspect tabs, selection colours, styles library, variables modes UI, glass, noise and texture effects, video and pattern fills, layout guides, image cropping, boolean operations, masks, vector networks beyond path editing, version history, branching.

Dialogs

  • Import: the File menu selects NUIF, SVG, HTML/CSS, DTCG, Penpot, static React JSX or static Svelte. External input is size-bounded before parsing; text profiles require UTF-8 while the Penpot profile validates bounded ZIP members in memory. A native NUIF package is structurally verified before opening; unsupported required capabilities are listed in the status bar and window title and force read-only inspection. A confirmation dialog shows fidelity-class and correspondence counts before the external imported document replaces the session as an unsaved document. Merge-into-document import is not implemented.
  • Export: the File menu selects PNG, SVG, HTML/CSS, DTCG, Penpot, static React JSX or static Svelte. Each external adapter export writes the artefact and a sibling .report.json; a profile mismatch fails before the destination chooser and writes nothing.
  • Tokens: token set editor.
  • Evaluation context: viewport size presets (360, 768, 1440 px and custom), scale factor, locale, writing direction, theme; the canvas renders the selected context; multiple contexts can be shown side by side for a surface.
  • Snapshot: writes the canonical document, the resolved snapshot for the current context and the CPU rasterization to a fixture directory in the harness format (conformance/HARNESS.md).

Keyboard bindings

Bindings reproduce the documented product bindings where verified; entries marked U in the source record are chosen to match common expectation and are not claimed to be product-accurate.

ActionmacOSWindows and Linux
Move, Hand, Frame, Rectangle, Ellipse, Line, Pen, TextV, H, F, R, O, L, P, Tsame
Command paletteCmd KCtrl K
Add or remove stack layoutShift A / Option Shift AShift A / Alt Shift A
Group / Ungroup / Frame selectionCmd G / Shift Cmd G / Option Cmd GCtrl G / Shift Ctrl G / Ctrl Alt G
Create component / Detach instanceOption Cmd K / Option Cmd BCtrl Alt K / Ctrl Alt B
Duplicate / duplicate by dragCmd D / Option dragCtrl D / Alt drag
Copy / PasteCmd C / Cmd VCtrl C / Ctrl V
Undo / RedoCmd Z / Cmd Shift ZCtrl Z / Ctrl Shift Z, Ctrl Y
Select all / inverseCmd A / Cmd Shift ACtrl A / Ctrl Shift A
Select child / parent; next / previous siblingEnter / Shift Enter; Tab / Shift Tabsame
Deep select; nested marquee; subtractive marqueeCmd click; Cmd drag; Shift dragCtrl click; Ctrl drag; Shift drag
Nudge 1 px / 10 pxArrow / Shift Arrowsame
Align left, right, top, bottom, centre horizontal, centre verticalOption A, D, W, S, H, VAlt A, D, W, S, H, V
Flip horizontal / verticalShift H / Shift Vsame
Zoom in / out; fit; selection; 100 %Cmd + / Cmd −; Shift 1; Shift 2; Shift 0Ctrl + / Ctrl −; Shift 1; Shift 2; Shift 0
Rulers; pixel gridShift R; Cmd ’Shift R; Ctrl ’
Minimize UI / Hide UICmd Shift \ / Cmd \Ctrl Shift \ / Ctrl \
ExportShift Cmd EShift Ctrl E
Temporarily disable snapping; measure to hoveredhold Control; hold Optionhold Control; hold Alt
Panhold Space and dragsame

Automation surface

The editor binary accepts --headless --script <file> and either --document <file> or --new-document <id>, then runs a session script against the same nuif-api engine without creating a window (nuif:research:blender-dna-rna-and-headless, nuif:research:unreal-asset-versioning-and-automation). --expect-document makes byte-exact parity blocking; --report and --snapshot-dir write the operation log and canonical/context/layout/scene/CPU-raster artifacts. The JSONL script language contains editor commands and semantic accessibility actions sharing one session.

The nuif-editor-automation feature-gated binary drives the native Masonry tree in process. It dispatches AccessKit actions, captures the matching accessibility tree and CPU-rendered shell frame, replays the protocol log independently and emits a machine-readable artifact set. cargo xtask editor-gui-trial repeats that run and requires identical canonical and pixel hashes. No socket transport is implemented.

Widget identity: every widget bound to a document entity exposes the entity identifier in its accessibility node (author_id), and every control exposes a role and label, so a harness locates “the width control of entity X” by query and sets it through an accessibility SetValue action (nuif:research:accesskit-semantic-ui-testing). No test depends on pixel coordinates of widgets.

Rendering and text

The canvas renders through nuif-render. Interactive rendering uses the Vello backend; snapshots and headless runs use the CPU reference backend so that editor snapshots and conformance references are produced by the same path. Fonts are limited to the pinned set shipped with fixtures; system fonts are not enumerated.

Implementation stack

Decided in ADR 0006 (accepted): Rust-native shell on Masonry (pinned by git revision; Xilem not used) with Vello rendering and AccessKit, replacing the earlier Svelte 5 shell proposal for the reference editor. The canvas lowers NUIF RenderScene to Masonry’s imaging command set; the CPU reference renderer in nuif-render remains the conformance oracle. Toolchain 1.98.0, MSRV 1.96. A browser build through WASM remains a later demonstration target, not the reference editor.


Canonical source.