* feat(code): link code to canvas layers and underline design issues
Code in the Code tab and layers on the canvas were unrelated: finding the
element behind a layer, or the layer behind an element, meant reading names.
Generated Design JSX and Tailwind JSX report the layer behind each element
in the order elements open, and edited Design JSX keeps the source line of
every element through the sandbox and renderer, so hovering an element
highlights its layer, Cmd/Ctrl-click brings it into view without changing
the selection the code shows, and errors and warnings from the design check
are underlined on the property that causes them.
* feat(code): explain the Code tab when nothing is selected
With no selection the editor showed a starter frame that read like a real
layer. The tab now says it shows the selected layers' code and offers Write
JSX, which opens the editor focused on the starter template.
* refactor(code): group code-to-layer linking into its own domain
Layer link types, issue mapping, and the hover and reveal behavior move
from the Code panel and a component file into src/app/code/layers, with
useCodeLayers as the panel's entry point, so app code no longer imports
types from components.
* fix(code): underline off-scale gaps after the spacing rule renamed its property
* feat(code): mark the layer of the element around the cursor
Hover highlighting and ⌘-click reveal replaced by one model: the element
around the cursor marks its opening and closing tag names and outlines its
layer on the canvas while the editor has focus. ⌘-click also collided
with CodeMirror's add-a-cursor gesture. Read-only Tailwind JSX now takes a
cursor so it links the same way.
Leaving the editor now ends a live Design JSX edit as one undo step.
Before, canvas edits made after typing never reached the code until the
tab was reopened, and their undo entries landed before the edit's.
* feat(code): sync the Code tab and the canvas both ways by patching
Canvas edits now patch the Design JSX a person wrote instead of waiting
for them to leave the editor: each linked element remembers the layer as
Design JSX last wrote it, and a canvas change rewrites only the attributes,
text and child elements that differ from that base, as CodeMirror changes
that keep the cursor, comments, formatting and history. Attributes written
as expressions are never overwritten; the code marks them when the canvas
now differs. Untouched code is regenerated with a minimal text change.
Code edits update layers in place: the new render is reconciled into the
existing layers (reconcileRenderedLayers), which keep their ids, so links,
selection and canvas edits survive typing. Each edit is one coalesced undo
step, replacing the restore-and-rerender preview and the commit on blur.
* feat(code): patch reordered layers and aliased properties in edited code
Reordering layers on the canvas now moves their elements in code a person
wrote: each child element and the blank lines and comments above it form a
block kept as written, and the children are written again in the new
order, staying linked. Children that cannot move safely, such as a loop
between them, keep their order and are marked.
Properties accepted under several names now come from one alias table in
the Design JSX schema, which the renderer resolves through and the patcher
and issue underlines use, so a canvas change to `w` patches `width` where
the person wrote that, instead of adding a second attribute.
* feat(code): keep the cursor in moved code and patch values written in style
A reorder rewrites the children span in one change, which collapsed a
cursor or out-of-sync marker inside a moved element to the span's edge.
The patch now carries where each block moved and places selections and
markers inside it at their new position.
Properties the renderer also reads from style={{ … }} come from a table in
the Design JSX schema instead of a hand-written list, keeping the rule
that an attribute under any of its names wins. The patcher uses it to
update a value written in style where it is, as a number or a px string
as written; values the renderer cannot read, such as '50%', are marked.
The layer patcher is split by concern: syntax helpers, attribute and
style patches, child patches, out-of-sync state and transaction assembly.
* feat(code): show the code's layer on the canvas as a tinted box
The layer of the element around the cursor used the canvas hover slot, so
moving the pointer over the canvas replaced it and the two read the same.
It now has its own shared editor state, codeFocusNodeId, drawn as the hover
outline over a light tint in every pane: hover stays an outline and the
selection keeps its handles, without borrowing the dashed outlines that
already mean component sets, drag parents and ghosts.
* fix(code): write added and removed layers when a reorder cannot move the code
When children could not be moved, such as two written on one line, the
patch marked the order and returned before adding or removing elements,
so a layer created in the same change never reached the code. It now
marks the order and still writes additions and removals.
* refactor(design-jsx): format the rebased layer description and stroke aliases
* feat(code): mount the layer-linked code editor through useCodeMirror
Master moved the code editor onto the shared useCodeMirror composable.
Its layer links, issue underlines, canvas patches, minimal text updates,
autofocus and read-only cursor now sit on that composable instead of a
hand-mounted view.
4.1 KiB
| title | description |
|---|---|
| Checking Designs | Find accessibility, consistency, and structure issues with the Lint panel and canvas issue markers. |
Checking Designs
OpenPencil checks the current page as you work and points out layers that break common design rules: text that is hard to read, controls that are too small to tap, colors that should use a variable, and spacing off the scale.
Lint Panel
Open the Lint tab in the right panel. Its badge shows how many errors and warnings the page has.
- Page lists every issue on the current page; Selection narrows the list to the selected layers and everything inside them; Document lists every page's issues, tagging the ones on other pages. Clicking one of those switches to its page. Pages of a large
.figfile that have not been opened yet are checked once you open them. - Issues are grouped by rule, most severe first. Errors and warnings start expanded; suggestions start collapsed.
- The severity buttons under the scope switch filter errors, warnings, and suggestions on and off.
- Hover a group title to read what the rule checks and why.
Hover an issue to highlight its layer on the canvas. Click it to select the layer; if it is off screen, the canvas pans to it, and zooms out only when the layer does not fit.
Fixing Issues
Rows that can be fixed in one step show a button on hover:
- A hardcoded color that matches one of the document's color variables binds to it (link button). The row names the variable.
- Subpixel positions and sizes round to whole pixels. Values that auto layout or text resizing sets, and vector artwork and the parts of groups, are left alone.
- Off-scale corner radius and spacing change to the nearest scale value, and text below the minimum size grows to it (wand button). These change the design, so they apply one row at a time.
Binding colors and rounding pixels keep the design as it looks, so their groups also offer Bind all or Fix all. Every fix is a single undo step.
Other issues show the value that needs attention, such as a contrast ratio or a touch target size, so you can fix them in the Design panel.
Canvas Markers
Layers with errors and warnings carry a marker at their top-right corner: red for errors, amber for warnings. Suggestions appear only in the Lint panel.
- Hover a marker to see its issues. Click it to select the layer and open its issues in the Lint panel.
- Markers that would overlap merge into one showing their combined count.
- When a layer is too small to see at the current zoom, its marker moves to the nearest enclosing layer large enough to point at.
- Errors and warnings outside the visible canvas are pinned to its edge, pointing toward them. Hover a pin to see them; click it to bring the nearest of the most severe into view and open it in Lint.
- Hidden layers and layers clipped out of view by a frame keep their issues in the panel but get no marker.
Pages with errors or warnings show their count in the page list, checked in the background while you work. The Layers panel marks the same layers: a layer with errors or warnings shows the most severe as an icon, and a collapsed layer with issues inside it shows a dot.
Turn markers and Layers panel marks on or off with View → Design issues, or with Show issues on canvas in the Lint panel's settings menu.
In the Code Panel
The Code tab underlines errors and warnings on the Design JSX or Tailwind JSX of their layers, on the property that causes the issue when there is one, such as size={10} for small text. Hover the underline to read the issue. The underlines follow your edits while you change the code live.
Rules
The settings menu in the Lint panel switches between rule presets:
- Recommended — balanced defaults for everyday work.
- Strict — every rule as a warning or error.
- Accessibility — contrast, touch target size, and text size only.
Turn off a single rule from its group's menu. Turn on turned-off rules in the settings menu brings them back. Presets and turned-off rules are saved between sessions.
The same rules run from the command line with openpencil lint; see Inspecting Files.