Klarhimmel UI

Button

Stable

Triggers an action. Five variants, three sizes, a 44 pixel hit area at every size.

npx shadcn add @klarhimmel/button

When 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

PropTypeDefaultDescription
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.
iconReactNode-Icon before the label.
iconEndReactNode-Icon after the label.
fullbooleanfalseStretch to the container width.
asChildbooleanfalseStyle the single child (an <a>, a router Link) instead of rendering a <button>.
classNamestring-Extra classes, merged after the component's own.

Accessibility

KeyDoes
Enter / SpaceActivates the button
TabMoves focus; the ring is always visible

An icon-only button needs an aria-label.

Accessibility