bx

Button

Displays a button or a component that looks like a button.

tsx
<Button>Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>

Button is the universal shadcn button. 6 variants (default, secondary, destructive, outline, ghost, link) × 4 sizes (default, sm, lg, icon). It renders a <button> or an <a> depending on whether href is set.

It is the base of DropdownMenuTrigger, DialogTrigger, PopoverTrigger, AlertDialogAction and others: the foundation of half the kit.

Installation

Terminal
$ bext ui add button

Usage

tsx
import { Button } from "@bext-stack/ui/primitives"

<Button>Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline" size="sm">Small outline</Button>
<Button variant="destructive">Delete</Button>
<Button href="/docs" target="_blank">External link</Button>
<Button loading>Saving...</Button>

Anatomy

<Button variant="default|secondary|destructive|outline|ghost|link" size="default|sm|lg|icon" href?>
  ├── {loading ? <Spinner /> : icon && <Icon />}
  └── {children}

API Reference

Button

Prop Type Default Description
variant "default" | "secondary" | "destructive" | "outline" | "ghost" | "link" "default" Visual style of the button.
size "default" | "sm" | "lg" | "icon" "default" Size: sm=h-8, default=h-9, lg=h-10, icon=h-9 w-9 (square).
href string — When set, renders an <a> instead of a <button>. Adds rel="noopener" if target is defined.
target string — E.g. "_blank" to open in a new tab.
type "button" | "submit" | "reset" "button" HTML type for real buttons (inside a form).
icon string — Lucide-style slug that adds an icon to the left of the label.
loading boolean — Shows a spinner in place of the icon. Disables the button (aria-busy).
disabled boolean — Standard HTML.

Keyboard

Key Action
Enter / Space Activates the button (native behavior).
Tab Moves focus to or away from the button.

Accessibility

Always provide explicit text or an aria-label when the button only contains an icon (size="icon"). Otherwise assistive technologies announce "button" with no context.

loading=true adds aria-busy="true" and disables the button.

Examples

Sizes (sm / default / lg / icon)

tsx
<Button size="sm">Small</Button>
<Button>Default</Button>
<Button size="lg">Large</Button>
<Button size="icon" aria-label="Add"><PlusIcon /></Button>

Loading state

tsx
<Button loading>Saving...</Button>
Try it live
Open in play

Edit this component live in the bext playground. The PRISM + signals version is the bext-native idiom: fine-grained reactivity, no virtual DOM.

src/app/page.tsx 2 files · signals · runs in your browser
Pure PRISM + real bext signals: fine-grained, no re-render.