Button
A clickable control that triggers an action.
Variants
Different visual styles for different contexts.
<button class="vt-btn vt-btn-primary">
Primary
</button>
<button class="vt-btn vt-btn-secondary">
Secondary
</button>
<button class="vt-btn vt-btn-bordered">
Bordered
</button>
<button class="vt-btn vt-btn-ghost">
Ghost
</button>
<button class="vt-btn vt-btn-danger">
Danger
</button>
<button class="vt-btn vt-btn-link">
Link
</button>
Sizes
Available in small, default, large, and icon sizes.
<button class="vt-btn vt-btn-primary vt-btn-sm">
Small
</button>
<button class="vt-btn vt-btn-primary">
Default
</button>
<button class="vt-btn vt-btn-primary vt-btn-lg">
Large
</button>
<button class="vt-btn vt-btn-primary vt-btn-icon" aria-label="Continue">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-arrow-right vt-w-4 vt-h-4">
<path d="M5 12h14"></path><path d="m12 5 7 7-7 7"></path>
</svg>
</button>
With Icon
Buttons can include leading or trailing icons.
<button class="vt-btn vt-btn-primary">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-upload vt-w-4 vt-h-4">
<path d="M12 3v12"></path><path d="m17 8-5-5-5 5"></path><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
</svg>
Upload
</button>
<button class="vt-btn vt-btn-bordered">
Next
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-chevron-right vt-w-4 vt-h-4">
<path d="m9 18 6-6-6-6"></path>
</svg>
</button>
<button class="vt-btn vt-btn-primary">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-mail vt-w-4 vt-h-4">
<path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path><rect x="2" y="4" width="20" height="16" rx="2"></rect>
</svg>
Send Email
</button>
States
Disabled and loading states.
<button class="vt-btn vt-btn-primary" disabled="">
Disabled
</button>
<button disabled="" class="vt-btn vt-btn-primary vt-opacity-80 vt-cursor-wait">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-w-4 vt-h-4 vt-animate-spin">
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
</svg>
Loading...
</button>
<button class="vt-btn vt-btn-bordered" disabled="">
Disabled
</button>
Full Width
Button that stretches to fill its container.
<button class="vt-btn vt-btn-primary vt-w-full">
Sign In
</button>
<button class="vt-btn vt-btn-bordered vt-w-full">
Create Account
</button>
Icon Only
Buttons that contain only an icon, used for compact actions and toolbars.
Primary
Secondary
Bordered
Ghost
Danger
<div class="vt-text-center">
<button class="vt-btn vt-btn-primary vt-btn-icon" aria-label="Edit">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-pencil vt-w-4 vt-h-4">
<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"></path><path d="m15 5 4 4"></path>
</svg>
</button>
<p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Primary</p>
</div>
<div class="vt-text-center">
<button class="vt-btn vt-btn-secondary vt-btn-icon" aria-label="Edit">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-pencil vt-w-4 vt-h-4">
<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"></path><path d="m15 5 4 4"></path>
</svg>
</button>
<p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Secondary</p>
</div>
<div class="vt-text-center">
<button class="vt-btn vt-btn-bordered vt-btn-icon" aria-label="Edit">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-pencil vt-w-4 vt-h-4">
<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"></path><path d="m15 5 4 4"></path>
</svg>
</button>
<p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Bordered</p>
</div>
<div class="vt-text-center">
<button class="vt-btn vt-btn-ghost vt-btn-icon" aria-label="Edit">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-pencil vt-w-4 vt-h-4">
<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"></path><path d="m15 5 4 4"></path>
</svg>
</button>
<p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Ghost</p>
</div>
<div class="vt-text-center">
<button class="vt-btn vt-btn-danger vt-btn-icon" aria-label="Delete">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-trash-2 vt-w-4 vt-h-4">
<path d="M10 11v6"></path><path d="M14 11v6"></path><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"></path><path d="M3 6h18"></path><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</button>
<p class="vt-text-xs vt-text-foreground-muted vt-mt-2">Danger</p>
</div>
Icon Rounded
Circle icon buttons using rounded-full.
<button class="vt-btn vt-btn-primary vt-btn-icon vt-rounded-full" aria-label="Add">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-4 vt-h-4">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
<button class="vt-btn vt-btn-secondary vt-btn-icon vt-rounded-full" aria-label="Like">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-heart vt-w-4 vt-h-4">
<path d="M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5"></path>
</svg>
</button>
<button class="vt-btn vt-btn-bordered vt-btn-icon vt-rounded-full" aria-label="Share">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-share-2 vt-w-4 vt-h-4">
<circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" x2="15.42" y1="13.51" y2="17.49"></line><line x1="15.41" x2="8.59" y1="6.51" y2="10.49"></line>
</svg>
</button>
<button class="vt-btn vt-btn-ghost vt-btn-icon vt-rounded-full" aria-label="More options">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-ellipsis vt-w-4 vt-h-4">
<circle cx="12" cy="12" r="1"></circle><circle cx="19" cy="12" r="1"></circle><circle cx="5" cy="12" r="1"></circle>
</svg>
</button>
Icon Sizes
Icon buttons in small, default, and large sizes.
sm
md
lg
<div class="vt-text-center">
<button class="vt-btn vt-btn-primary vt-btn-icon vt-btn-sm" aria-label="Add">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-3.5 vt-h-3.5">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
<p class="vt-text-xs vt-text-foreground-muted vt-mt-2">sm</p>
</div>
<div class="vt-text-center">
<button class="vt-btn vt-btn-primary vt-btn-icon" aria-label="Add">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-4 vt-h-4">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
<p class="vt-text-xs vt-text-foreground-muted vt-mt-2">md</p>
</div>
<div class="vt-text-center">
<button class="vt-btn vt-btn-primary vt-btn-icon vt-btn-lg" aria-label="Add">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-plus vt-w-5 vt-h-5">
<path d="M5 12h14"></path><path d="M12 5v14"></path>
</svg>
</button>
<p class="vt-text-xs vt-text-foreground-muted vt-mt-2">lg</p>
</div>
Guidelines
Reach for a button for any clickable action, including low-emphasis text actions. Keep one primary button per view — secondary actions use bordered or ghost. Don't use a button for inline navigation inside text; use a link instead.
Read our documentation to get started.
Read our to get started.
API Reference
All CSS classes available for the Button component.
| Class | Type | Description |
|---|---|---|
vt-btn |
Base | Base button styles — flex, rounded, font, transition |
vt-btn-primary |
Variant | Blue fill, white text — primary actions |
vt-btn-secondary |
Variant | Muted fill — secondary actions |
vt-btn-bordered |
Variant | Outline only, no fill |
vt-btn-danger |
Variant | Red fill — destructive actions |
vt-btn-link |
Variant | Looks like a link — underline on hover |
vt-btn-ghost |
Variant | Transparent, subtle hover background |
vt-btn-sm |
Size | Small button (32px height, text-xs) |
vt-btn-lg |
Size | Large button (44px height, text-base) |
vt-btn-icon |
Modifier | Square aspect ratio for icon-only buttons |
disabled |
State | HTML attribute — reduced opacity, no pointer events |
Accessibility
Keyboard and screen reader support.
| Feature | Details |
|---|---|
| Role | Use <button> for actions, <a> for navigation |
| Keyboard | Enter and Space activate the button |
| Focus | Visible focus ring via :focus-visible |
| Disabled | Use disabled attribute — removes from tab order automatically |
| Icon-only | Add aria-label to describe the action when there is no visible text |