- Components
Button
Triggers an action. Five variants, three sizes, a 44 pixel hit area at every size.
npx shadcn add @klarhimmel/buttonWhen to use
Use for
Saving, sending, confirming a step. One primary button per view.
Not for
Going to another page. Use Button link or Text link.
Pairs with
Field, Card, Copy button.
Preview
button.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { Button } from '@/components/klarhimmel/ui/button';
export default function Example() {
return (
<Theme theme="brand">
<div className="flex gap-3">
<Button>Save changes</Button>
<Button variant="secondary">Cancel</Button>
</div>
</Theme>
);
}Install
Import
import { Button } from '@/components/klarhimmel/ui/button';- Lands in
- components/klarhimmel/ui/button.tsx, plus cn() and the theme item if they are missing. Import theme.css after Tailwind.
- Render in
- Render it inside <Theme>, once near the root of your app. Tokens and fonts are scoped to it, so outside it the component is unstyled.
Examples
Sizes
import { Button } from '@/components/klarhimmel/ui/button'; export default function ButtonSizes() { return ( <div className="flex flex-wrap items-center gap-3"> <Button size="sm">Small</Button> <Button size="md">Medium</Button> <Button size="lg">Large</Button> </div> ); }States
import { Button } from '@/components/klarhimmel/ui/button'; export default function ButtonStates() { return ( <div className="flex flex-wrap items-center gap-3"> <Button>Default</Button> <Button variant="secondary">Default</Button> <Button disabled>Disabled</Button> <Button variant="secondary" disabled>Disabled</Button> </div> ); }With icon
import { ArrowRight, Download, Plus } from 'lucide-react'; import { Button } from '@/components/klarhimmel/ui/button'; export default function ButtonWithIcon() { return ( <div className="flex flex-wrap items-center gap-3"> <Button icon={<Plus aria-hidden className="size-4" />}>New project</Button> <Button variant="secondary" icon={<Download aria-hidden className="size-4" />}>Download</Button> <Button variant="ghost" iconEnd={<ArrowRight aria-hidden className="size-4" />}>Continue</Button> </div> ); }As child
import { Button } from '@/components/klarhimmel/ui/button'; /** Composition: Button styles the child it wraps, here a link, so navigation stays a real <a>. */ export default function ButtonAsChild() { return ( <div className="flex flex-wrap items-center gap-3"> <Button asChild> <a href="#docs">Read the docs</a> </Button> <Button asChild variant="secondary"> <a href="#changelog">View changelog</a> </Button> </div> ); }
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'secondary' | 'ghost' | 'accent' | 'soft' | 'primary' | Visual style. Primary is ink on canvas, so it reads on every tone. |
size | 'sm' | 'md' | 'lg' | 'md' | Height and padding. The hit area stays 44 px. |
icon | ReactNode | - | Icon before the label. |
iconEnd | ReactNode | - | Icon after the label. |
full | boolean | false | Stretch to the container width. |
asChild | boolean | false | Style the single child (an <a>, a router Link) instead of rendering a <button>. |
className | string | - | Extra classes, merged after the component's own. |
Accessibility
| Key | Does |
|---|---|
Enter / Space | Activates the button |
Tab | Moves focus; the ring is always visible |
An icon-only button needs an aria-label.
Accessibility