Capítulo 20 de 108
Button is the base interactive element: 6 variants, 8 sizes, and composable icon/spinner slots via data-icon attributes for correct spacing.
variant: default | outline | ghost | destructive | secondary | link.size: default | xs | sm | lg | icon | icon-xs | icon-sm | icon-lg (icon sizes are square, for icon-only buttons).data-icon="inline-start" / "inline-end": required attribute on any icon or Spinner placed inside a Button for correct spacing, not automatic just by being a child.buttonVariants helper: use to style a plain <a> as a link that looks like a button; never render Button as an <a> via render/nativeButton={false}, since the Base UI Button forces role="button" which overrides the native link semantics.cursor: default; opt into cursor: pointer via CSS (@layer base rule) or shadcn init --pointer.<Button variant="outline">Button</Button>
<Button variant="outline" size="icon" aria-label="Submit">
<ArrowUpIcon />
</Button>
<Button variant="outline">
<IconGitBranch data-icon="inline-start" /> New Branch
</Button>
<Button variant="outline">
Fork
<IconGitFork data-icon="inline-end" />
</Button>
data-icon.<Button variant="outline" disabled>
<Spinner data-icon="inline-start" />
Generating
</Button>
Spinner, mesmo padrão de data-icon que ícones normais.import { buttonVariants } from "@/components/ui/button"
<a href="#" className={buttonVariants({ variant: "secondary", size: "sm" })}>
Login
</a>
@layer base {
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;
}
}
cursor: pointer (Tailwind v4 default mudou para cursor: default).| Prop | Type | Default |
|---|---|---|
variant | "default" | "outline" | "ghost" | "destructive" | "secondary" | "link" | "default" |
size | "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | "default" |
<Button render={<a />} nativeButton={false} /> for links: Base UI's Button always sets role="button", breaking the anchor's native link semantics for assistive tech. Use buttonVariants on a real <a> instead.data-icon: spacing will be wrong; the attribute is what triggers the correct margin/gap.cursor: pointer by default: Tailwind v4 changed this; must opt in explicitly (per user's own global convention: resolve once in @layer base, never per-class).aria-label (no visible text for screen readers to use).rtl:rotate-180 on directional icons (e.g. arrows) and dir={dir} on the container; see the RTL configuration guide for global setup.Button composes with ButtonGroup for grouped action clusters (separate component/docs).@base-ui/react as a dependency (this is a Base UI-backed component, base: base style).data-icon-style slot conventions for inline addons.