shadcn.io is an independent project built on shadcn/ui
One status, two workflows, starting at To Do. The first row is To Do, In Progress, Review, and Done. The second is Backlog, Active, and Completed. Picking Active clears To Do. Any step can be picked, including a jump to Done. The value is only stored, not saved.
Keep the row that matches the workflow. These are pressed buttons, not radios. Arrow keys in one stop need a Radio Group. In React, Ark UI does not save the status.
Installation
Anatomy

Usage
<div className="flex flex-col gap-4">
<ButtonGroup aria-label="Status">
{STATUSES.map((item) => (
<Button
aria-pressed={status === item.value}
key={item.value}
onClick={handleSelect}
size="sm"
value={item.value}
variant={status === item.value ? "default" : "outline"}
>
{item.label}
</Button>
))}
</ButtonGroup>
<ButtonGroup aria-label="Stage">
{STAGES.map((item) => (
<Button
aria-pressed={status === item.value}
key={item.value}
onClick={handleSelect}
size="sm"
value={item.value}
variant={status === item.value ? "default" : "outline"}
>
{item.label}
</Button>
))}
</ButtonGroup>
</div>FAQ
How is the status tracked?
One value, starting at todo. Each button carries its own value, such as inProgress, and pressing it stores that value. The matching button gets variant="default" and aria-pressed.
Do the two rows share a selection?
Yes. Picking Active clears To Do. Keep the row that matches your workflow.
Can someone skip from To Do to Done?
Yes, any button can be picked. Disable the steps that aren't allowed yet if your workflow enforces an order.
Does the demo save the status?
No. It only stores it in the component. Send the value to your API when it changes.
API Reference
Button Group
Sets aria-label="Status" and aria-label="Stage". The rest is on the Button Group page.
Button
Sets aria-pressed={status === item.value}, onClick={handleSelect}, size="sm", value={item.value} and variant={status === item.value ? "default" : "outline"}. The rest is on the Button page.





