Button
uistableButton — extracted 1:1 from WEM-App.
npx shadcn add @krawma/buttonnpm: class-variance-authority@^0.7.1, radix-ui@^1.6.1 · registry: @krawma/utils
Preview
Variants
defaultoutlinesecondaryghostdestructivelink
Sizes
defaultxssmlgiconicon-xsicon-smicon-lg
States
hoverfocus-visibleactivedisabledaria-invalid
Keyboard
EnterSpace
Depends on
utils
Purpose
The primary action trigger. Use for anything that performs an action (submit, open,
confirm). For navigation that changes the URL, render a link — either an <a> via
asChild, or the link variant when it should look like a button-styled link.
Anatomy
Single element: <Button>. With asChild, it forwards its styling/behavior to a
child (e.g. a next/link <a> or a Radix trigger) instead of rendering a
<button>.
Style
- variant (default
default):default(primary, filled) ·outline·secondary·ghost(chromeless, for toolbars/menus) ·destructive(muted danger — used on destructive actions) ·link(inline, underline-on-hover). - size (default
default):default·xs·sm·lg, plus squareicon·icon-xs·icon-sm·icon-lgfor icon-only buttons. - Colors come from tokens (
bg-primary,bg-destructive/10, …); never restyle with ad-hoc classes — add a variant instead.
Behavior & functionality
- Renders a native
<button>(type defaults to the browser default — passtype="button"inside forms to avoid accidental submits). - Cursor:
cursor-pointeron all variants (includinglinkandasChildlinks) — Tailwind v4 resets native<button>tocursor:default, so the base restores the pointer.disabledshows no pointer (pointer-events-none). - Active press yields a subtle translate; disabled disables pointer events.
- Icon children are auto-sized; use
data-[icon=inline-start|inline-end]slots for padding-aware icon buttons.
Accessibility
- Role
button; operable with Enter and Space. - Visible focus via
focus-visiblering (--ring). - Icon-only buttons MUST have an accessible name (
aria-labelor visually hidden text). disabledis both non-interactive and visually muted;aria-invalidstyling is supported for form-trigger cases.
Do / Don't
- ✅ Use
asChildto make a link look/behave like a button — don't nest<a>in<button>. - ✅ Use
destructivefor delete/remove; pair with a confirm (AlertDialog) for irreversible actions. - ❌ Don't pass raw color/size classes to change appearance — pick or add a variant.
- ❌ Don't use
linkvariant for real buttons that don't navigate.