Layout Guides Plugin
Overview
@designful/layout-guides-plugin is a standalone runtime plugin for frame layout guides.
It is not a ui-plugin-host modal plugin. You enable it through editor.pluginManager, then use editor.layoutGuides for API access.
What It Adds
- multiple guides per frame
square,columns/stretch,columns/fixed,rows/stretch,rows/fixed- page-scoped presets
- global show/hide for all guides on the current page
- copy/paste between frames
- history-safe replay for frame metadata and plugin document state
Why It Stays Decoupled
@designful/editor-coredoes not statically import the package- runtime dependencies stay limited to editor contracts,
plugin-base,types, andkonva - API actions and context-menu actions share the same validation and command path
- package-boundary tests prevent imports from unrelated Designful modules
Persistence
Frame guide collections are stored on each frame:
frame.metadata.plugins.layoutGuides
Page-scoped plugin state is stored on current page metadata:
page.metadata.layoutGuidesPlugin
That page state contains:
globalVisiblepresets
Docs Routes
- API reference: /docs/plugins/layout-guides/api
- Live demo: /docs/plugins/layout-guides/demo
- Frame help: /help/frames/layout-guides
Why Aren't My Layout Guides Showing?
The plugin has one shared visibility rule source, so the runtime behavior and docs stay aligned. Guides stay hidden when:
- all guides on the frame are toggled off
- global guide visibility is off for the page
- the current target is not a frame
- the frame has any non-zero rotation
The package exports resolveLayoutGuideVisibilityReason(...), and the plugin emits the same result on layoutGuides:removed as a reason payload.
Demo Checklist
- Open the live demo and select the root frame.
- Add a guide through the API panel, then add another guide through the context-menu path.
- Save a preset, switch to the nested frame, and apply that preset there.
- Toggle global visibility, then undo and redo to verify state replay.
Selection Behavior In The Live Demo
- Clicking the nested frame's blank area selects the nested frame, even when the click does not land on the inner rect.
- Keeping the root frame selected does not disable next-level hover feedback; direct children still render hover outlines.
- Hovering the nested frame blank area still resolves to the nested frame hover outline, even when Konva does not return a child hit target.
- The live demo listens to editor
selection:changedandscope:changedevents, so the sidebar and runtime snapshot always reflect the editor's real selection state. - Direct nested-frame drag uses the same alignment snap path as the left-side rect in the demo.
- Selected-frame threshold drags keep alignment guides visible during nested-frame snapping instead of clearing them from the stage sync path.
- Descendant-hit fallback frame drags still suppress snapping until the frame itself owns the drag lifecycle, which prevents descendant streams from producing stale snap guides.