# Button: Controlled status

> Drive `status` directly, for example from a form library’s submit state.

Example: https://hextaui.com/docs/button/examples/controlled-status
Component docs: https://hextaui.com/docs/button.md

## Add this example

```bash
npx shadcn@latest add https://hextaui.com/r/button-controlled-status.json
```

This adds `components/examples/button/controlled-status.tsx` with the Button component and the HextaUI theme tokens.

## Source

```tsx title="components/examples/button/controlled-status.tsx"
"use client"

import * as React from "react"
import { IconRocket } from "@tabler/icons-react"

import { Button, type ButtonStatus } from "@/components/ui/button"

const statuses: ButtonStatus[] = ["idle", "loading", "success", "error"]

export function ButtonControlledStatus() {
  const [status, setStatus] = React.useState<ButtonStatus>("idle")

  return (
    <div className="flex flex-col items-center gap-3">
      <Button
        status={status}
        onStatusChange={setStatus}
        successLabel="Deployed"
        errorLabel="Deploy failed"
      >
        <IconRocket data-icon="inline-start" />
        Deploy
      </Button>
      <div className="flex flex-wrap justify-center gap-2">
        {statuses.map((next) => (
          <Button
            key={next}
            size="xs"
            variant={status === next ? "secondary" : "ghost"}
            onClick={() => setStatus(next)}
          >
            {next}
          </Button>
        ))}
      </div>
    </div>
  )
}
```

## Props in this example

### Button

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` | `"default" \| "outline" \| "secondary" \| "ghost" \| "ghost-destructive" \| "destructive" \| "link"` | `"default"` |  |
| `size` | `"xs" \| "sm" \| "default" \| "lg" \| "icon-xs" \| "icon-sm" \| "icon" \| "icon-lg" \| "icon-xl"` | `"default"` |  |
| `onClick` | `(event) => unknown` | – | Return a promise to drive feedback. |
| `status` | `"idle" \| "loading" \| "success" \| "error"` | – | Controlled status. Takes priority over loading. |
| `onStatusChange` | `(status: ButtonStatus) => void` | – |  |
| `successLabel` | `ReactNode` | `"Done"` |  |
| `errorLabel` | `ReactNode \| (error: unknown) => ReactNode` | `"Failed"` |  |

## More Button examples

- [Variants](https://hextaui.com/docs/button/examples/variants.md)
- [Sizes](https://hextaui.com/docs/button/examples/sizes.md)
- [Pill](https://hextaui.com/docs/button/examples/pill.md)
- [With icon](https://hextaui.com/docs/button/examples/with-icon.md)
- [Disabled](https://hextaui.com/docs/button/examples/disabled.md)
- [Custom labels](https://hextaui.com/docs/button/examples/custom-labels.md)
- [Smooth width](https://hextaui.com/docs/button/examples/smooth-width.md)
- [Error details](https://hextaui.com/docs/button/examples/error-details.md)
- [Forms](https://hextaui.com/docs/button/examples/form.md)
- [Icon buttons](https://hextaui.com/docs/button/examples/icon-feedback.md)
- [Feedback on every variant](https://hextaui.com/docs/button/examples/variants-feedback.md)
- [Controlled loading](https://hextaui.com/docs/button/examples/controlled-loading.md)
- [As a link](https://hextaui.com/docs/button/examples/link.md)
- [Right to left](https://hextaui.com/docs/button/examples/rtl.md)
