FIGMA-SYNC — MATRIZ Editor UI mirror
Figma file: MATRIZ Editor UI · fileKey bZ17CtfEJ11rcV8UHNGKvh · team “Simao” (pro) › project Design System
Published team library (since 2026-08-22): library name “MATRIZ Editor UI”, libraryKey lk-b931c8db22df25b8ee2f083c2054745e097825332ca48818ced9d75442953f04… — 177 assets as last published (2 variable collections + Typography strings, 19 text styles, 5 effect styles, all component sets, 128 icons, 6 panel masters). ⚠️ The published library is STALE: as of 2026-08-29 every sampled component reports CHANGED or UNPUBLISHED, so library consumers still see the 2026-08-22 state. After any sync that changes tokens/components, re-publish: Figma UI → file menu → “Publish library…” (the plugin API cannot publish; it’s a manual/browser-driven step).
Created: 2026-08-22, generated from code via the official Figma MCP server (write path: use_figma Plugin-API scripts).
Round 5, 2026-10-16: borderless fields (
D:editor-outline-reduction, #1065) + Planned/Mobile pages. Variables (Editor Colors, 82 vars).core/field418:2 light 94%→92% (#ebebeb), dark a.09→.10. Newcore/field-hover436:2 (FRAME_FILL/SHAPE_FILL, WEBvar(--field-hover)): light 88% (#e0e0e0), dark white a.14. The six “drift” variables were already correct in Figma (darkcore/secondary208:3 +core/accent208:5 white a.15,core/secondary-foreground208:4 +core/accent-foreground208:6 +sidebar/accent-foreground208:15 white a.93,sidebar/ring208:16 white a.75 =index.css.dark), so nothing changed there; the drift was code-side and #1065 fixed it. Older drift found and fixed in the same pass (dark mode, values fromindex.css.dark):core/background2:3 →#16161a,core/card2:5 +core/popover208:7 →#1d1d22,sidebar/background2:27 →#1a1a1f,core/highlight204:2 →#2a2a30 (D:dark-ramp-soft-slate, Figma still had the pure-black ramp),core/destructive-text204:4 →#f98d8d, and alpha nudgescore/input208:10 +core/control418:3 .40→.41,core/chip-input418:4 .50→.55,core/muted-foreground2:14 /core/primary-faded98:4029 /core/foreground-tertiary165:2846 .55→.60. Light values forcore/input/core/outline/core/mutedalready matched (--input52% #858585,--outline56% #8f8f8f,--muted96.1%). Components (edited in place, strokes removed, fills bound tocore/field, focus = 1pxcore/ringstroke, hover =core/field-hover).Input23:646 andSelect / Trigger23:653: all variants borderless; addedstate=hover(436:12207 / 436:12211) andstate=error(1pxcore/destructive; 436:12209 / 436:12214) desktop variants.PropertyEditor / FieldShell26:163 (18value-unit-inputframes; hover members usecore/field-hover, focused keeps the ring).Grammar / FieldRow422:791 fields (PairRow 422:816 inherits),Grammar / AlignmentMatrix422:836,Grammar / SegmentedControl422:844 (trackcore/field, active option 422:838 =core/background+Shadow/sm),PropertyEditor / ClusterSwitch25:131 (trackcore/field, active chips 13:50 / 25:121 =core/background+Shadow/sm),Button10:68variant=outline(20 members: fillcore/field, hovercore/field-hover, focus ring;outline-dasheduntouched). Mobile page: 12 hand-builttextarea/searchframes un-stroked. Paint trap, again: binding an alpha variable with a placeholder black paint renders black in the component sets even though it rendered correctly in a scratch frame; setting the paintcolorto the variable’s resolved dark RGB andopacityto its alpha (in addition to binding) fixed it (rule in Figma MCP gotchas above). Bound paints ignore their ownopacitywhen the variable carries alpha; verified in light and dark. Pages. Mobile424:2already existed (built 2026-10; undocumented until now): sectionsMobile / Shell424:3 (TabBar 424:128, ScreenHeader 424:142, ListRow 424:164, SectionLabel 424:167, OpenOnDesktop 424:175, FAB 424:181, ViewBanner 424:193, BottomSheet 424:287),Mobile / Slice parts426:650, and screen sections Shell 425:110 (Sites = Home list 425:111, More, Team, sheets), Canvas 427:754 (edit + inspector 427:755, layers sheet 427:924, preview, publish confirm, replace image), Email 428:1550 (campaigns, new campaign sheet 428:1696 = send step 1, detail, send confirm sheet 428:1991, block edit/add), CMS 430:2867 (collections, items, item editor 430:3193, image source sheet); each in Dark and Light at 390x844. No page was created. Planned - Formats438:2(new): 12 frames labelled “PLANNED (not built)” fromD:formats-owner-decisions: S3 438:3, DIFF 438:53, S5 438:89, S7 438:160, S12 438:187, S11 438:233, S13 439:2, F6 439:27, M6 Settings > Access 439:88, BULKCAP 439:122, S8 439:161, M6 phone notice 439:193 (only feature with a phone variant; the Formats workspace is desktop). Hand-built from tokens (no components instanced exceptMobile / TabBarin 439:193); they are drafts, not specs. Motion Studio skipped (no concrete UI specified). Remaining gaps. No Figma component forNumberControl,Textarea, standaloneValueUnit;FieldShellhas noerrormember;source-switcher(26:163 children) kept its border (code unverified); Tier 3 holdouts stay bordered by design (EntityPicker 423:954, Grammar Tabs 422:846);ActionToggle338:7370 default keeps its 8% stroke. Darkbg-white/15active segment in the decision does not match code (ClusterSwitch.tsx:80=bg-background); Figma mirrors the code. Library not re-published (plugin API cannot): publish from the Figma UI. A UX review of the synced UI and the planned frames was written to the session scratchpad (not committed); its top findings are in the hand-off report. 2026-09-23 (D:ancestor-state-layer,D:view-switch). The state row gained a trailing+trigger (AncestorLayerMenu.tsx, lucidePlus,text-muted-foreground), rendered byPropertyEditorShell.tsxright AFTER<StateTabBar />in the same flex row (code: outside thebg-mutedpill; the mirror draws it as the set’s last child — a known 2px simplification): everyPropertyEditor / StateTabBarvariant (13:38,25:132,25:143,25:154,25:165) got anadd-ancestor-layerframe (404:725/404:730/404:735/404:740/404:745) holding anicon/Plus9:96 instance at 12px, strokes bound tocore/muted-foreground. The popover it opens (ancestor-state input, group-hover row, hover-group checkbox) is NOT mirrored — same precedent as the other un-drawn popovers. New palette iconicon/LayoutList404:10 (Icons section 9:128, x=120 y=560,createNodeFromSvg, strokes bound tocore/foreground@0.93 like the set) for the Filters family’s “View switch” entry; the add-element palette itself has no mirror. Library not re-published from here (plugin API cannot) — publish from the Figma UI. S30 check, 2026-09-21 (D:list-chrome-section). Two chrome changes to sync:CollectionControlSection.tsx’s Mode pill → plain summary sentence + two new nav-option checkboxes, and a newListChromeSection.tsxmounted fromDataBindingProperties.tsx. CheckedPropertyEditor / CollectionControlSection213:6072before editing: it only ever depicted the FILTER-role rows (Repeater/Field/Operator/Value) — the Mode pill, Rendered items/Reveal size fields and now the two nav-option checkboxes belong to theloadmore/legacy-pagination/pager-role rows, which this mirror has never drawn. No edit needed there, same as the S36 check’s precedent.PropertyEditor / DataBindingProperties213:6008DID need updating: it lists every Data-tab section as aCollapsibleSection Header(9 before this — Data Source/Entry/Pre-Filters/Default Sort/Group By/Limits & Pagination/Repeater State/Empty & Loading/Visitor Controls, in the same order the code renders them, 3 with example bodies drawn), and the code gained a 10th section between Limits & Pagination and Repeater State. Cloned theVISITOR CONTROLSheader instance (213:6063,expanded=false/ overridden=falsemember of set26:137), retitled its text node toLIST CHROME, andinsertChild’d it at the correct index —213:6008‘s auto-layout (VERTICAL,primaryAxisSizingMode: AUTO,itemSpacing: 1) grew it 388→420px automatically, and the parent rowRow / Data & Logic209:5178(HORIZONTAL,counterAxisSizingMode: AUTO) re-hugged to match with no manual resize and no sibling reflow (siblings sit side-by-side on the same axis). New node: INSTANCE399:11(title textI399:11;26:118). Verified withget_screenshotbefore and after the move — no clipping, no overlap, spacing matches its 9 siblings exactly. Deliberately left as a collapsed placeholder, same deferral every other un-bodied header here already carries: the roster, the mode-summary sentence, and the Rendered-items/Reveal-size fields the real section shows are NOT drawn —DataBindingProperties’ own documented state is “4 of 9 sections populated… the remaining deferral,” and List chrome joins the 5 (now 6) that aren’t. No library re-publish needed for this change: an INSTANCE of an already-published component was added and repositioned, no component/variant/token definition changed. S36 check, 2026-09-21 (D:controls-on-data-tab).QuickStylesProperties.tsx’s Style-tab quick section stopped mounting the imported-control section, the native filter family (Filter Bar/Group/Control) and the Carousel/Slider sections — they now mount on the node’s Data tab inPropertyEditorShell.tsx(owner call Q1, 2026-09-20: “nothing in the quick-style section”). Checked the mirror before editing it: no edit was needed.PropertyEditor / CollectionControlSection213:6072was already grouped underGroup / Data & Logic209:5176→Row / Data & Logic209:5178(alongsideDataBindingProperties/ConditionalVisibilityProperties/LinkProperties), not under the Quick/Style family — the module catalog already modelled the destination this fix moves the live code to.PropertyEditor / QuickStylesProperties213:5616only ever showed generic collapsedCollapsibleSection Headerplaceholders (Text style / Fill / Radius / …), never a literal Slider/Carousel/Filter instance, so nothing there depicted the old (now wrong) placement either.FilterBarSection,FilterControlSection,SliderSectionandCarouselSectionhave no Figma mirror at all — confirmed by listing everyPropertyEditor / *component underProperty Modules - Page Root209:5165(19 total, none named for these four) — a pre-existing gap this change neither introduces nor closes; recorded under “Known gaps” below rather than silently skipped. While checking this, found the page map below stale (Property Modules208:21/Property Parts208:22no longer exist as top-level pages — merged intoProperty Editor368:2354at some point after the last page-map update); corrected in place. Round 4 (FU-5), 2026-09-13. Mirrored the preview-mode comments chrome that landed on master (D:preview-topbar,D:canvas-comments): the newPreviewTopBar.tsxthat replaced the floatingPreviewModeControlspill, the AppSidebar “To-do” mode, and the canvas comment pins/thread popover. New:Panel / PreviewTopBar394:3 (Panels page, 1440×56, same fill/border tokens asPanel / TopBar);Canvas / CommentPin392:363 (SET, axiskind= Open392:355/ Resolved392:357/ Draft392:359);Canvas / CommentThreadPopover394:2 (both inSection / Preview & modes209:97 on Canvas & Overlays, which grew 509→849px, pushingSection / Overlays & menusandSection / Command surfacesdown 340px — same page, new absolute y);TodoRow395:587 (Panels page, MenuRow/TreeRow-style wrapper) holdingStatus=Open395:588 /Status=Resolved395:589;Panel / Todo395:7853 (Sidebar Panels page, x=3060, the 10th→11th sidebar-mode master, instancing the two TodoRow variants).Panel / IconTray27:432 gained amode-todorow (394:7627,icon/ListTodo) betweenmode-modulesandmode-settings— the tray’sspacerchild shrank 356→316px to keep the master at its original 844px height andBehaviorSwitcherpinned at y=804, matching the code’smodesarray order inAppSidebar.tsx. Five lucide icons were missing and got added to the Icons page (section 9:128, grown 580→620px):icon/ListTodo387:9,icon/MessageSquare387:13,icon/MessageSquareOff387:19,icon/MapPin387:24,icon/RotateCcw387:29 — all bound tocore/foregroundper sync-contract rule 4, built viafigma.createNodeFromSvg()(theupload_assetsegress block still applies, see gotcha below).Canvas / PreviewModeControls213:7494 is NOT deleted — itsdescriptionnow says SUPERSEDED (D:preview-topbar), left in place for reference. TheCommentComposerface ofCommentThreadPopover.tsxis not separately mirrored — only theCommentThread(read) face; noted as a gap below. Library re-publish is pending (adds 5 icons, the CommentPin set, CommentThreadPopover, Panel/PreviewTopBar, Panel/Todo, TodoRow to the count in the header above). Round-2 code→Figma sync, 2026-08-30. Six surfaces that landed on master that day were pushed into the mirror: the QuickToolbar identity-bar rebuild (D:toolbar-identity), the token popover’s new Scope tab (D:token-scopes), the token matrix’s inline rename (D:token-rename), the symbol instance bar’s copy state (Detach→Unlink), and the library variant section’s multi-axis rewrite (D:library-variant-fixes). The three new inventory sections needed no work — round 3 had already mirrored them. Details below under “Round 2 (2026-08-30)”.
Re-synced from the live file 2026-08-29 (round 3 —
plans/FIGMA-PARITY-ROUND3-PLAN.md; the audit that triggered it isdocs/Research/FIGMA-MIRROR-DRIFT-AUDIT.md). What changed: the dark palette is now alpha-based on BOTH sides (D:alpha-token-rebase),Editor Colorswent 52 → 81 variables, and four new pages carry 142 components mirroring the editor surfaces that had never been drawn. The variable-ID map below was regenerated — 22 IDs in the previous revision pointed at deleted variables.
Source of truth: the CODE. The Figma file is a mirror of frontend/src. When they disagree and no intentional design change is in flight, the code wins. When a design change is made by hand in Figma, it flows back to code via the /figma-editor-sync skill, and this doc is updated in the same change.
Sync contract (read this before touching either side)
Section titled “Sync contract (read this before touching either side)”- Editor theme tokens live in
frontend/src/index.css(lines ~6–85) +frontend/tailwind.config.js. They are mirrored 1:1 as Figma variables in the collections below. Any change to a CSS variable value, a Tailwind color mapping, or--radiusMUST be pushed to the matching Figma variable (both modes), and vice-versa. - Dark is the default mode in Figma (first mode), because the app defaults to dark (
index.htmlFOUC script,themeStoredefault). Light is the second mode. - Chrome accent semantics (orange=component/override, sky=data, emerald=style-dot, purple=state-dot, teal=dynamic-dot, blue=binding, amber=conditional/warning, violet=variant chip, green=shared-style-linked) are contracts from
frontend/src/lib/node-semantics.tsandfrontend/src/components/property-editor/registry/DESIGN-SYSTEM.md. They exist assemantic/*,dot/*,state/*,accent/*variables. Their WEB code syntax stores the Tailwind class, not a CSS var, because that is what the code uses. - Icons are lucide-react 0.552.0, uploaded as exact SVGs and componentized at 16×16 with stroke ≈1.333 (24-grid rescaled ×2/3), strokes bound to
core/foreground. If the app adds a new lucide icon, regenerate its SVG fromfrontend/node_modules/lucide-react/dist/esm/icons/(follow alias re-exports) and add anicon/<PascalName>component. Never redraw icons by hand. - Fonts: Geist / Geist Mono (Google Fonts; loaded in
index.html). In Figma the style name isSemiBold(no space) — unlike Inter’sSemi Bold. - No motion to model.
tailwind.config.jsshipsplugins: [](notailwindcss-animate), so all shadcn enter/exit animation classes are inert in the app.
Figma object map (node IDs are stable — do not recreate, edit in place)
Section titled “Figma object map (node IDs are stable — do not recreate, edit in place)”| Page | ID | Holds |
|---|---|---|
_staging (scratch, keep empty) |
0:1 | — |
| Cover | 6:2 | frame 22:432 |
| Foundations (swatch boards, type ramp) | 6:3 | 22:436 / 22:600 / 22:764 |
--- LIBRARY --- (divider) |
6:4 | — |
| Icons | 6:5 | section 9:128, 152 icon/* components |
| Components | 6:6 | 39 components in 5 sections (162:4892 UI Primitives · 162:4894 Property Editor · 162:4896 Chrome & Navigation · 162:4898 Sections · 162:4900 CMS) |
| Chrome Parts | 6:7 | empty — its 8 components moved onto Components 6:6; the IDs below are unchanged |
--- SCREENS --- (divider) |
6:8 | — |
| Editor Screen | 6:9 | full-UI frames 14:2 (dark) / 28:1307 (light) |
| Panels | 27:371 | 22 masters |
| CMS | 63:2 | 4 panels + 12 CMS / * components + the owner’s 2026-08-28 exploration |
| Sidebar Panels | 73:2 | 11 masters, one per AppSidebar.tsx mode (added 2026-09-13: Panel / Todo 395:7853) |
--- MICRO-PANELS --- (divider) |
208:20 | — |
Property Editor (found 2026-09-21 as the merged home of the old “Property Modules” 208:21 / “Property Parts” 208:22 pages — those two IDs no longer exist as top-level pages; get_metadata/figma.root.children both confirm) |
368:2354 | Panel Assembly 368:2355 (Panel/Properties, PropertyTabStrip, SelectionColors, GridRules, AddPropertyButton, TokenDetailPopover); Property Modules - Page Root 209:5165 (19 PropertyEditor / * module components, grouped into Group / <family> sections — PropertyEditor / CollectionControlSection 213:6072 sits in Group / Data & Logic 209:5176 alongside DataBindingProperties/ConditionalVisibilityProperties/LinkProperties, NOT under the Quick/Style family — see D:controls-on-data-tab note below); Property Parts Root 365:2705; WIP / Grid Layout Explorations 368:2356; Data & Logic Sub-editors 368:2357 (the DataBindingProperties sub-editor shelf: DataSourceSelector, QueryBuilder, SortingEditor, GroupByEditor, LimitsEditor, RepeaterStateTabs, PropertyBindingsEditor) |
| Canvas & Overlays | 208:23 | 22 components |
| App Surfaces | 208:24 | 44 components |
| Mobile (documented 2026-10-16) | 424:2 | phone editor chrome, 5 sections, 390x844 frames Dark+Light (see Round 5 note) |
| Planned - Formats (2026-10-16) | 438:2 | 12 “PLANNED (not built)” frames, D:formats-owner-decisions |
Variable collections
Section titled “Variable collections”| Collection | ID | Modes |
|---|---|---|
Editor Colors (82 vars, +core/field-hover 436:2: core/*, chart/*, sidebar/*, semantic/*, dot/*, state/*, accent/*, status/*, overlay/*) |
VariableCollectionId:2:2 | Dark 2:0 (default), Light 2:1 |
Editor Metrics (34 floats: radius/*, layout/*, icon/*, spacing/*px, text/*) |
VariableCollectionId:4:2 | Value |
Editor Typography (family/sans = Geist, family/mono = Geist Mono) |
VariableCollectionId:4:37 | Value |
| Bookbuilder Colors (MISPLACED — relocated to the bookbuilder file, pending deletion here; see “Bookbuilder tokens” below) | VariableCollectionId:203:2 | Value 203:0 |
The 2026-08-29 drift check is CLOSED — the hand-rework was adopted, not reverted. An
independent code→Figma pass that same day (master d7e0c70) found the Editor Colors collection
hand-edited away from code: 22 ledger variables deleted, ~20 added with no WEB code syntax, and
every dark neutral rewritten to white-alpha overlays while light still matched index.css. It
correctly declined to revert and asked for a direction. The owner’s call was to adopt it, so
round 3 pulled it into code (D:alpha-token-rebase — see
plans/FIGMA-PARITY-ROUND3-PLAN.md §1 for the Tailwind mechanism that makes token-level alpha
survive /opacity modifiers), re-created the deleted variables the app still uses, and gave every
variable a WEB code syntax. The full finding is preserved in
docs/Research/FIGMA-MIRROR-DRIFT-AUDIT.md; the collection is authoritative again, in both
directions.
Also landed by that pass and still true: core/highlight 204:2, core/highlight-foreground
204:3, core/destructive-text 204:4 (FX-9 code tokens that Figma lacked, values from
index.css both modes, with swatch rows on both Foundations boards — dark 204:5/204:8/204:11,
light 204:14/204:17/204:20); Editor Metrics text/micro-9|label-10|value-11 WEB syntax corrected to
text-4xs/text-3xs/text-2xs (the FX-9f micro-type scale); and 10 chrome icons (Icons page
below). Checked clean and still clean: --radius 6px = radius/lg, Geist/Geist Mono, and the
layout metrics (topbar 56, tray 48, panel 300/240–640, headers 40, control 24/28).
Do not hand-maintain a full variable-ID list here. The previous revision’s list went stale in three days (22 of 54 IDs deleted, 20 added under new IDs). Query the live file by name instead:
const vars = await figma.variables.getLocalVariablesAsync()const byName = Object.fromEntries(vars.map(v => [v.name, v.id]))Anchors worth knowing, because code reads them constantly: core/background 2:3, core/foreground
2:4, core/card 2:5, core/primary-foreground 2:10, core/muted 2:13, core/muted-foreground
2:14, core/destructive 2:17, core/border 2:19, core/ring 2:21, chart/1–chart/5 2:22–2:26,
sidebar/background 2:27, sidebar/foreground 2:28, sidebar/accent 2:31.
Added 2026-08-29 (round 3): core/{primary 208:2, secondary 208:3, secondary-foreground 208:4, accent 208:5, accent-foreground 208:6, popover 208:7, popover-foreground 208:8, card-foreground 208:9, input 208:10, destructive-foreground 208:11} (re-created — the app still uses them);
sidebar/{border 208:12, primary 208:13, primary-foreground 208:14, accent-foreground 208:15, ring 208:16}; status/approved-{bg 208:17, fg 208:18, dot 208:19} (the code has FIVE statuses);
semantic/{component-badge-bg 234:6246, data-text 234:6247, data-badge-bg 234:6248, conditional 234:6249} and state/shared-style-linked 234:6250 (restored node-semantics.ts contracts);
accent/{insert-flow 234:6251, insert-cross 234:6252, state-lens-ghost 234:6253} — these three
expose colours the code hardcodes (CanvasAddButton.tsx:90-91 #3b82f6/#8b5cf6, duplicated in
preview.html; StateLensChip.tsx:123 indigo-500, a hue with no family in this system).
Gap, 2026-10-05 (D:brand-logo-lime): --brand (74 92% 54%, #c3f61e) and --brand-foreground (0 0% 3.9%) are in index.css/tailwind.config.js but not yet mirrored — add accent/brand + accent/brand-foreground to Editor Colors (same value both modes) and to both Foundations swatch boards, then record the IDs here.
Added 2026-08-30 (round 2): semantic/override-badge-bg 301:1270 — bg-orange-500/10,
the BADGE_TONE_CLASS.override wash behind state/override text. It exists because an
INSTANCE drops a manually-set paint opacity when the paint is variable-bound: the identity
chip’s badges carried opacity: 0.15 on a paint bound to semantic/component-text, and every
instance of them re-resolved to the variable’s own opaque value, rendering solid orange blocks
inside Panel / QuickToolbar. The wash has to live IN the variable. The badge fills are now
bound to semantic/component-badge-bg 234:6246 / semantic/data-badge-bg 234:6248 /
semantic/override-badge-bg 301:1270 / core/muted 2:13 accordingly.
core/secondary-foreground 165:2846 was renamed core/foreground-tertiary — it holds
white@32%, which is a tertiary text tone, NOT shadcn’s --secondary-foreground. The real
--secondary-foreground is 208:4. Every variable now carries a WEB code syntax; that mapping is the
code↔design contract while Code Connect stays plan-blocked.
Styles
Section titled “Styles”19 text styles (Micro 9/*, Label 10/*, Value 11/*, XS 12/*, SM 14/*, Base 16/*, LG 18/SemiBold, Mono 9–12/Regular) and 5 effect styles (Shadow/sm|default|md|lg|xl = Tailwind v3 defaults).
Components (Components page) — all interactive sets carry a state axis (2026-08-22)
Section titled “Components (Components page) — all interactive sets carry a state axis (2026-08-22)”| Component | ID | Variants | Code source |
|---|---|---|---|
| Button (set) | 10:68 | variant(6) × size(4) × state(default/hover/focus/disabled) = 96 | ui/button.tsx |
| Badge (set) | 10:81 | variant(6) × state(default/hover) = 12 | ui/badge.tsx |
| Input (set) | 23:646 | state default/focus/disabled/hover/error, borderless (default member = 11:20) | ui/input.tsx |
| Select / Trigger (set) | 23:653 | state default/focus/disabled/hover/error, borderless (default member = 11:22) | ui/select.tsx |
| Switch (set) | 11:31 | checked(on/off) × state(default/disabled) | ui/switch.tsx |
| Checkbox (set) | 11:37 | checked(true/false) × state(default/disabled) | ui/checkbox.tsx |
| Separator / Horizontal | 11:38 | — | ui/separator.tsx |
| Tooltip | 11:39 | — | ui/tooltip.tsx |
State styling encoded from code: hover = /90 (primary,destructive), /80 (secondary, badge fills), bg-accent + text-accent-foreground (outline,ghost), underline (link — default link is NOT underlined); focus = 1px OUTSIDE stroke bound to core/ring; disabled = node opacity 0.5.
Chrome parts (Chrome Parts page)
Section titled “Chrome parts (Chrome Parts page)”| Component | ID | Variants | Code source |
|---|---|---|---|
| Sidebar / Mode Button (set) | 12:18 | state active/idle/hover | AppSidebar.tsx IconTray |
| Panel / Header | 12:19 | — | AppSidebar.tsx ExpandedPanel |
| DOMTree / Row (set) | 12:91 | state idle/hover/selected/multi/drop-target/hidden | DOMTree.tsx |
| PropertyEditor / StateTabBar (set) | 25:176 | active-tab Default/Hover/Active/Focus/Disabled (Default member = 13:38); trailing add-ancestor-layer + (2026-09-23) |
shared/StateTabBar.tsx |
| PropertyEditor / ClusterSwitch (set) | 25:131 | selected Desktop/Mobile (Desktop member = 13:49) | shared/ClusterSwitch.tsx |
| PropertiesPanel / UiModeToggle (set) | 25:116 | selected Simple/Advanced (Advanced member = 13:63) | PropertiesPanel.tsx |
| PropertyEditor / CollapsibleSection Header (set) | 26:137 | expanded(t/f) × overridden(t/f) (collapsed+overridden member = 13:89) | shared/CollapsibleSection.tsx |
| PropertyEditor / FieldShell (set) | 26:163 | state default/modified/bound (default member = 13:97) | registry/FieldShell.tsx |
Panels page — one editable component per chrome region (masters; the full-UI frames hold INSTANCES, so edits here propagate everywhere)
Section titled “Panels page — one editable component per chrome region (masters; the full-UI frames hold INSTANCES, so edits here propagate everywhere)”| Panel component | ID | Code source |
|---|---|---|
| Panel / TopBar (1440×56) | 27:372 | TopBar.tsx |
| Panel / IconTray (48×844) | 27:432 | AppSidebar.tsx IconTray |
| Panel / DOMTree (300×844) | 27:507 | AppSidebar.tsx + DOMTree.tsx |
| Panel / CanvasColumn (792×844) | 27:671 | CanvasPanel.tsx + CanvasTabs.tsx + CanvasBottomBar.tsx |
| Panel / Properties (300×844) | 27:764 | PropertiesPanel.tsx + PropertyEditorShell.tsx |
| Panel / PreviewTopBar (1440×56) | 394:3 | canvas/PreviewTopBar.tsx (D:preview-topbar, added 2026-09-13) — the bar preview mode shows instead of Panel / TopBar, same height/fill/border tokens. left-group (Exit Preview · page tabs) · centre-group (a clone of the BreakpointSelector instance also used in Panel / TopBar) · right-group (language · split · separator · PreviewAsSelector · separator · comment-mode toggle · To-do badge). Supersedes Canvas / PreviewModeControls 213:7494 (left in place, description now says SUPERSEDED) |
| TodoRow | 395:587 | comments/TodoPanel.tsx row markup, MenuRow/TreeRow-style wrapper holding Status=Open 395:588 / Status=Resolved 395:589 (checkbox icon · body + meta · delete) |
| Panel / QuickToolbar (docked) | 28:371 | canvas/QuickToolbar.tsx — rebuilt 2026-08-30 as the IDENTITY BAR (D:toolbar-identity). Row = 3 handles · separator · identity (an INSTANCE of Canvas / SelectionIdentityChip, capped at the 260px IDENTITY_RESERVE) · separator · actions in the declared priority order of canvas/toolbar-layout.ts, then the ⋯ trigger LAST. 740×40. ⚠️ 61:709 (qt-radius) no longer resolves — radius folded into the compact spacing trigger and the old row was replaced |
| Popover / PublishMenu | 40:426 | PublishMenu.tsx PopoverContent |
| Popover / StatusControl | 40:460 | TopBar.tsx StatusControl popover |
| Popover / ProjectSwitcher | 40:477 | TopBar.tsx ProjectSwitcher popover |
| Popover / BreakpointSelector | 41:459 | BreakpointSelector.tsx PopoverContent |
| Menu / EditorModeSwitcher | 41:514 | TopBar.tsx EditorModeSwitcher dropdown |
| Panel / TokenMatrix (FX-1/FX-2) | 52:474 | theme-editor/TokenMatrix.tsx — states-as-columns grid (member/ghost/editing cells, override dots, prefix group headers) |
| Section / SelectionColors (FX-5) | 53:496 | property-editor/sections/SelectionColorsSection.tsx — instance also lives inside Panel / Properties (53:544) |
| Section / PropertyTabStrip (FX-12a) | 60:699 | PropertyEditorShell.tsx — variant set: labels=true (strip ≥380px) / labels=false. 5-way taxonomy incl. the NEW Color tab; the icon is unconditional, so a text-only strip is unrepresentable |
Panel / TokenDetailPopover (D:token-scopes) |
313:1032 (SET, axis tab = Details 312:995 / Scope 313:995) |
theme-editor/TokenDetailPopover.tsx — Figma’s own Details | Scope shape. Scope is the checkbox tree writing value.$extensions.matriz.scopes; “Show in all supported properties” ON == no authored scopes == pre-feature behaviour, and the per-scope boxes are disabled while it is on. Labels from TOKEN_SCOPE_LABELS (lib/tokens/relevance.ts) |
| Section / GridRules (FX-12e) | 61:650 | property-editor/modules/GridRulesSection.tsx — nth layer family (nth<a>[+<b>], first, last) styling the container’s DIRECT CHILDREN |
CMS page — the content surfaces (added 2026-08-24)
Section titled “CMS page — the content surfaces (added 2026-08-24)”| Component | ID | Code source |
|---|---|---|
| Panel / CMS Sidebar (220×940) | 63:3 | cms/CollectionSidebar.tsx — search, Name/Tag sort toggle, Members, grouped collections (FORMS/AUDIENCES/SINGLETONS/COMMERCE/CONTENT/OTHER) with counts |
| Panel / CMS Table (960×940) | 65:97 | cms/TableView.tsx — toolbar, schema-derived column headers, entry rows, paging footer |
| Panel / CMS EntryRail (420×940) | 66:167 | cms/RowDetail.tsx — status badge + workflow actions, schema-driven fields, timestamps, Connections |
| Section / Connections (FX-12j) | 63:191 | cms/RowDetail.tsx ConnectionsSection — lazy backlinks: “Mentioned in N items” (quoted-phrase FTS, in <field>) + “Referenced by N items” (structural refs, via <field>), each row with a collection chip |
| Full-UI frame | ID | Mode |
|---|---|---|
CMS — Dark / 1600×1000 |
66:2566 | explicit Dark (2:0) — instances of the three CMS panels + CMSLayout header |
CMS — Light / 1600×1000 |
66:3144 | explicit Light (2:1) |
Built from the live /ui-lab?view=cmsrow render (ground truth) rather than from code-reading alone.
Related research: docs/Research/FIGMA-VARIABLES-UX.md — captured Figma’s own variables/component-property UX (2026-08-22) with takeaways for MATRIZ’s token editor and FieldShell.
Icons page — icon/<PascalCaseLucideName> (157 components)
Section titled “Icons page — icon/<PascalCaseLucideName> (157 components)”icon/Box = 8:2, icon/Palette = 15:127, the rest are 9:2 … 9:127 in a single section (9:128, now 540×620 — grown 2026-09-13 for the row below). Added 2026-08-29 (chrome imports that were missing): icon/Clock 206:2, icon/Columns3 206:3, icon/FileSpreadsheet 206:4, icon/HelpCircle 206:5, icon/List 206:6, icon/MoveHorizontal 206:7, icon/MoveVertical 206:8, icon/SortAsc 206:9, icon/SortDesc 206:10, icon/SplitSquareHorizontal 206:11 (aliases followed: HelpCircle→circle-question-mark, SortAsc→arrow-up-narrow-wide, SortDesc→arrow-down-wide-narrow, SplitSquareHorizontal→square-split-horizontal; section grown to 540px tall). Added 2026-08-29 (round-3 follow-up, ids 255:10–255:97): Minimize2, MoreVertical, BarChart2, FileUp, ArrowRight, Save, UserRound, Bot, MousePointerClick, Key, Code, FileCode, Terminal, Sliders. Aliases that bit: MoreVertical→ellipsis-vertical, BarChart2→chart-no-axes-column, Sliders→sliders-vertical. Deliberately NOT added: Users2, Building2, Globe2, ImagePlus — a track wanted them, but no file in frontend/src imports them, and the mirror only carries icons the app actually renders. Layers2 already existed (9:66). Added 2026-09-13 (FU-5, the preview-comments chrome): icon/ListTodo 387:9, icon/MessageSquare 387:13, icon/MessageSquareOff 387:19, icon/MapPin 387:24, icon/RotateCcw 387:29 — no aliasing needed, all five are direct lucide-react 0.552.0 filenames. Built via figma.createNodeFromSvg() (the upload_assets recipe is still blocked in this environment, see the gotcha below), rescaled 24→16 preserving offsets, strokes bound to core/foreground at the same 0.93 opacity as the existing set.
Look up by name with page.query('COMPONENT[name=icon/<Name>]') — names match lucide-react import names (aliases preserved: Layout, Wand2, Loader2, CheckCircle2, MoreHorizontal, Columns, Rows, Filter, Home, Layers3, AlignLeft/Center/Right, FilePlus2, Code2 etc.).
Editor Screen page — full-UI frames composed from Panel instances
Section titled “Editor Screen page — full-UI frames composed from Panel instances”| Frame | ID | Mode |
|---|---|---|
Editor — Dark / 1440×900 |
14:2 | explicit Dark (2:0) — instances of the 5 panels + floating QuickToolbar instance |
Editor — Light / 1440×900 |
28:1307 | explicit Light (2:1) via setExplicitVariableModeForCollection — same panel instances, tokens flip automatically |
The original hand-built panel subtrees were converted to components with createComponentFromNode (2026-08-22); the frames now hold instances — edit the masters on the Panels page, both frames update. New full-UI frames = instantiate the 6 panel components + set an explicit Editor Colors mode on the frame.
Canonical state mirrored: Neutral accent, editor mode, tree sidebar mode active, “CTA Button” selected (bg-primary row + canvas selection ring + breadcrumb), Layout property tab active, SIZING expanded, FILL with override dot, Events Grid subtree data-bound (sky) with REPEATER chip.
Micro-panel pages (added 2026-08-29, round 3) — 142 components
Section titled “Micro-panel pages (added 2026-08-29, round 3) — 142 components”Four pages mirroring the editor surfaces that had never been drawn. Every component’s
description is its source file path; names match the code symbol. Look one up by name rather
than by ID: page.query('COMPONENT[name=PropertyEditor / LayoutProperties]').
| Page | ID | Contents |
|---|---|---|
| Property Modules | 208:21 | 28 components, all 300px (layout/panel-width), from property-editor/modules/* + sections/*. Sections: Layout & Position, Typography & Color, Effects & Style, Data & Logic, Structure & Attributes, Selection Inventories. Anchors: LayoutProperties 213:50, TypographyProperties 213:5479, DataBindingProperties 213:6008, VisibilityTierBadge 213:6167 (SET, axis tier). The 7 data-binding/components/* sub-editors were added 2026-08-29: DataSourceSelector 255:6596, QueryBuilder 255:6618, SortingEditor 255:556, GroupByEditor 255:6666, LimitsEditor 255:6576, PropertyBindingsEditor 255:6716, RepeaterStateTabs 255:6560. |
| Property Parts | 208:22 | 48 components from property-editor/shared/* (19), property-inputs/* (8), and 21 modals/bars/sections. Anchors: OverrideDot 213:36, StatusBadge 213:49 (SET), FillPicker 213:7068, CmsBindingModal 213:8081. Round 2: SymbolInstanceBar is now COMPONENT_SET 309:6686 (axis role = Master 234:6199 / Copy 309:64) — combined in place, not recreated; LibraryVariantSection 234:6245 rewritten to one select per axis. |
| Canvas & Overlays | 208:23 | 22 components from canvas/* + the editor chrome overlays. Anchors: SelectionIdentityChip 213:29 (SET), EdgeInsertButton 213:6249 (SET — merges CanvasAddButton + CanvasInsideAddButton, 3 colour intents), CommandPalette 213:8415, UndoHistoryPanel 213:8477. Added round 2: Canvas / IdentityBadge 302:285 (SET, axis tone = Component/Data/Override/Neutral — the BADGE_TONE_CLASS vocabulary) and Canvas / QuickToolbar Overflow 303:277 (the ⋯ popover). Both live in Section / Selection & identity 209:91. Added round 4 (2026-09-13, FU-5): Canvas / CommentPin 392:363 (SET, axis kind = Open/Resolved/Draft) and Canvas / CommentThreadPopover 394:2 (the CommentThread read face only — CommentComposer is not separately mirrored), both in Section / Preview & modes 209:97, which grew 509→849px as a result (pushed Section / Overlays & menus and Section / Command surfaces down 340px on this page). |
| App Surfaces | 208:24 | 44 components: dashboard/* (8), settings/* + ControlHub (20), 9 dialogs, library-panel/* + import (6). Anchors: TargetCard 213:5407 (SET), ControlHub 213:7165, ConfirmDeleteDialog 234:6445 (SET), Import / ImportWizard 283:6803 (SET, axis step = source/review/members/run — 245:538 is now its step=source variant, combined in place, not recreated), Library / ComponentBrowser 276:506. |
Known incomplete, by name, so a follow-up can pick them up:
DONE 2026-08-29 — now a COMPONENT_SETImport / ImportWizardmirrors the Source step only283:6803with all four steps.DONE —ComponentBrowser’s panel shell is not drawnLibrary / ComponentBrowser276:506.FilterBarInsertDialogHostdeliberately not drawn: it is a pure conditional wrapper (if (!pending) return nullaroundFilterBarInsertDialog) with no markup of its own, so it has no surface distinct fromDialog / FilterBarInsertDialog244:506. Do not “fix” this.DataBindingProperties213:6008 now has 4 of its 10 sections populated (List chrome added 2026-09-21,S30, collapsed-only like 5 of its siblings) and its 7 sub-editors exist as their own components (see the page table above).QuickStylesProperties213:5616 is still section structure plus representative rows only — the remaining deferral.PropertyEditor / ExpandToggle (DUPLICATE — use 213:5414)213:5595 is an unreferenced duplicate at the wrong size, left in place rather than deleted. Safe to delete deliberately.
Tracks D and E did not instance the shared masters (FieldShell, CollapsibleSection Header,
Button, Badge, Input, Chip, MenuRow, and many icon/*), hand-building lookalikes instead
to keep pace. Visually consistent, not DRY. The cleanup is a mechanical instance-swap pass, not a
rebuild — do it before anyone treats these pages as a component source.
Bookbuilder tokens (added 2026-08-29, RELOCATED same day)
Section titled “Bookbuilder tokens (added 2026-08-29, RELOCATED same day)”Bookbuilder’s palette was briefly mirrored into this file as a “Bookbuilder
Colors” collection — the wrong home. It now lives in bookbuilder’s own Figma
file (bookbuilder — Design System, fileKey BSVfIwIf6MO4Sh53ZesKtJ, Figma
project “bookbuilder”), integrated into that file’s Primitives/Color
collections with Light+Dark modes and a STATUS swatch section; see
~/Dev/bookbuilder/design/FIGMA-SYNC.md. Pending cleanup in THIS file:
delete collection VariableCollectionId:203:2 and Foundations board 203:17
(nothing in MATRIZ references either — verified by a full bound-variable scan
before the move).
Round 2 (2026-08-30) — what this sync covered, and what it did not
Section titled “Round 2 (2026-08-30) — what this sync covered, and what it did not”| Code change | Mirror | Status |
|---|---|---|
| QuickToolbar rebuilt as an identity bar | Panel / QuickToolbar 28:371, Canvas / IdentityBadge 302:285, Canvas / QuickToolbar Overflow 303:277, Canvas / SelectionIdentityChip 213:29 |
done |
| Token popover gained a Scope tab | Panel / TokenDetailPopover 313:1032 (new) |
done |
| Three new inventory sections | SelectionSpacingSection 213:7304, SelectionTypographySection 213:7330, SelectionRadiusSection 213:7352, shared shell InventorySection 213:6559 |
already mirrored in round 3 — verified against code, no change needed |
| Symbol surfaces; Detach→Unlink | SymbolInstanceBar 309:6686 (SET), SymbolSyncDialog 213:8334 |
done — the dialog already said “Unlink” and carried the review shape; the instance bar gained its role=Copy state ([Master] [Unlink], sync warning, “What syncs?”) |
| Inline rename on the matrix name cell | Panel / TokenMatrix 52:474 |
done — row-background’s name cell now renders the ring-bordered rename input, matching how row-primary already showed a value cell mid-edit |
| Library panel: 9 dead variant switchers + 3 variants removed | LibraryVariantSection 234:6245 |
done — the mirror said “DROPDOWN VARIANT”, and dropdown is one of the switchers that was deleted, so it overstated what exists. Rewritten to the shipped multi-axis shape (Tone + Size, pinning the reported Destructive+Small bug) |
Vocabulary split, deliberate — do not “fix” it. PropertyEditor / UnlinkDialog 213:7595 still
reads “Detach from shared style?” / “Detach”. That matches the code: the rename to Unlink
applies only to SYMBOL surfaces (SymbolInstanceBar.tsx explains why — three different things
were all called detach, and two can appear in the same panel). The shared-style dialog keeps
“Detach” in shared/UnlinkDialog.tsx despite the file name.
Drift found, logged not fixed (unrelated to this batch): accent/variant-chip-bg 3:15
carries WEB syntax bg-violet-500/15, and its LIGHT value is rgba(139,92,246,0.15) — but its
DARK value is rgba(139,92,246,1.00), i.e. the alpha was lost on the dark side. Anything binding
it in dark renders an opaque violet block instead of a 15% wash. Compare accent/data-chip-bg
165:2847, which is 0.15 in both modes. Owner’s call whether to correct the dark value.
Also still true: the round-3 note that tracks D and E hand-built lookalikes instead of
instancing shared masters. Round 2 pushed against that where it touched: Panel / QuickToolbar
now INSTANCES Canvas / SelectionIdentityChip rather than redrawing it, and
SymbolInstanceBar’s ◆/↻/✎/⛓ text glyphs were replaced with real icon/* instances
(Component 9:35, RefreshCw 9:98, PenLine 9:94, Unlink 9:126) per sync-contract rule 4.
Known gaps / blockers (updated 2026-09-25)
Section titled “Known gaps / blockers (updated 2026-09-25)”-
PENDING SYNC — Surface ladder (
D:surface-ladder, 2026-09-25). Code changed; Figma NOT touched (the rule comes FROM Figma 61:650 / RuleChip 114:4246; this lists what the rest of the file must catch up to). Contract:plans/EDITOR-UI-SPEC.md§14.2 + §14.11; screenshotsplans/assets/ui-grammar/surfaces-*.png.- New token
--chip(frontend/src/index.css): dark =var(--muted)/var(--muted-a)(white 15%, what 114:4246 already binds), light =0 0% 92%#ebebeb(NOT--muted96.1%, which does not separate from the 98% panel). Add an Editor Colors variable (suggestsurface/chip, WEBhsl(var(--chip))) and rebind 114:4246’s fill from--mutedto it, so the light mode resolves. Fields inside a chip stay on--card(both modes). - Chips in Figma that still draw a border instead of the fill — re-skin to the ladder (fill
surface/chip, radius 4, padding 5, no stroke, rows 3px apart, fields 22px--cardr3 no stroke): the Track ARuleChipcomponent (6px + 1px border, see the Track A note below), the Layers-tab layer cards, and the micro-panel frames for shadow / filter / backdrop-filter / transition / transform / grid-track / fill-layer rows (StackEditor, werebg-card+border-input), conditional-visibility rules, property-binding cards and table columns (ListEditorCard, werebg-background/50+ border), list-query filter conditions, node-binding index rows, sort rows, visitor sort options, form derive rules, custom-attribute rows and behavior rows. AddRowdash is--outline(was--border), matching 114:4246’s “Add property”.- RuleChip header label is
foregroundink (wasmuted-foreground), matching 114:4246.
- New token
-
PENDING SYNC — UI grammar (
D:ui-grammar, Track A, 2026-09-25). Code changed; Figma NOT touched on purpose (the owner is editing the file; the Figma pass is Track D). To mirror:- New token
--mod(frontend/src/index.css:root+.dark, Tailwindmod):24.6 95% 53.1%= orange-500#f97316in BOTH themes. Add an Editor Colors variable (suggeststate/modified, WEB syntaxhsl(var(--mod))) and bind every modified/override dot to it. Check whethersemantic/override-badge-bg301:1270 should becomestate/modified@10%. - OverrideDot is now 6px
bg-modeverywhere (wasbg-primary, i.e. black/white; blue on the Desktop/Mobile switch; 4px/8px orange on the cascade rail and field reset dot) — update the dots on the StateTabBar / BreakpointBar / section-header frames. - New primitives (
components/property-editor/shared/):RuleChip(6px radius, 1px border, no shadow, 20px header: chevron · 10px uppercase label · right slot · ×),AddRow(dashed 24px “+ Add …” row; parameter variant with 20px inputs inside),PresetPill(24px, rounded-full, 10px medium; active =bg-accent+ insetring-primary/40), andValueUnitInput’s inside-field label (10pxforeground-tertiary, left slot). Add them as components on the Components page. - Frames that changed:
PropertyEditor / LayoutGrid Rules (rule cards, dashed add row, pills above it), the Layers tab (layer cards, dashed add rows, pill quick layers), Quick › Radius / Transition “None” active ring, Data › Data Source selects 32 → 28px. Screenshots and the full list:plans/EDITOR-UI-SPEC.md§14.5,plans/assets/ui-grammar/.
- New token
-
PENDING SYNC — Grid Rules rule chips (
D:ui-grammarTrack C +D:grid-rule-breakpoints, 2026-09-25). Code changed; Figma NOT touched (Track D editsSection / GridRules61:650 in place). Code isGridRulesSection.tsx+RuleChip; screenshotsplans/assets/ui-grammar/grid-rules-{before,after}-{dark,light}.png,grid-rules-collapsed-dark.png. What 61:650 lacks, top to bottom inside each chip:- Header: the collapse chevron sits LEFT of the label (Track A’s RuleChip), not the
^beside ×. A match strip sits between label and ×: one 4px dot per child (max 12, then+N),foregroundwhen the rule hits that child,muted-foreground/30when not. Collapsed, the header readsLABEL · W 50% · H auto(summary in 10pxforeground-tertiary, normal case). - Active at row (new): 10px label + a segmented control, 6 options
Base SM MD LG XL XXL(20px buttons in a 24pxbg-muted/40track); an OFF bucket is struck through in tertiary ink. - W / H and Col / Row pairs as in 61:650 (Col/Row now on every chip, unit
span). - Tie note (new, only when it applies): 10px tertiary text, “W on child 1: First child wins.”
- Add property is the Layers tab’s picker: a dashed row with
property/valueinputs and a trailing + (61:650 shows a plain “+ Add property” button); added props list above it asname value ×rows. - Below the chips: presets First child · Last child · Odd · Even (PresetPill) and the adder “Every [3] rd child, from [3] +” (was “Every [3] th, offset [0] +”).
- Header: the collapse chevron sits LEFT of the label (Track A’s RuleChip), not the
-
PENDING SYNC — state selector (
D:state-selector, Track B, 2026-09-25). Code built FROMstate-switcher-wrapper154:4973; Figma NOT touched. Where the code diverges from 154:4973 (update the node in place, or tell code to change):- “+” beside the control — the ancestor-layer menu (
D:ancestor-state-layer) must stay reachable; 20×20Plus, right of “Default ⌄”. 154:4973 has no “+”. - “+N” overflow chip after the dots (10px,
text-modwhen a hidden state has styles; filledbg-backgroundwhen the current state is behind it) — not in 154:4973. - Current-with-styles ring (
ring-1 ring-modaround the 6px current dot) — agreed in the plan, not drawn. - Dropdown (grouped Built-in / Custom / Ancestor / Motion / Data, check on current, inline
OverrideDotper row) and dot tooltip — no Figma frames; add them beside 154:4973. - Divider 20px tall, ‹ › have no resting fill (hover
bg-accent/60; the drawn prev button shows the hover fill); chevron-down 10px (drawn 8px). - Compact variant: same bar at 24px, short labels (“Def”), no “+” — no frame.
- Placement: its own row under the breakpoint row (the
PropertyEditorframes still show the old pill grid next to the breakpoint switch). Screenshots:plans/assets/ui-grammar/state-*.png.
- “+” beside the control — the ancestor-layer menu (
-
Spec-module check, 2026-09-25 (
D:editor-ui-spec, slice 4): no sync needed. Layout (Flex Layout, Flex Child/Grid Item, Padding, Margin, Radius), Position, fx › Cursor, Text › Variable Font, Attributes, Link and Video now render from*.panel.jsonspecs. They are pixel-identical to the hand-written sections (239 of 241/ui-labcaptures; the other 2 differ only by atitleattribute), and no tokens, icons or chrome layout changed. Two changes appear only on interaction: the existing orange section-override dot now also shows on Position, Stacking, Overflow, Transform and Variable Font for a linked node with overrides, and the Link type select keeps a freshly picked kind. Note the dot on thosePropertyEditor / *frames at the next pass (plans/EDITOR-UI-SPEC.md§12). -
FilterBarSection,FilterControlSection,SliderSectionandCarouselSection(native filter family + carousel/slider) have no Figma mirror — noPropertyEditor / *component exists for any of the four underProperty Modules - Page Root209:5165. Surfaced while checking S36’s Data-tab move (D:controls-on-data-tab, 2026-09-21); pre-existing, not introduced by that change. A follow-up mirroring these four alongside the already-mirroredCollectionControlSection213:6072would close it.D:compare-slider(2026-09-23): the newCompareSection(same file, one “Initial split” field) joins this gap — no mirror, nothing to edit in place. Its icon and the Insert menu’s “Before/after” row useSplitSquareHorizontal, which already exists asicon/SplitSquareHorizontal206:11, so no new icon component is needed. S31 check, same day (D:carousel-panel-parity):CarouselSectiongained a Type (slide/fade) toggle, a Speed (ms) field, and a conditional read-only “Imported: ‹residue›” line + a static edit-mode note. Re-confirmed LIVE viaget_metadataonProperty Modules - Page Root209:5165: still exactly 19PropertyEditor / *symbols across the 6 groups, none named forCarouselSection/SliderSection/FilterBarSection/FilterControlSection— the gap is unchanged, so there was nothing to edit in place (the golden rule is edit-in-place, never recreate; building these four from scratch is the follow-up already scoped above, out of this item’s reach). The follow-up that mirrorsCarouselSectionshould draw from its CURRENT code (frontend/src/components/property-editor/modules/ListControlSettings.tsx), which already includes the S31 fields — there is no separate “pre-S31” mirror anywhere to reconcile against. Widened by the S29 check below: the newFilterControlTargetDialog(frontend/src/components/filters/FilterControlTargetDialog.tsx,D:filter-panel-uxitem 8) is a real dialog with its own markup — unlikeFilterBarInsertDialogHost(see the entry below, deliberately not drawn), it is a peer ofDialog / FilterBarInsertDialog244:506and belongs in the same follow-up rather than getting a one-off component of its own. -
S29 check, 2026-09-21 (
D:filter-panel-ux).CollectionControlSection.tsxgained a Field picker (was free text), a context chip / “No value needed” / suggested-values shape for Value, a per-mode Mode sentence, and a Clear-conversion switch. CheckedPropertyEditor / CollectionControlSection213:6072(metadata + screenshot) before editing: no edit was needed. That mirror has only ever been a 4-row schematic (REPEATER/FIELD/OPERATOR/VALUE, each drawn as a plain label + generic value box, with NO widget-type distinction —OPERATOR, a real<Select>in code since before this item, already rendered as plain text “Equals” with no chevron) — so a<Select>-backed FIELD row reads exactly as it already did, andVALUE: "Prints"remains a correct instance of the literal-value branch (unchanged by this item; the new chip/“No value needed” shapes are alternate branches for a DIFFERENT control state). The schematic was already missing the Mode row, the field/target callout paragraphs, the list-chrome block and the liveness caveat before this item — none of those are newly wrong, but a future pass rebuilding this mirror to real fidelity should add: a MODE row, a CLEAR row (the new Field-not-on-collection / “No value needed” text if going for full fidelity), matching the code inCollectionControlSection.tsx. -
Library not publishedDONE 2026-08-22 — moved to Simao › Design System and published (see header). Re-publish manually after each sync. A re-publish is pending as of 2026-09-13 and now covers even more (round 4 added 5 icons,Canvas / CommentPin,Canvas / CommentThreadPopover,Panel / PreviewTopBar,Panel / Todo,TodoRow, on top of round 2’ssemantic/override-badge-bgand its 3 new/5 edited components): the Bookbuilder Colors collection, Editor Colors 52 → 81 variables, 15 new icons total, the metrics code-syntax fixes, and 142+ new components across the micro-panel pages. -
UNRESOLVED (2026-08-29): Editor Colors was hand-reworked in FigmaRESOLVED — adopted. The owner’s call was to take the alpha re-base into code rather than revert Figma. Done in round 3 (D:alpha-token-rebase): the dark neutrals moved to a paired--<token>-aalpha var multiplied through the Tailwind colour, the deleted variables the app still uses were re-created,core/secondary-foregroundwas renamedcore/foreground-tertiaryto stop it colliding with shadcn’s token, and every variable now carries a WEB code syntax.Sidebar Panels73:2 is recorded in the page map above. -
Code Connect is plan-blocked, not a to-do. Figma rejects Code Connect writes on Pro: “You need a Dev or Full seat on an Organization or Enterprise plan.” Confirmed via the MCP
send_code_connect_mappingscall 2026-08-22. Until/unless the team upgrades, the component tables in this doc ARE the code↔design mapping (each Figma component’sdescriptionalso names its source file). -
One canonical screen state.CLOSED 2026-08-29 — the eleven sidebar-mode panels live onSidebar Panels73:2 (addedPanel / Todo395:7853, 2026-09-13), the popovers/menus onPanels27:371, and 142+ further surfaces on the four micro-panel pages. Still unmirrored: the UI Lab views, and the incomplete items listed under “Micro-panel pages” above. -
CommentComposer(the placed-pin, not-yet-saved face ofCommentThreadPopover.tsx) is not mirrored — onlyCommentThread(the read/edit face) becameCanvas / CommentThreadPopover394:2. A follow-up can add aface=Composervariant (textarea + Cancel/Comment pair) combined into the same component. -
Panel / IconTray’s newmode-todorow (394:7627) is a hand-built lookalike, matching the row style its 11 siblings already use — none of them instanceSidebar / Mode Button12:18 (the interactive state=active/idle/hover set on the Chrome Parts page). This is the same tracks-D/E gap noted below, not a new one; fixing it is the mechanical instance-swap pass already on file, not a per-row fix. -
VideoSection(Data tab,element_type: 'video') and the Add Element palette’s newVideoitem (lucideVideo) have no Figma mirror (2026-09-23). Same pre-existing gap as the other per-element Data-tab sections (QrSection,CountdownSection,LanguageSwitcherSection,EmbedSection,CustomCodeSection) and the palette itself, none of which is mirrored — nor are their icons (MonitorPlay,QrCode,TimerReset, …).icon/Videowas deliberately NOT added alone: the icon set carries only glyphs a mirrored surface renders. Mirror the palette and these sections together (existingSwitch/Select / Trigger/ CollapsibleSection masters suffice). -
4 lucide icons are still missing (
Heading,Repeat,ArrowUpCircle,Rows3) — surfaced while mirroring the data-binding sub-editors, which substitutedicon/Plusor omitted the glyph. Add them per sync-contract rule 4, then fixGroupByEditor255:6666,RepeaterStateTabs255:6560 andDataSourceSelector255:6596. Note the recipe’supload_assetsstep is currently blocked by this environment’s egress proxy (mcp.figma.comreturns 403 by org policy);figma.createNodeFromSvg()with the same extracted__iconNodedata is a working substitute that keeps the geometry exact. -
Switchmaster11:31is now out of date. The code’s thumb was a flatbg-white, which the master mirrors faithfully. That white was invisible in two of four states (light unchecked 1.09:1, dark checked 1.04:1) and the code now usesdata-[state=checked]:bg-primary-foreground/data-[state=unchecked]:bg-foreground. The master needs a matching two-state thumb. -
Binding an alpha-carrying variable can render opaque black. Figma does not apply a COLOR variable’s embedded alpha to a paint automatically, so
setBoundVariableForPaint({color:{r:0,g:0,b:0}}, 'color', v)against one of the ~31 alpha variables renders solid black. Set the paint’scolorto the variable’s resolved RGB and itsopacityto the resolved alpha, in addition to binding. Audited after round 3: only 2 of 1,180 alpha-bound paints across the four micro-panel pages had actually hit this, both since fixed — so this is a trap to avoid, not a backlog. -
Two shared-master requests, both decided:
Button10:68has noINSTANCE_SWAPproperty for its leading/trailing icon, so icon-bearing instances keep a baked-in default — worth adding, but it is a 96-variant edit to the most-instanced master in the file, so it should be done deliberately rather than mid-track.Select / Trigger23:653was asked for a width-hug variant and that is declined: the code isw-full(ui/select.tsx:19), so a hug variant would show something the app never renders. -
Code hardcodes three colours the token system has no home forRESOLVED — the code now uses--accent-insert-flow,--accent-insert-crossand--accent-state-lens-ghost, matching the Figma variable paths 1:1.frontend/public/preview.htmldeliberately keeps its#3b82f6/#8b5cf6literals (they also drive the selection outline and drop-indicator gradients, and it has no CSS vars); both files carry a comment saying the two must change in lockstep, and the byte-level parity gate covers it. -
Some code surfaces bypass the theme tokens —
ImportMaterializationPanel.tsxis now fully retokenized.PageFormatDialogwas listed here in error: it was already tokenized, and this entry was written from a mirroring report rather than the file.BookletPreviewDialog’sbg-[#52565e]stays on purpose — a theme-invariant “light-table” backdrop behind the page preview, which no current token expresses. Remaining raw-hue offenders, worst first:ComponentInstanceHeader.tsx(11 rawviolet-*, which the chrome-accent contract already names as the variant-chip semantic),cms/fields/CellRenderer.tsx(indigo + violet + gray),editors/PageEditor.tsx,registry/controls/RotationControl.tsx,cms/fields/SlugField.tsx. -
Hover states exist only where modeled as explicit variants (Figma has no CSS hover).
-
Accent presets (themeStore’s 8 accent hues) are not modeled as variable modes (pro plan caps a collection at 4 modes). Neutral is the canonical accent.
-
Icon stroke weight at 14/12/10px: instances keep the 16px-calibrated 1.333 stroke when resized (real render would be 1.167/1/0.833). Visually negligible; noted for pixel-perfection work.
-
Clerk UserButton is a placeholder circle; TipTap/canvas internals are sketches inside the
iframe (preview.html)frame.