WebberUI

Live Preview Wizard

A two-column onboarding layout with a stepped form on the left and a live preview canvas on the right — input morphs into the preview instantly, and step changes slide the form directionally while the preview cross-fades.

Loading preview…
npx shadcn@latest add https://webberui.com/r/live-preview-wizard.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

<LivePreviewWizard />

Installation

npx shadcn@latest add https://webberui.com/r/live-preview-wizard.json

Or, once registries are configured in components.json, install it as @webberui/live-preview-wizard.

Usage

Declare each step's form fields with <LivePreviewWizardStep>, and supply the right-hand live preview through preview. Fields inside a step read and write the shared values through useLivePreviewWizard, so input is reflected in the preview instantly.

import {
  LivePreviewWizard,
  LivePreviewWizardStep,
  useLivePreviewWizard,
} from "@/components/ui/live-preview-wizard";

type Form = {
  name: string;
};

function NameField() {
  const { values, setValue } = useLivePreviewWizard<Form>();
  return (
    <input
      value={values.name}
      onChange={(e) => setValue("name", e.target.value)}
    />
  );
}

function Preview() {
  const { values } = useLivePreviewWizard<Form>();
  return <h1>{values.name || "Your product"}</h1>;
}

export function Example() {
  return (
    <LivePreviewWizard<Form>
      defaultValues={{ name: "" }}
      preview={<Preview />}
      onComplete={(values) => console.log(values)}
    >
      <LivePreviewWizardStep label="Brand">
        <NameField />
      </LivePreviewWizardStep>
    </LivePreviewWizard>
  );
}

Props

LivePreviewWizard

PropTypeDefaultDescription
childrenReactNodeStep declarations, all <LivePreviewWizardStep>
previewReactNode | (ctx) => ReactNodeDefault live preview content, used when a step does not supply its own
valuesTControlled form data; when omitted, the component manages it internally (uncontrolled)
defaultValuesT{}Initial data in uncontrolled mode
onValuesChange(values: T) => voidFires when the data changes, with the latest complete data
stepnumberControlled current step index; when omitted, the component manages it internally
defaultStepnumber0Initial step in uncontrolled mode
onStepChange(step, direction) => voidFires when the step changes (direction: 1 forward, -1 back)
onComplete(values: T) => voidFires when "Complete" is pressed on the last step
progress"dots" | "bar" | false"dots"Progress indicator style; false hides it
controlsbooleantrueWhether to render the built-in back / next control bar
previewSide"left" | "right""right"Which side the preview canvas sits on for wide screens
previewLabelstring"preview.app"Text in the preview frame's faux address bar
backLabel / nextLabel / completeLabelstring上一步 / 下一步 / 完成Control bar button text
classNamestringAppended to the outer grid's className

LivePreviewWizardStep

PropTypeDefaultDescription
labelstringStep title shown in the progress indicator
childrenReactNodeThis step's form fields
previewReactNode | (ctx) => ReactNodePreview specific to this step, overriding the container's preview
classNamestringAppended to the step container's className

useLivePreviewWizard<T>()

Returns the current values, setValue(key, value), setValues(partial), plus navigation state such as step / total / direction / isFirst / isLast / goTo / next / back. It must be called inside <LivePreviewWizard>.

How it works

  • Both modes: values and step each support controlled (pass the prop) and uncontrolled (defaultValues / defaultStep) usage.
  • Live morph: fields write into the shared values through setValue, and the preview repaints instantly within the same step; for color changes, pair it with CSS transition-colors to make the morph smoother.
  • Direction aware: next / back / goTo derive the switch direction, so the form slides horizontally and the preview cross-fades.
  • Per-step preview: setting preview on a <LivePreviewWizardStep> lets different steps emphasize different things, cross-fading naturally as you move between them.

Accessibility

  • The progress dots / bar carry role and aria-* attributes; steps you have already reached are clickable to jump to, and the ones you have not are disabled.
  • Step blocks carry aria-roledescription="步驟" (step) and an aria-label, and the current step is announced through aria-live="polite".
  • The preview canvas carries aria-label="即時預覽" (live preview); the control bar buttons are all keyboard operable and have focus styling.
  • When the user has "reduce motion" enabled, the slide becomes a fade in / fade out and the spring transitions are disabled, with no impact on the layout structure.

On this page