Panel editor

Brochure-style content editor with a 3D panel preview, per-panel completion tracking, and side flipping.

Default brand color scheme

0/6 sections complete0%
x
Leave empty
Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/panel-editor.json
Usage
Define your panels (with side + label), then render the editor with controlled state.
TSImport
import {
  PanelEditor,
  type PanelDefinition,
} from "@/components/blocks/panel-editor";
TSExample
import * as React from "react";
import {
  PanelEditor,
  type PanelDefinition,
} from "@/components/blocks/panel-editor";

const panels: PanelDefinition[] = [
  { key: "out-1", label: "Panel 1", side: "outside" },
  { key: "out-2", label: "Panel 2", side: "outside" },
  { key: "out-3", label: "Panel 3", side: "outside" },
  { key: "in-1",  label: "Panel 4", side: "inside"  },
  { key: "in-2",  label: "Panel 5", side: "inside"  },
  { key: "in-3",  label: "Panel 6", side: "inside"  },
];

export function Example() {
  const [values, setValues] = React.useState<Record<string, string>>({});
  return (
    <PanelEditor
      label="Tri-fold brochure"
      caption="Default brand color scheme"
      required
      foldType="tri_fold"
      panels={panels}
      value={values}
      onChange={setValues}
    />
  );
}
Composition
Anatomy of the panel editor.
PanelEditor
├── Header (label / description / required indicator)
├── 3D fold preview (tri_fold | bi_fold | no_fold)
├── Side toggle (outside / inside, or front / back)
└── Per-panel content cards (one per PanelDefinition)
Tri-fold (brand)
Six panels — three outside, three inside. Default brand color scheme.

Default brand color scheme

0/6 sections complete0%
x
Leave empty
Tri-fold (coral)
Same shape, alternate color scheme.
0/6 sections complete0%
x
Leave empty
Tri-fold (custom colors)
Pass `customColors` — an array of `{ background }` objects — to set per-panel colors directly. Each entry is applied to the corresponding panel; mix in `{ className }` if you'd rather use Tailwind utilities.

Per-panel colors via `customColors`.

0/6 sections complete0%
x
Leave empty
With dictation
`editor="dictation"` adds a mic button next to the active panel; the Web Speech API streams transcribed text into the active panel.

Click the mic in any panel and start talking.

0/6 sections complete0%
x
Leave empty
With rich-text editor
`editor="rich-text"` swaps the textarea for a `<RichTextEditor>` so authors can format copy inline (bold, italics, lists, links).

Each panel hosts a full RichTextEditor.

0/6 sections complete0%
x
Leave empty
Tri-fold (flat / 2D)
Pass `flat` to disable the 3D fold rotation — panels render as a flat 2D strip.

Same editor, no 3D fold rotation.

0/6 sections complete0%
x
Leave empty
Error state
Pass `errorMessage` to flag unfilled panels — the editor shakes (transitions-dev error-state-shake) and the message fades in below. Click Validate to trigger it.

Click Validate with unfilled panels to trigger the error.

0/6 sections complete0%
x
Leave empty
Bi-fold
Four panels — two outside, two inside.
0/4 sections complete0%
x
Leave empty
No fold (single sheet)
Front/back only. Flip swaps between the two faces.
0/2 sections complete0%
x
Leave empty
API Reference
Props for the PanelEditor block and the PanelDefinition entries.

PanelEditor

PropTypeDefaultDescription
labelstringField label rendered above the editor.
captionstringSub-text under the label.
requiredbooleanfalseRenders a required indicator.
foldType"tri_fold" | "bi_fold" | "no_fold"Drives the 3D preview geometry and side vocabulary.
panelsPanelDefinition[]Panels rendered in display order.
valueRecord<string, string>Per-panel content keyed by `PanelDefinition.key`. Panels marked "leave empty" store the exported `PANEL_LEFT_EMPTY` sentinel so validation/persistence see the decision — strip it to "" when shaping the final payload.
onChange(next: Record<string, string>) => voidFired whenever any panel content changes.
colorScheme"brand" | "coral" | "rainbow" | "violet" | "pink""brand"Color palette for the panel headers.
flatbooleanfalseRender the panels flat (2D) — disables the 3D fold rotation.

PanelDefinition

PropTypeDefaultDescription
keystringStable identifier — also the value-map key.
labelstringPanel header label.
side"outside" | "inside" | "front" | "back"Which face the panel belongs to (use front/back for `no_fold`).