feat: Design tab, live style editing, route-aware artboards, canvas onboarding
Design tab (4-tab inspector: Design / Props / Diff / Graph) - Click any component in a live artboard to inspect computed CSS - Typography, Layout, Visual sections auto-populated from getComputedStyle - Every property is inline-editable; changes apply live via PATCH_ELEMENT_STYLE - Zero source-code modifications — purely in-browser style overrides Protocol additions (packages/renderer) - REQUEST_ELEMENT_STYLES / ELEMENT_STYLES round-trip for CSS inspection - PATCH_ELEMENT_STYLE for live style patching Live SDK (packages/live-sdk) - respondWithStyles(): reads 30 curated computed CSS properties - patchElementStyle(): applies inline style override to fiber's DOM element Canvas store - selectedComponentStyles: current element's CSS map - styleEditEvent mailbox: Design tab → LiveArtboard style dispatch (Zustand v5 compatible) Route-aware artboards - Each artboard now has an optional route (e.g. /dashboard) - buildSrc(base, route) helper in Artboard.tsx - Route field editable in Inspector Props tab, persisted to metadata_jsonb On-canvas onboarding - Empty canvas now shows 3-step guide: press A → CLI command → paste URL - CLI command shown inline in a highlighted code block Changelog and Handoff updated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
8514ffdc1a
commit
edada3091e
@@ -30,6 +30,18 @@ interface CanvasStore {
|
||||
selectedComponentId: string | null;
|
||||
selectedComponentData: FiberNode | null;
|
||||
selectComponent: (id: string | null, data: FiberNode | null) => void;
|
||||
|
||||
// ── Component computed styles (populated by ELEMENT_STYLES response) ────────
|
||||
/** Computed CSS property map for the currently-selected component DOM element. */
|
||||
selectedComponentStyles: Record<string, string> | null;
|
||||
setComponentStyles: (styles: Record<string, string> | null) => void;
|
||||
|
||||
// ── Style edit mailbox ──────────────────────────────────────────────────────
|
||||
// The Design tab drops a patch here; the owning LiveArtboard picks it up,
|
||||
// forwards it to the iframe, then clears it.
|
||||
styleEditEvent: { artboardId: string; nodeId: string; property: string; value: string } | null;
|
||||
patchStyleEdit: (artboardId: string, nodeId: string, property: string, value: string) => void;
|
||||
clearStyleEdit: () => void;
|
||||
}
|
||||
|
||||
export const useCanvas = create<CanvasStore>((set) => ({
|
||||
@@ -38,7 +50,7 @@ export const useCanvas = create<CanvasStore>((set) => ({
|
||||
|
||||
selectedArtboardId: null,
|
||||
selectArtboard: (id) =>
|
||||
set({ selectedArtboardId: id, selectedComponentId: null, selectedComponentData: null }),
|
||||
set({ selectedArtboardId: id, selectedComponentId: null, selectedComponentData: null, selectedComponentStyles: null }),
|
||||
|
||||
workspaceId: null,
|
||||
projectId: null,
|
||||
@@ -58,5 +70,14 @@ export const useCanvas = create<CanvasStore>((set) => ({
|
||||
|
||||
selectedComponentId: null,
|
||||
selectedComponentData: null,
|
||||
selectComponent: (id, data) => set({ selectedComponentId: id, selectedComponentData: data }),
|
||||
selectComponent: (id, data) =>
|
||||
set({ selectedComponentId: id, selectedComponentData: data, selectedComponentStyles: null }),
|
||||
|
||||
selectedComponentStyles: null,
|
||||
setComponentStyles: (styles) => set({ selectedComponentStyles: styles }),
|
||||
|
||||
styleEditEvent: null,
|
||||
patchStyleEdit: (artboardId, nodeId, property, value) =>
|
||||
set({ styleEditEvent: { artboardId, nodeId, property, value } }),
|
||||
clearStyleEdit: () => set({ styleEditEvent: null }),
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user