The designer provides a comprehensive set of React components for building design applications. These components handle everything from the core designer interface to individual property editors and UI primitives.
Designer
The main container component that provides context and state management for the entire design interface.
The Designer component supports both controlled and uncontrolled patterns, similar to React form components.
Uncontrolled
Use defaultLayers
when you want the Designer to manage its own internal state. This is perfect for demos, static examples, and applications where you don't need external state management.
import { Designer } from "@shadcn/designer"
function UncontrolledDesigner() {
return (
<Designer
defaultLayers={[
{
id: "text-1",
type: "text",
name: "Hello",
value: "Hello World",
cssVars: {
"--width": "200px",
"--height": "100px",
}
}
]}
frameSize={{ width: 1024, height: 1024 }}
onMount={() => {
console.log("Designer mounted")
}}
>
{/* Designer content */}
</Designer>
)
}
Controlled
Use layers
+ onLayersChange
when you need full control over layer state.
import { Designer } from "@shadcn/designer"
import { useState } from "react"
function ControlledDesigner() {
const [layers, setLayers] = useState([
{
id: "text-1",
type: "text",
name: "Hello",
value: "Hello World",
cssVars: {
"--width": "200px",
"--height": "100px",
}
}
])
const handleLayersChange = (newLayers) => {
setLayers(newLayers)
// Optionally save to external storage
saveToDatabase(newLayers)
}
return (
<Designer
layers={layers}
onLayersChange={handleLayersChange}
>
{/* Designer content */}
</Designer>
)
}
Props
Prop | Type | Required | Description |
---|---|---|---|
defaultLayers | Layer[] | No* | Initial layers for uncontrolled mode |
layers | Layer[] | No* | Current layers for controlled mode |
onLayersChange | (layers: Layer[]) => void | No* | Callback for controlled mode |
layerTypes | LayerType[] | No | Available layer types (defaults to built-in types) |
frameSize | { width: number, height: number } | No | Canvas frame size (default: 1024x1024) |
keybindings | Record<string, Keybinding> | No | Keyboard shortcuts configuration |
mode | "single" | "multiple" | No | Designer mode (default: "multiple") |
onMount | () => void | No | Callback when designer is mounted |
debug | boolean | No | Enable debug mode |
className | string | No | Additional CSS classes |
Important notes:
- You can use one of
defaultLayers
(uncontrolled) orlayers
+onLayersChange
(controlled), but not both. - The
onLayersChange
callback is only called for user actions, not prop changes - This prevents infinite loops when implementing controlled components
- Each pattern provides complete isolation - controlled components manage external state, uncontrolled components manage internal state
mode
The Designer
component has a mode
prop that can be set to single
or multiple
. The default is multiple
.
When in single
mode, the designer is optimized for single layer editing, ideal for cases where you're only working with one layer for example an image editor.
In single
mode, the designer will automatically select the first layer when the designer is mounted.
DesignerHeader
Header area for toolbar controls and actions.
import { Designer, DesignerHeader } from "@shadcn/designer"
function CustomDesigner() {
return (
<Designer>
<DesignerHeader>
{/* Header controls */}
</DesignerHeader>
</Designer>
)
}
DesignerContent
Main content area that contains the canvas and panels.
import { Designer, DesignerHeader, DesignerContent } from "@shadcn/designer"
function CustomDesigner() {
return (
<Designer>
<DesignerHeader />
<DesignerContent>
{/* Panels and canvas */}
</DesignerContent>
</Designer>
)
}
DesignerCanvas
Canvas area where the design frame is rendered.
import { Designer, DesignerContent, DesignerHeader, DesignerCanvas, DesignerFrame } from "@shadcn/designer"
function CustomDesigner() {
return (
<Designer>
<DesignerHeader />
<DesignerContent>
<DesignerCanvas>
<DesignerFrame />
</DesignerCanvas>
</DesignerContent>
</Designer>
)
}
DesignerFrame
The interactive frame that contains and renders all layers.
import { Designer, DesignerContent, DesignerHeader, DesignerCanvas, DesignerFrame } from "@shadcn/designer"
function CustomDesigner() {
return (
<Designer>
<DesignerHeader />
<DesignerContent>
<DesignerCanvas>
<DesignerFrame />
</DesignerCanvas>
</DesignerContent>
</Designer>
)
}
DesignerStaticFrame
A static version of the frame for non-interactive rendering.
import { DesignerStaticFrame } from "@shadcn/designer"
function PreviewFrame() {
return (
<DesignerStaticFrame
layers={layers}
width={1024}
height={1024}
/>
)
}
You can use this component to generate a static image of the design. See the Convert to Image guide for more information.
DesignerPanel
Side panel container for organizing controls and tools. You can use one or both of these panels to render a designer with left and right panels.
import { Designer, DesignerContent, DesignerHeader, DesignerCanvas, DesignerFrame, DesignerPanel, DesignerPane } from "@shadcn/designer"
function CustomDesigner() {
return (
<Designer>
<DesignerHeader />
<DesignerContent>
<DesignerPanel>
{/* Left Panel */}
</DesignerPanel>
<DesignerCanvas />
<DesignerPanel>
{/* Right Panel */}
</DesignerPanel>
</DesignerContent>
</Designer>
)
}
DesignerPane
Individual pane within a panel with a title and content. Use a pane to group related controls and tools. Panes can be configured to show only when specific layer types are selected.
import { DesignerPane, DesignerPaneTitle, DesignerPaneContent, ActionImage } from "@shadcn/designer"
function PaneImageActions() {
return (
<DesignerPane showForLayerTypes={["image"]}>
<DesignerPaneTitle>Image</DesignerPaneTitle>
<DesignerPaneContent>
<ActionImage />
</DesignerPaneContent>
</DesignerPane>
)
}
Prop | Type | Required | Description |
---|---|---|---|
showForLayerTypes | string[] | "all" | No | Controls when the pane is visible based on selected layer types. Defaults to "all" . |
import { DesignerPane, DesignerPaneTitle, DesignerPaneContent } from "@shadcn/designer"
function ConditionalPanes() {
return (
<>
{/* Always visible (default) */}
<DesignerPane>
<DesignerPaneTitle>General</DesignerPaneTitle>
<DesignerPaneContent>
<ActionPosition />
<ActionSize />
</DesignerPaneContent>
</DesignerPane>
{/* Only visible when text layers are selected */}
<DesignerPane showForLayerTypes={["text"]}>
<DesignerPaneTitle>Text</DesignerPaneTitle>
<DesignerPaneContent>
<ActionTextValue />
<ActionFontSize />
<ActionColor />
</DesignerPaneContent>
</DesignerPane>
{/* Only visible when image layers are selected */}
<DesignerPane showForLayerTypes={["image"]}>
<DesignerPaneTitle>Image</DesignerPaneTitle>
<DesignerPaneContent>
<ActionImage />
<ActionImageFit />
</DesignerPaneContent>
</DesignerPane>
{/* Visible when text OR icon layers are selected */}
<DesignerPane showForLayerTypes={["text", "icon"]}>
<DesignerPaneTitle>Typography</DesignerPaneTitle>
<DesignerPaneContent>
<ActionFont />
<ActionTextAlign />
</DesignerPaneContent>
</DesignerPane>
</>
)
}
Available Layer Types:
"frame"
- Frame/container layers"text"
- Text layers"image"
- Image layers- Custom layer types defined in your
LayerType[]
configuration
Visibility Rules:
showForLayerTypes="all"
(default): Pane is always visibleshowForLayerTypes={["text"]}
: Pane is visible only when text layers are selectedshowForLayerTypes={["text", "image"]}
: Pane is visible when text OR image layers are selected- The pane is visible only when all selected layers match the specified types
DesignerToolbar
Toolbar container for grouping actions and controls. This component is displayed as a floating toolbar at the bottom of the designer.
import { DesignerToolbar, DesignerToolbarGroup, DesignerToolbarButton, DesignerToolbarSeparator } from "@shadcn/designer"
import { IconArrowBackUp } from "@tabler/icons-react"
function CustomDesigner() {
return (
<DesignerToolbar>
<DesignerToolbarGroup>
<DesignerToolbarButton tooltip="Example" onClick={() => {}}>
<IconArrowBackUp />
</DesignerToolbarButton>
</DesignerToolbarGroup>
<DesignerToolbarSeparator />
<DesignerToolbarGroup />
<DesignerToolbarGroup />
</DesignerToolbar>
)
}
- Use the
DesignerToolbarButton
component to add buttons to the toolbar. - Use the
DesignerToolbarSeparator
component to add a separator between groups of buttons.