# Job Card

> One job on one line, like an import, a send, a sync, or an export: its status, what it is, a few words about it, and how long it took. A thin bar fills while it runs. It opens to the details.

- Name: `job-card`
- Status: beta
- Categories: ai, feedback
- File: the install writes `job-card.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `@base-ui/react`. The install adds them.
- Other registry items: `@arbokui/card`, `@arbokui/spinner`. The install adds them.
- Gallery: https://arbokui.com/components/job-card
- Registry item: https://arbokui.com/r/job-card.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/job-card
   ```

## Use it for

- In an activity log or a jobs page, one card per job: what ran, on what, and what came of it.
- Pass status queued before it starts, running while it runs, then done, failed, or canceled.
- Pass progress from 0 to 1 while it runs, like 0.45 for 45%. A thin bar fills along the bottom edge, and the line shows the percent.
- Keep summary to a few words, like the file name or how many rows. The full data goes in details.
- Pass details as labeled sections, like Request and Response. An object or array shows as JSON. Pass a node to show it your own way.
- On failed, pass error in plain words, like "Row 214 has no email." It shows under the line, so no one has to open the card to see it.
- Stack several in a flex column with a small gap for a list of jobs.

## Avoid it for

- A job that needs a person to say yes before it runs. Ask first, then show the job.
- Many jobs grouped by who has to act next. Use the Task Inbox block.
- A status on a row or in a table. Use StatusText.
- A single upload with nothing to open. Use Progress.
- An agent's tool call. Use ToolCallCard.

## Props

- `title`: `ReactNode`. Required. What the job is, like "Import contacts".
- `status`: `"queued" | "running" | "done" | "failed" | "canceled"`. Required. Where the job stands. queued is a dashed ring, running spins in the brand tone, done is a success check, failed is danger red, and canceled is quiet.
- `summary`: `ReactNode`. The job in a few words, like "contacts.csv, 2,400 rows". Shown on the closed line, cut short with an ellipsis.
- `progress`: `number`. running: how far along it is, from 0 to 1. A thin bar fills along the bottom edge, and the line shows the percent.
- `details`: `{ label: string; value: ReactNode | Record<string, unknown> | unknown[] }[]`. Default `[]`. What the open card shows, in order, like Request and Response. An object or array shows as JSON. With none, it says it is waiting, or that there are no details.
- `error`: `ReactNode`. failed: what went wrong, in plain words. It shows under the line, open or closed.
- `duration`: `string`. How long it took, has run so far, or when it ran, like "1.5s" or "2m ago". Update it while running for a live timer.
- `defaultOpen`: `boolean`. Default `false`. Starts open.
- `open`: `boolean`. Controls whether it is open. Pair it with onOpenChange.
- `onOpenChange`: `(open: boolean) => void`. Called when the card opens or closes.
- `disabled`: `boolean`. Default `false`. The line can't be opened.
- `className`: `string`. Extra classes on the card. Later classes win.

## Accessibility

- The line is one button. It says the status in words, the title, the summary, the percent, and the time, and it tells screen readers if it is open.
- Enter or Space opens and closes it.
- Status is shown three ways: words for screen readers, an icon shape, and a color.
- While running with progress, a progress bar named by the title sits outside the button.
- A change of status is said once, politely, in a hidden status region: Import contacts: Done.
- The error is plain text under the line, so it is read without opening the card.
- The spinner stops and the bar jumps to its value when the theme turns motion off, and for reduced motion. The panel then opens at once.

## Examples

### Running, with progress

```tsx
<JobCard title="Import contacts" status="running" summary="contacts.csv, 2,400 rows" progress={0.45} duration="12s" />
```

### Done, with details

```tsx
<JobCard
  title="Send welcome email"
  status="done"
  summary="ana@example.com"
  duration="0.4s"
  details={[
    { label: "Request", value: { to: "ana@example.com", template: "welcome" } },
    { label: "Response", value: { id: "msg_812", status: 202 } },
  ]}
/>
```

### Failed

```tsx
<JobCard title="Sync calendar" status="failed" summary="Team events" duration="4.2s" error="The calendar's access ran out. Connect it again." />
```

### Queued

```tsx
<JobCard title="Export report" status="queued" summary="Q3 sales, PDF" />
```
