# Flowchart

> Lay out an agent workflow as a sequence of steps joined by connectors.

Source: https://ai.honestui.com/docs/components/flowchart

```tsx
import { Flowchart, FlowStep } from "@/components/ai/flowchart"

export function FlowchartDemo() {
  return (
    <div className="w-full max-w-md min-w-0">
      <Flowchart label="Invoice follow-up workflow">
        <FlowStep
          kind="Trigger"
          title="Invoice becomes overdue"
          caption="Runs once for each invoice, the day after its due date."
        />
        <FlowStep
          kind="If / Else"
          title="Amount is over 1,000"
          caption="Larger invoices go to a person before any email is sent."
        />
        <FlowStep kind="Action" title="Draft a reminder email" caption="Waits for approval." />
      </Flowchart>
    </div>
  )
}

```

## Overview [#overview]

Flowchart shows a workflow from top to bottom: a trigger, a condition, an action. Each step is a card with a kind, a title, and a caption, and any controls you put inside it.

It is a layout, not an editor. The steps are in the order you render them and cannot be dragged. The Beautiful UI original let cards be dragged around a canvas, which has no keyboard equivalent and stores nothing, so it is left out.

## Anatomy [#anatomy]

<Anatomy title="Flowchart">
  <AnatomyItem name="Flowchart" description="The dotted canvas and the ordered list of steps" />

  <AnatomyItem name="FlowStep" description="One step: a kind, a card, and the connector above it" />

  <AnatomyItem name="Children" description="Your controls for the step" />
</Anatomy>

`flowchart` has no registry dependencies.

## Behavior [#behavior]

### Order [#order]

Steps are stacked in the order you render them, with a connector above every step but the first.

### Step content [#step-content]

`title` and `caption` are optional. A step's children are placed in its card under them, for a condition's fields or a summary of what an action will do.

## Accessibility [#accessibility]

The flow is an ordered list named by `label`, so the sequence is available without the connectors, which are decoration. Each step's kind is text.

Flowchart has no keyboard interaction of its own. Controls you place in a step keep theirs.

## Installation [#installation]


  

  
    <CliBlock commands="[&#x22;@honestai/flowchart&#x22;]" />
  

  
    
      
        Copy and paste this file into your project.
      

      ### components/ai/flowchart.tsx

```tsx
import * as React from "react"

import { cn } from "@/lib/utils"

export type FlowchartProps = React.ComponentProps<"ol"> & {
  /** Names the workflow for screen readers. */
  label: string
}

/**
 * A workflow as a top-to-bottom sequence of steps joined by connectors. The
 * steps are an ordered list, so the order is available without the lines.
 */
function Flowchart({ label, className, ...props }: FlowchartProps) {
  return (
    <ol
      role="list"
      aria-label={label}
      data-slot="flowchart"
      className={cn(
        "m-0 flex w-full min-w-0 list-none flex-col items-center gap-[var(--hui-space-9)] rounded-[var(--hui-radius-4)] bg-[var(--hui-color-background-base-secondary)] bg-[radial-gradient(var(--hui-color-border-base-secondary)_1px,transparent_1px)] p-[var(--hui-space-7)] [background-size:16px_16px]",
        className
      )}
      {...props}
    />
  )
}

export type FlowStepProps = Omit<React.ComponentProps<"li">, "title"> & {
  /** The step's role in the flow, such as "Trigger" or "If / Else". */
  kind: string
  title?: React.ReactNode
  /** One line under the title. */
  caption?: React.ReactNode
}

/** One step. Put controls for the step, such as a condition's fields, in its children. */
function FlowStep({ kind, title, caption, className, children, ...props }: FlowStepProps) {
  return (
    <li
      data-slot="flow-step"
      className={cn(
        // The connector is drawn above every step but the first.
        "relative flex w-full max-w-sm min-w-0 flex-col gap-[var(--hui-space-2)] before:absolute before:bottom-full before:left-1/2 before:h-[var(--hui-space-9)] before:w-px before:bg-[var(--hui-color-border-base-emphasis)] first:before:hidden",
        className
      )}
      {...props}
    >
      <span className="w-fit rounded-[var(--hui-radius-full)] bg-[var(--hui-color-background-neutral-secondary)] px-[var(--hui-space-3)] py-[var(--hui-space-1)] text-[var(--hui-color-foreground-base-primary)] [font-size:var(--hui-font-size-mini)] [font-weight:var(--hui-font-weight-medium)] [line-height:var(--hui-line-height-mini)]">
        {kind}
      </span>
      <div className="flex min-w-0 flex-col gap-[var(--hui-space-3)] rounded-[var(--hui-radius-4)] border-[0.5px] border-[var(--hui-color-border-base-primary)] bg-[var(--hui-color-background-base-primary)] p-[var(--hui-space-4)] text-[var(--hui-color-foreground-base-primary)] shadow-[var(--hui-shadow-soft)] [font-size:var(--hui-font-size-small)] [line-height:var(--hui-line-height-small)]">
        {(title || caption) && (
          <div className="flex min-w-0 flex-col gap-[var(--hui-space-1)]">
            {title && (
              <p className="m-0 break-words [font-size:var(--hui-font-size-regular)] [font-weight:var(--hui-font-weight-medium)] [line-height:var(--hui-line-height-regular)]">
                {title}
              </p>
            )}
            {caption && (
              <p className="m-0 break-words text-[var(--hui-color-foreground-base-secondary)]">{caption}</p>
            )}
          </div>
        )}
        {children}
      </div>
    </li>
  )
}

export { Flowchart, FlowStep }

```

      
        Update the import paths to match your project setup.
      
    
  


