action
A clickable action. Supports variants, sizes, icon-only buttons, loading state and links.
npx blankui add buttonimport { Button } from "@/components/ui/button"
| Variant | Use for |
|---|---|
default | The main action in a view. One per view. |
secondary | A second, less important action. |
outline | Cancel, back, and other neutral actions. |
ghost | Toolbar and icon actions with little weight. |
destructive | Delete or other actions that cannot be undone |
link | An action that should look like a link. |
Sizes: sm, default, lg, icon.
<Inline gap={2} justify="end">
<Button variant="outline">Cancel</Button>
<Button type="submit" loading={isSaving}>
Save changes
</Button>
</Inline>
Icon buttons must have an aria-label. TypeScript reports an error without it.
import { Trash } from "lucide-react"
;<Button size="icon" variant="ghost" aria-label="Delete project">
<Trash />
</Button>
Icons next to text go before the text:
import { Plus } from "lucide-react"
;<Button>
<Plus /> New project
</Button>
Links that look like buttons:
<Button asChild variant="outline">
<a href="/pricing">See pricing</a>
</Button>
type defaults to "button", so a Button inside a form does not submit it. Use type="submit" for the submit button.loading shows a spinner, disables the button and sets aria-busy.| Avoid | Instead |
|---|---|
| <button className=...> (a raw button element) | <Button> |
| <Button className="bg-red-500"> | <Button variant="destructive"> |
| <Button size="icon"><Trash /></Button> without a label | <Button size="icon" aria-label="Delete"><Trash /></Button> |
| <Button><a href=...>Docs</a></Button> (a link inside a button) | <Button asChild><a href="/docs">Docs</a></Button> |
| {isSaving ? <Spinner /> : 'Save'} with disabled={isSaving} | <Button loading={isSaving}>Save</Button> |
| Several default (primary) buttons side by side | One default button, the rest variant="outline" or "ghost" |
Install with the shadcn CLI: npx shadcn add https://blank.vageshwar.dev/r/button.json