Xzero UI
Pro library

AI workflowPro

A Linear-style AI workflow card where a Gmail trigger, a Claude step, a branch and Slack and Linear actions sit on one hairline rail, and a test run glides down it, opening each step's output inline. Steps are added from a compact command menu with real app marks.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/ai-workflow
Live · keyboard ready

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/ai-workflow

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { useState } from "react";
import { AiWorkflow, workflowSampleSteps } from "@/components/xzero/ai-workflow/ai-workflow";
import type { WorkflowStep } from "@/components/xzero/ai-workflow/ai-workflow";

export function SupportAutomation() {
  const [steps, setSteps] = useState<WorkflowStep[]>(workflowSampleSteps);
  return (
    <AiWorkflow
      title="Escalate urgent support email"
      steps={steps}
      onStepsChange={setSteps}
      autoPlay={false}
      onRunStep={async (step, { signal, previous }) => {
        const res = await fetch(`/api/workflows/test/${step.id}`, { method: "POST", body: JSON.stringify({ previous }), signal });
        if (!res.ok) throw new Error((await res.json()).message);
        return res.json();
      }}
    />
  );
}

API reference

AiWorkflow

A compact, Linear-style automation builder card with an AI step. Steps are 32px rows on one 1px hairline rail: a trigger (New email in Gmail), an AI step (Classify with Claude Sonnet 5.5), a branch (Route by label) whose paths switch with small tabs, and actions (Post to #support in Slack, Create Linear issue). Test run glides a small accent dot down each connector while the line behind it fills; each step crossfades to Running with a shimmering activity line, then shows its duration and an inline output preview in small muted text (the email, the label with a streamed reason, the posted message, the created issue). The untaken path is marked Skipped. A failing step shows its error and Retry, which resumes the run from that step. Steps are added from a command menu (search field, compact rows with real app marks and number shortcuts) and removed with a small button. With no props it plays the sample flow, simulated, and says so.

PropTypeDefaultDescription
titlestring"Escalate urgent support email"Workflow name in the header.
descriptionstring"Runs on every new email to support@northwind.dev"One line of context under the name.
stepsWorkflowStep[]–Controlled steps. Pair with onStepsChange so adding and removing keep working. Each step has id, kind ("trigger" | "ai" | "action" | "branch"), app (a built-in id or { name, mark }), title, and optional detail, activity, output, durationMs and error. A branch carries paths: { id, label, steps }[] and must be the last top-level step.
defaultStepsWorkflowStep[]workflowSampleStepsInitial steps when uncontrolled. Pass [] for the empty state, which lists the catalog's triggers as compact rows.
onStepsChange(steps: WorkflowStep[]) => void–Called after a step is added or removed. New steps land at the end of the flow, or at the end of the visible path when the flow ends in a branch.
catalogWorkflowCatalogItem[]workflowSampleCatalogEntries for the add step command menu: the same shape as a step without id. Triggers are offered in the empty state; everything else goes in the menu. Pass [] to hide the menu.
onRunStep(step: WorkflowStep, context: { signal: AbortSignal; previous: Record<string, WorkflowOutput>; attempt: number }) => Promise<WorkflowOutput | void>–Runs one step for real and returns its output. Throw to fail the step with the error message. A branch returns { type: "route", pathId } to pick its path. The signal aborts on Stop, a new run or unmount. Without it, runs are simulated from each step's sample output and durationMs.
onRunComplete(result: { status: "passed" | "failed"; durationMs: number; outputs: Record<string, WorkflowOutput>; failedStepId?: string }) => void–Called when a test run passes or stops on a failed step.
loadingbooleanfalseShows three skeleton steps while your flow loads. Test run and the add menu are unavailable.
autoPlaybooleantruePlays a test run once the card is in view and repeats it after a short pause until someone presses or types inside the card. Nothing is scheduled while the card is off screen.
editablebooleantrueShows the add step menu and the remove buttons. Triggers cannot be removed.
classNamestring–Class on the root section.

WorkflowOutput

The output preview union a step can return, rendered inline in small muted text under the step, aligned with its title.

PropTypeDefaultDescription
email{ type: "email"; from: string; address?: string; subject: string; preview: string }–Sender, subject on one line and a two line preview.
label{ type: "label"; label: string; confidence?: number; reason?: string }–A hairline label with a status dot, confidence (0 to 1) in monospace, and a reason that streams in fast chunks.
route{ type: "route"; pathId: string; note?: string }–Which branch path ran.
message{ type: "message"; channel: string; author: string; text: string }–A posted chat message.
record{ type: "record"; id: string; title: string; meta?: string }–A created or updated record: an issue key, a row, a ticket or a page.
text{ type: "text"; text: string }–Free text such as a drafted reply, streamed in fast chunks.

Keyboard interactions

KeysAction
TabMoves through Test run (or Stop), each step's remove button, the branch path tabs, Retry on a failed step, and the Add step button.
Enter / SpaceStarts or stops a test run, removes a step, retries a failed step, or opens the add step menu.
Arrow keysMove between paths in the branch tabs (Home and End jump to the ends). In the open menu, Up and Down move the highlighted row.
TypeFilters the add step menu by step title, app or detail.
Enter (menu)Adds the highlighted step and closes the menu.
1 to 9 (menu)With an empty search, adds the step with that shortcut.
EscapeCloses the add step menu and returns focus to its trigger.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in ai

Guidance for AI tools

AI workflow: A Linear-style AI workflow card where a Gmail trigger, a Claude step, a branch and Slack and Linear actions sit on one hairline rail, and a test run glides down it, opening each step's output inline. Steps are added from a compact command menu with real app marks. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components