The designer hooks you will reach for most often when building custom editor UI.
Most custom designer UI is built from a small set of hooks. The full hooks reference lists everything, but this page covers the hooks that usually matter first when you are wiring up toolbars, panes, custom controls, and document actions.
Reading the document
Use these hooks when your UI needs to reflect the current document or selection.
| Hook | Use it for |
|---|---|
useLayers | Reading the raw layer array. |
useLayersWithStyles | Reading layers with computed style and contentStyle. |
useLayerTree | Rendering a nested layer tree. |
useSelectedLayers | Reading the selected layer objects. |
useSelectedLayerTypes | Showing controls for the selected layer types. |
Most inspector controls start with useSelectedLayers:
import { useSelectedLayers } from "@shadcn/designer"
function SelectedLayersList() {
const selectedLayers = useSelectedLayers()
if (!selectedLayers.length) {
return null
}
// Render a list of the selected layers.
return (
<ul>
{selectedLayers.map((layer) => (
<li key={layer.id}>{layer.name}</li>
))}
</ul>
)
}Updating layer data
Layer data falls into four buckets: common layer properties, layer-specific values, metadata, and CSS variables.
| Hook | Use it for |
|---|---|
useSetLayersValue | Updating the value of one or more layers. |
useSetLayersMeta | Updating the meta of one or more layers. |
useSetLayersProperty | Updating shared layer fields like name, isLocked |
createLayerCssVarAction + useLayerCssVarAction | Building controls for CSS variables like fill, size, position, and typography. |
Use useSetLayersValue for custom layer values:
import { useSelectedLayers, useSetLayersValue } from "@shadcn/designer"
function ShapeTypeAction() {
const selectedLayers = useSelectedLayers()
const setLayersValue = useSetLayersValue()
const shapeLayers = selectedLayers.filter((layer) => layer.type === "shape")
return (
<button
onClick={() => setLayersValue(shapeLayers, { type: "circle" })}
disabled={shapeLayers.length === 0}
>
Circle
</button>
)
}useSetLayersValue and useSetLayersMeta accept a layer ID, an array of layer
IDs, a layer object, or an array of layer objects. If you only have IDs, pass the
layer type as a generic so TypeScript can check the value:
setLayersValue<"shape">(selectedLayerIds, { type: "square" })
setLayersMeta<"shape">(selectedLayerIds, { source: "toolbar" })Use the updater form when the next value depends on the previous value:
setLayersValue<"shape">("shape-1", (prev) => ({
...prev,
type: prev.type === "circle" ? "square" : "circle",
}))Use useSetLayersProperty for common fields that are not specific to one layer
type:
const setLayersProperty = useSetLayersProperty()
setLayersProperty(selectedLayerIds, "isLocked", true)Do not use useSetLayersProperty to update cssVars. Use createLayerCssVarAction and useLayerCssVarAction instead.
For visual properties stored in cssVars, prefer a CSS variable action. It
automatically reads and writes the value across the current selection.
import {
createLayerCssVarAction,
useLayerCssVarAction,
} from "@shadcn/designer"
const fill = createLayerCssVarAction("--background-color", "#000000")
function FillAction() {
const [value, setValue] = useLayerCssVarAction(fill)
return (
<input
type="color"
value={value}
onChange={(event) => setValue(event.target.value)}
/>
)
}All of these setters record undo history by default. Pass { history: false }
when you need an internal update that should not create an undo step:
setLayersValue<"shape">("shape-1", { type: "circle" }, { history: false })Creating and deleting layers
Use these hooks when a control changes the structure of the document.
| Hook | Use it for |
|---|---|
useAddLayers | Creating one or more layers from layer input. |
useDeleteLayers | Deleting layers by ID. |
Use useAddLayers when you are creating new layer objects yourself:
const addLayers = useAddLayers()
addLayers([
{
type: "text",
name: "Text",
value: "Hello world",
cssVars: {
"--translate-x": "120px",
"--translate-y": "120px",
},
},
])Canvas and editor controls
These hooks control the designer shell rather than the document data itself.
| Hook | Use it for |
|---|---|
useDesignerAction | Running canvas-level commands like zoom, undo, redo, redraw, and deselect. |
useDesignerTool / useSetDesignerTool | Reading or switching between the move and hand tools. |
useZoom / useSetZoom | Reading or setting the current zoom. |
useFrameSize / useSetFrameSize | Reading or setting the frame size. |
useUnitSystem / useSetUnitSystem | Reading or setting the active unit system. |
useDPI / useSetDPI | Reading or setting DPI for unit conversion. |
useDesignerAction is useful for toolbar buttons that map directly to designer
commands:
const designerAction = useDesignerAction()
designerAction("ZOOM_IN")
designerAction("ZOOM_FIT")
designerAction("UNSELECT_ALL")For controls that need to show the current value, pair the read and write hooks:
const zoom = useZoom()
const setZoom = useSetZoom()
setZoom(Math.min(zoom + 0.1, 3))History
Use the dedicated history hooks when you are building undo and redo UI.
| Hook | Use it for |
|---|---|
useUndo | Undoing the last recorded layer change. |
useRedo | Redoing the next recorded layer change. |
useCanUndo | Disabling undo UI when there is nothing to undo. |
useCanRedo | Disabling redo UI when there is nothing to redo. |
function HistoryActions() {
const undo = useUndo()
const redo = useRedo()
const canUndo = useCanUndo()
const canRedo = useCanRedo()
return (
<div>
<button onClick={undo} disabled={!canUndo}>
Undo
</button>
<button onClick={redo} disabled={!canRedo}>
Redo
</button>
</div>
)
}Next Steps
- See the full Hooks Reference.
- Learn how to register typed layer values in Type Safety.
- Learn how to build custom layer types in Layers.