Find an action, edit its parameters, inspect proposed changes, then execute with cancellation, retry and optional undo.
Choose an action to inspect its changes.
pnpm dlx shadcn@latest add @latheui/command-previewPart of Lathe Pro. Set up your project once with your license key: npx latheui init --key <key>. See Lathe Pro.
Command Preview is part of Lathe Pro
The preview is live and free to try. The source, the install and every assembly come with Pro: $79 once, with lifetime updates.
Depends on
| Prop | Type | Default | Description |
|---|---|---|---|
| commands* (required) | readonly PreviewCommand[] | — | Unique ids, labels, descriptions, optional parameter definitions, preview and execute callbacks, and optional undo. Keep command definitions consistent during a run. |
| commands[].parameters | { key; label; defaultValue?; required? }[] | — | String parameters. Required values prevent preview when blank. |
| commands[].preview | (parameters, signal) => ReactNode | Promise<ReactNode> | — | Return a side-effect-free preview. Editing parameters invalidates it. |
| commands[].execute | (parameters, signal) => void | Promise<void> | — | Run only after a successful preview. Honor signal; reject to show retry feedback. |
| commands[].undo | (signal) => void | Promise<void> | — | Optional application-owned undo offered after successful execution. No undo control is shown otherwise. |
| disabled | boolean | false | Disable search, selection and actions. |
| className | string | — | Classes for the section. |
Replace the demo data and callbacks with your application. Honor AbortSignal in asynchronous callbacks so cancellation also stops transport work.
"use client"
import * as React from "react"
import { Checkbox } from "@/components/ui/checkbox"
import {
CommandPreview,
type PreviewCommand,
} from "@/components/command-preview"
export default function CommandDemo() {
const [archived, setArchived] = React.useState(false)
const [fail, setFail] = React.useState(false)
const commands: PreviewCommand[] = [
{
id: "archive",
label: "Archive completed work",
description: "Move finished projects out of the active workspace.",
parameters: [
{
key: "workspace",
label: "Workspace",
defaultValue: "Studio",
required: true,
},
],
preview: async (params, signal) => {
await new Promise((resolve) => setTimeout(resolve, 250))
if (signal.aborted) return null
return (
<div className="space-y-2">
<p className="font-medium">
3 projects will be archived in {params.workspace}.
</p>
<ul className="list-inside list-disc text-xs text-muted-foreground">
<li>Brand exploration</li>
<li>Autumn campaign</li>
<li>Website audit</li>
</ul>
<p className="text-xs text-muted-foreground">
Files stay available. This action supports undo.
</p>
</div>
)
},
execute: async (_params, signal) => {
await new Promise((resolve) => setTimeout(resolve, 500))
if (signal.aborted) return
if (fail) {
setFail(false)
throw new Error("The workspace is offline. Try again.")
}
setArchived(true)
},
undo: async (signal) => {
if (!signal.aborted) setArchived(false)
},
},
{
id: "export",
label: "Prepare project export",
description: "Inspect the contents of a project archive.",
parameters: [
{
key: "project",
label: "Project",
defaultValue: "Field notes",
required: true,
},
],
preview: (params) => (
<p className="text-xs">
The export for {params.project} will contain 12 documents and 4
images.
</p>
),
execute: async () => {
await new Promise((resolve) => setTimeout(resolve, 300))
},
},
]
return (
<div className="w-full max-w-2xl space-y-3">
<CommandPreview commands={commands} />
<div className="flex flex-wrap justify-between gap-2 text-xs text-muted-foreground">
<Checkbox
label="Fail next action"
checked={fail}
onCheckedChange={(checked) => setFail(checked === true)}
className="text-xs"
/>
<span>{archived ? "3 projects archived" : "3 projects active"}</span>
</div>
</div>
)
}