Inputsreadycomponentready
Button
A native button and link primitive with RadCN variants, sizing, disabled states, and token-driven styling.
Import
import { Button } from 'radcn/button'Live package example
Use the same Button component for actions, secondary choices, and link-style navigation.
Variants
Use the same Button component for actions, secondary choices, and link-style navigation.
import { Button } from 'radcn/button'
import { Spinner } from 'radcn/spinner'
export function ButtonPreview() {
return (
<div class="button-preview">
<Button>Deploy site</Button>
<Button variant="secondary">Preview</Button>
<Button variant="outline">View docs</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Delete</Button>
<Button variant="link">Link</Button>
<Button href="/docs/components/button">Href Button</Button>
<Button size="sm" variant="outline">
<svg aria-hidden="true" fill="none" height="16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="16">
<path d="M7 17 17 7" />
<path d="M8 7h9v9" />
</svg>
New Branch
</Button>
<Button disabled size="sm" variant="outline">
<Spinner ariaLabel="Submitting" />
Submit
</Button>
<Button ariaLabel="Submit" size="icon" variant="outline">
<svg aria-hidden="true" fill="none" height="16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="16">
<path d="M7 17 17 7" />
<path d="M8 7h9v9" />
</svg>
</Button>
<Button ariaLabel="Upload" class="radcn-fixture-rounded-button" size="icon" variant="outline">
<svg aria-hidden="true" fill="none" height="16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="16">
<path d="M7 17 17 7" />
<path d="M8 7h9v9" />
</svg>
</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
<Button ariaLabel="Submit small" size="icon-sm" variant="outline">^</Button>
<Button ariaLabel="Submit large" size="icon-lg" variant="outline">^</Button>
</div>
)
}Installation
Intended future install command. RadCN is private and not published to npm yet, so this snippet documents the target user-facing API rather than something external consumers can run today.
pnpm add radcn # intended future package
import { Button } from 'radcn/button'Theming
RadCN tokens read the resolved theme from the document. Store the user's preference separately, then resolve system preferences to a concrete light or dark theme before setting package tokens.
<html data-radcn-theme-mode="system" data-radcn-theme="dark">
...
</html>Accessibility
- Renders a native button by default, preserving keyboard and form behavior without client JavaScript.
- Renders an anchor when href is provided, so link semantics remain real links.
- Icon-only buttons can use ariaLabel to provide an accessible name while the icon stays decorative.
- Supports disabled and aria-disabled states for unavailable actions.
Customization
- The component is styled through RadCN CSS variables such as --radcn-primary, --radcn-radius, and --radcn-control-height.
- Variants and sizes are expressed as data attributes and class names so app-level CSS can extend the visual system.
- Loading buttons are plain composition: render a disabled Button with a nested Spinner.
Remix 3 Notes
- The Remix 3 port does not wrap React components. It returns host elements from remix/ui and keeps behavior close to the platform.
- shadcn/ui asChild maps to the explicit href prop in RadCN, avoiding React Slot while preserving link semantics.
- Composition favors explicit props and package imports instead of a generated component copy inside the consuming app.
