Primitive

Button

The Button primitive — 6 variants × 4 sizes. Mirrors the shadcn/ui Button surface so muscle memory translates 1:1. Used inside ShadNG components and freely composable in your own UI.

Preview — variants

Preview — sizes

Installation

bash
npm install @shadng/core

Usage

typescript
import { Component } from '@angular/core';
import { Button } from '@shadng/core';

@Component({
  selector: 'app-search-bar',
  imports: [Button],
  template: `
    <ai-button
      variant="default"
      size="default"
      (pressedChange)="onClick()"
    >
      Search
    </ai-button>

    <ai-button
      variant="destructive"
      (pressedChange)="onDelete()"
    >
      Delete
    </ai-button>

    <ai-button
      variant="outline"
      size="icon"
      ariaLabel="Toggle theme"
      [pressed]="isDark()"
      (pressedChange)="toggleTheme()"
    >
      <svg><!-- icon --></svg>
    </ai-button>
  `,
})
export class SearchBar {
  onClick() { /* ... */ }
  onDelete() { /* ... */ }
}

API — Inputs

NameTypeDefaultDescription
variant'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link''default'Visual treatment.
size'default' | 'sm' | 'lg' | 'icon''default'Size class. Use icon for icon-only buttons (square).
type'button' | 'submit' | 'reset''button'Native button type. Stays as button by default to avoid accidental form submissions.
disabledbooleanfalseDisable the button.
pressedboolean | nullnullToggle state. null means not a toggle (no aria-pressed emitted).
ariaLabelstring''Accessible name. Required for icon-only buttons.
titlestring''Native HTML title tooltip.

API — Outputs

NameTypeDescription
pressedChangeMouseEventFires on click. Carries the native MouseEvent in case modifier keys matter.

Variants

NameTypeDescription
defaultvariantPrimary CTA. Solid background using --primary.
destructivevariantDangerous actions (delete, remove). Uses --destructive.
outlinevariantBordered, transparent fill. Secondary actions where presence is needed but not bold.
secondaryvariantSoft alternative to default. Uses --secondary.
ghostvariantNo background at rest, accent on hover. Use in toolbars or compact layouts.
linkvariantRenders like an underlined link. Use for inline navigation actions.

Sizes

NameTypeDescription
defaultsize36px high (h-9), text-sm. The standard for most buttons.
smsize32px high (h-8), text-xs. Compact rows.
lgsize40px high (h-10). Heroes and primary CTAs.
iconsize36px square. Icon-only buttons. Pair with ariaLabel.

Accessibility

  • Native <button> under the hood — full keyboard support out of the box (Tab, Enter, Space).
  • ariaLabel recommended for icon-only buttons (size icon) — required by AT for context.
  • pressed input toggles aria-pressed for toggle-button semantics (null = not a toggle).
  • Focus ring uses the --ring semantic token, with offset against --background.
  • Touch targets: default/icon = 36px, sm = 32px, lg = 40px — meets WCAG 2.2 SC 2.5.8.

Theming

Semantic tokens consumed per variant:

  • default--primary / --primary-foreground
  • destructive--destructive / --destructive-foreground
  • outline--input (border) + --background + hover --accent
  • secondary--secondary / --secondary-foreground
  • ghost — transparent + hover --accent
  • link--primary as text color
MIT © Kalvnerv0.1.0 · pre-release