# Save button (goodtabs UI)

A bookmark toggle. Outline when unsaved, filled in the brand colour when saved.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/save-button.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/save-button`

## Usage

```tsx
import { SaveButton } from "@/components/ui/save-button"

<SaveButton onSavedChange={(saved) => save(item.id, saved)} />
<SaveButton saved={isSaved} onSavedChange={setSaved} showLabel />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| saved | `boolean` |  | Controlled saved state. Leave undefined to let the button manage it. |
| defaultSaved | `boolean` | `false` | Starting state when uncontrolled. |
| onSavedChange | `(saved: boolean) => void` |  | Called with the next state on every toggle. |
| labels | `{ save: string; saved: string }` | `{ save: "Save", saved: "Saved" }` | Visible text with showLabel, accessible name without it. |
| showLabel | `boolean` | `false` | Show the label next to the icon. Switches the size from icon-sm to sm. |
| variant | `Button variant` | `"outline"` | Any shadcn button variant. Use ghost inside cards. |

## When to use

- Bookmarking a resource, article, issue or listing for later
- In a card corner, a toolbar or next to a title, wherever one item can be kept
- When the saved state should be visible at a glance across a grid

## When not to use

- For likes, votes or reactions, which carry a count and a different meaning
- For following or subscribing to a feed; use a labelled toggle with its own copy
- As a submit action; it toggles state, it does not send a form

## Notes for agents

- Uncontrolled by default (defaultSaved); pass saved plus onSavedChange to control it from a store
- Demos that pass onSavedChange or onClick from a server page must themselves be client components
- The saved colour is the text-brand utility, which needs --brand and --color-brand in globals.css; without them the saved state still reads by the filled icon
- aria-pressed carries the state; the accessible name stays the save label so screen readers hear Save, pressed

Docs: https://ui.goodtabs.co/components/save-button