## Usage [#usage]

```tsx
import { Flowchart, FlowStep } from "@/components/ai/flowchart"

<Flowchart label="Invoice follow-up workflow">
  {workflow.steps.map((step) => (
    <FlowStep key={step.id} kind={step.kind} title={step.title} caption={step.summary} />
  ))}
</Flowchart>
```

## Examples [#examples]

### A step with controls [#a-step-with-controls]

The condition step holds a Select. Its value is yours to store.

```tsx
"use client"

import * as React from "react"

import { Flowchart, FlowStep } from "@/components/ai/flowchart"
import {
  Select,
  SelectItem,
  SelectPopup,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

const fields = [
  { value: "amount", label: "Amount" },
  { value: "region", label: "Region" },
  { value: "age", label: "Days overdue" },
]

export function FlowchartControlsExample() {
  const [field, setField] = React.useState("amount")

  return (
    <div className="w-full max-w-md min-w-0">
      <Flowchart label="Condition editor">
        <FlowStep kind="Trigger" title="Invoice becomes overdue" />
        <FlowStep kind="If / Else" title="Branch on a field">
          <Select
            items={fields}
            value={field}
            onValueChange={(next) => {
              if (typeof next === "string") setField(next)
            }}
          >
            <SelectTrigger size="sm" aria-label="Field to branch on" className="w-full">
              <SelectValue />
            </SelectTrigger>
            <SelectPopup>
              {fields.map((item) => (
                <SelectItem key={item.value} value={item.value}>
                  {item.label}
                </SelectItem>
              ))}
            </SelectPopup>
          </Select>
        </FlowStep>
      </Flowchart>
    </div>
  )
}

```

## API reference [#api-reference]

### Flowchart [#flowchart]

Accepts native ol props beyond those listed. Its children are the steps.

| Prop    | Type   | Default  | Description         |
| ------- | ------ | -------- | ------------------- |
| `label` | string | Required | Names the workflow. |

### FlowStep [#flowstep]

Accepts native li props beyond those listed.

| Prop      | Type      | Default  | Description                  |
| --------- | --------- | -------- | ---------------------------- |
| `kind`    | string    | Required | The step's role in the flow. |
| `title`   | ReactNode | None     | What the step does.          |
| `caption` | ReactNode | None     | One line under the title.    |
