Button

Trigger actions with variants, sizes, and asChild.

Installation

npm install @aspyn-io/kit @aspyn-io/tokens
import { Button } from "@aspyn-io/kit";

Variants

Six visual intents. Default is the primary action; use one primary per view.

<Button>Save changes</Button>
<Button variant="secondary">Duplicate</Button>
<Button variant="outline">Export</Button>
<Button variant="ghost">Dismiss</Button>
<Button variant="link">Learn more</Button>
<Button variant="destructive">Delete account</Button>

Sizes

<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>
<Button size="icon" aria-label="Settings">
  <SettingsIcon />
</Button>

As a link (asChild)

Render the button as a Next.js Link (or any element) while keeping styling and focus behavior.

import Link from "next/link";

<Button asChild>
  <Link href="/billing">Manage billing</Link>
</Button>

Loading state

Disable while pending and communicate progress to assistive tech.

<Button disabled aria-busy="true">
  <SpinnerIcon className="animate-spin" />
  Saving…
</Button>

Notes

  • Icon-only buttons require an aria-label.
  • Buttons get cursor:pointer automatically from @aspyn-io/tokens — no per-app fixes needed.
  • Use variant="destructive" only for irreversible actions, paired with a confirmation Dialog.