# Call To Action

> A next step offered in a card: a scene that shows it, what it is, why, how far along you are, and the step itself.

- Name: `call-to-action`
- Status: beta
- Categories: actions
- File: the install writes `call-to-action.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `lucide-react`. The install adds them.
- Other registry items: `@arbokui/button`, `@arbokui/card`, `@arbokui/icon`, `@arbokui/ring-progress`, `@arbokui/tool-button`. The install adds them.
- Gallery: https://arbokui.com/components/call-to-action
- Registry item: https://arbokui.com/r/call-to-action.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/call-to-action
   ```

## Use it for

- Where the space would sit empty otherwise: a workspace still setting up, a feature nobody has tried yet.
- title says what the step is. text says why, in a line or two. Put a Scene in scene to show it.
- main is the step itself, a primary button with its icon. later is the quiet way out: "Skip" or "Later".
- Pass progress, like { done: 3, of: 4 }, when the step is one of a set.
- Give main a result, like { label: "Invites sent", onUndo, onCommit }, to show what the press did on the button, with Undo for 8 seconds.

## Avoid it for

- More than one on a screen.
- Warnings or news. Use an alert.
- Steps people can't skip. Put them in the page's flow.

## Props

- `title`: `string`. Required. What the step is: "Invite your team". It names the card for screen readers.
- `text`: `ReactNode`. Why, in a line or two.
- `scene`: `ReactNode`. A Scene, inset 6px from the card's edge.
- `progress`: `{ done: number; of: number }`. How far along a set of steps is: a small ring and "3 of 4".
- `main`: `{ label: string; icon?: IconName | ReactNode; onClick?: () => void | Promise<unknown>; result?: ActionResult; loading?: boolean; disabled?: boolean }`. Required. The step itself: a brand button with its icon. icon is a name from Icon's set or any icon. A returned promise shows it's busy.
- `later`: `{ label: string; onClick?: () => void }`. The quiet way out, a ghost button before the step.
- `className`: `string`. Extra classes on the card. Later classes win.

## Accessibility

- The card is a region named by its title.
- Tab goes to the way out, then the step. Both are buttons.
- Progress reads as "3 of 4 done". The ring is hidden, since the words say it.
- A result changes the step's own name, like "Invites sent. Press to undo.", and is said in a polite live region.
- Undo only undoes once 1.2 seconds have passed, so a double press never undoes. ⌘Z takes it back too.

## Examples

### With progress, a way out, and Undo

```tsx
import { UserPlus } from "lucide-react";

<CallToAction
  scene={
    <Scene>
      <SceneHint icon={<UserPlus />} label="Invite people" />
    </Scene>
  }
  title="Invite your team"
  text="They see the plan and pick up work, without asking you."
  progress={{ done: 3, of: 4 }}
  later={{ label: "Skip", onClick: () => console.log("skip") }}
  main={{
    label: "Invite people",
    icon: <UserPlus />,
    result: { label: "Invites sent", onUndo: () => {}, onCommit: () => console.log("send invites") },
  }}
/>
```
