Designer

The core components for building the design canvas and layout structure.

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.

components/uncontrolled-designer.tsx
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.

components/controlled-designer.tsx
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

PropTypeRequiredDescription
defaultLayersLayer[]No*Initial layers for uncontrolled mode
layersLayer[]No*Current layers for controlled mode
onLayersChange(layers: Layer[]) => voidNo*Callback for controlled mode
layerTypesLayerType[]NoAvailable layer types (defaults to built-in types)
frameSize{ width: number, height: number }NoCanvas frame size (default: 1024x1024)
keybindingsRecord<string, Keybinding>NoKeyboard shortcuts configuration
mode"single" | "multiple"NoDesigner mode (default: "multiple")
onMount() => voidNoCallback when designer is mounted
debugbooleanNoEnable debug mode
classNamestringNoAdditional CSS classes

Important notes:

  • You can use one of defaultLayers (uncontrolled) or layers + 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.

components/custom-designer.tsx
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.

components/custom-designer.tsx
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.

components/custom-designer.tsx
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.

components/custom-designer.tsx
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.

components/preview-frame.tsx
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.

components/custom-designer.tsx
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.

components/pane-image-actions.tsx
import { DesignerPane, DesignerPaneTitle, DesignerPaneContent, ActionImage } from "@shadcn/designer"
 
function PaneImageActions() {
  return (
    <DesignerPane showForLayerTypes={["image"]}>
      <DesignerPaneTitle>Image</DesignerPaneTitle>
      <DesignerPaneContent>
        <ActionImage />
      </DesignerPaneContent>
    </DesignerPane>
  )
}
PropTypeRequiredDescription
showForLayerTypesstring[] | "all"NoControls when the pane is visible based on selected layer types. Defaults to "all".
components/conditional-panes.tsx
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 visible
  • showForLayerTypes={["text"]}: Pane is visible only when text layers are selected
  • showForLayerTypes={["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.

components/custom-designer.tsx
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.