Core Primitives Tailwind v4 Pure HTML5 Zero-JS
Button
Interactive button primitives with rich visual variants, loading spinners, icons, and keyboard accessibility.
Interactive Preview
Live Edit & Viewport Resizer Variants:
Installation
Add the Button component to your project via CLI:
terminal bash
npx plain-ui add button Features
- ✓ Semantic HTML <button> and <a> support
- ✓ 6 visual styles: Primary, Secondary, Outline, Ghost, Destructive, Link
- ✓ 4 size presets: sm, md, lg, icon
- ✓ Accessible focus rings, active scaling, disabled states
- ✓ Loading state with animated inline SVG spinner
Variants & Examples
Standard Styles
All core visual styles and hierarchy presets.
button-standard-styles.html html
<div class="flex flex-wrap items-center justify-center gap-4">
<button class="px-4 py-2 text-sm font-medium text-white bg-zinc-900 dark:bg-zinc-100 dark:text-zinc-900 rounded-lg hover:bg-zinc-800 dark:hover:bg-zinc-200 active:scale-95 transition-all shadow-sm cursor-pointer">Primary</button>
<button class="px-4 py-2 text-sm font-medium text-zinc-800 bg-zinc-100 dark:bg-zinc-800 dark:text-zinc-200 rounded-lg hover:bg-zinc-200 dark:hover:bg-zinc-700 active:scale-95 transition-all cursor-pointer">Secondary</button>
<button class="px-4 py-2 text-sm font-medium text-zinc-800 dark:text-zinc-200 border border-zinc-300 dark:border-zinc-700 rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 active:scale-95 transition-all cursor-pointer">Outline</button>
<button class="px-4 py-2 text-sm font-medium text-zinc-600 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-zinc-100 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg transition-all cursor-pointer">Ghost</button>
<button class="px-4 py-2 text-sm font-medium text-red-600 bg-red-50 hover:bg-red-100 dark:bg-red-950/40 dark:hover:bg-red-900/40 dark:text-red-400 rounded-lg active:scale-95 transition-all cursor-pointer">Soft Destructive</button>
<button class="text-sm font-medium text-blue-600 dark:text-blue-400 underline-offset-4 hover:underline cursor-pointer">Link Button</button>
</div> Sizes & Loading
Compact small, medium, large sizes, plus loading spinner and disabled state.
button-sizes-&-loading.html html
<div class="flex flex-wrap items-center justify-center gap-4">
<!-- Small -->
<button class="px-2.5 py-1.5 text-xs font-medium bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900 rounded-md cursor-pointer">Small</button>
<!-- Medium -->
<button class="px-4 py-2 text-sm font-medium bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900 rounded-lg cursor-pointer">Medium</button>
<!-- Large -->
<button class="px-6 py-3 text-base font-semibold bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900 rounded-xl cursor-pointer">Large</button>
<!-- Loading State -->
<button disabled class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900 rounded-lg opacity-75 cursor-wait">
<svg class="w-4 h-4 animate-spin" viewBox="0 0 24 24" fill="none">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"></path>
</svg>
Processing...
</button>
<!-- Disabled -->
<button disabled class="px-4 py-2 text-sm font-medium bg-zinc-200 text-zinc-400 dark:bg-zinc-800 dark:text-zinc-600 rounded-lg cursor-not-allowed">Disabled</button>
</div> With Icons
Buttons with leading icons, trailing arrows, and icon-only floating buttons.
button-with-icons.html html
<div class="flex flex-wrap items-center justify-center gap-4">
<button class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900 rounded-lg hover:bg-zinc-800 shadow-sm cursor-pointer">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
New Project
</button>
<button class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-blue-600 text-white hover:bg-blue-700 rounded-lg shadow-sm transition-all cursor-pointer">
Continue
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"/></svg>
</button>
<button aria-label="Bookmark" class="p-2.5 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 transition-all cursor-pointer">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z"/></svg>
</button>
</div> Attributes & Classes
| Attribute / Prop | Type | Default | Description |
|---|---|---|---|
| type | button | submit | reset | button | Semantic HTML button type. |
| disabled | boolean | false | Disables button interactions and reduces opacity. |
| aria-label | string | - | Required for icon-only buttons for screen reader access. |
Accessibility & Keyboard Navigation
- • Uses native <button> elements with full keyboard activation via Space and Enter.
- • Always provide an aria-label when rendering icon-only buttons.
- • Focus rings use focus-visible:ring-2 to preserve keyboard navigation clarity without mouse clutter.