Appearance
@vibe-labs/design-components-buttons
Button component tokens, styles, and TypeScript types for the Vibe Design System.
Installation
bash
npm install @vibe-labs/design-components-buttonscss
@import "@vibe-labs/design-components-buttons";ts
import { ButtonSizes, ButtonVariants, ButtonShapes } from "@vibe-labs/design-components-buttons/types";
import type { ButtonSize, ButtonVariant, ButtonShape, ButtonStyleProps } from "@vibe-labs/design-components-buttons/types";Contents
Tokens
Component-specific tokens defined in @layer vibe.tokens (file: button.css). Core sizing tokens (--btn-height-*, --btn-px-*, --btn-radius, --btn-font-weight, --btn-font-size-*) are owned by @vibe-labs/design-forms.
Variant Tokens
Each variant defines bg, color, border, hover, and active states:
- Primary —
--btn-primary-bg·--btn-primary-color·--btn-primary-border·--btn-primary-hover-bg·--btn-primary-hover-border·--btn-primary-active-bg·--btn-primary-active-border - Secondary —
--btn-secondary-bg·--btn-secondary-color·--btn-secondary-border·--btn-secondary-hover-bg·--btn-secondary-hover-border·--btn-secondary-active-bg - Ghost —
--btn-ghost-color·--btn-ghost-hover-bg·--btn-ghost-active-bg - Danger —
--btn-danger-bg·--btn-danger-color·--btn-danger-border·--btn-danger-hover-bg·--btn-danger-hover-border·--btn-danger-active-bg·--btn-danger-active-border - Link —
--btn-link-color
Other Tokens
| Token | Default | Description |
|---|---|---|
--btn-loading-spinner-width | --spinner-width (2px) | Loading spinner border width |
--btn-spinner-color | --color-accent-contrast | Spinner color |
--btn-group-overlap | --border-width-1 | Negative margin between grouped buttons |
Generated Styles
Component classes generated into @layer vibe.components (file: button.g.css).
Variants
| Variant | Description |
|---|---|
primary | Accent-colored solid button |
secondary | Elevated surface with border |
ghost | Transparent with hover overlay |
danger | Danger-colored solid button |
link | Inline link style, no padding/height |
Sizes
sm · md (default) · lg — sizing tokens from @vibe-labs/design-forms.
Shapes
| Shape | Description |
|---|---|
default | Standard --btn-radius — no data-shape attribute needed |
circle | Full radius (--radius-full) with hover scale(1.1) / active(1.05) |
Shape is set via data-shape attribute. The base transition includes transform so shape animations compose cleanly with variant colour transitions.
States
| State | Description |
|---|---|
disabled | Reduced opacity, cursor: not-allowed, no pointer events (also aria-disabled) |
data-loading | Hides text, shows CSS spinner via ::after pseudo-element |
focus-visible | Ring via box-shadow using --ring-color / --ring-offset-* |
Modifiers
| Modifier | Description |
|---|---|
data-full | width: 100% |
data-icon | Removes horizontal padding, aspect-ratio: 1 |
Button Group
.btn-group — inline flex container that strips inner border radii and overlaps borders between adjacent buttons using --btn-group-overlap.
TypeScript Types
ts
ButtonSizes // ["sm", "md", "lg"]
ButtonVariants // ["primary", "secondary", "ghost", "danger", "link"]
ButtonShapes // ["default", "circle"]
type ButtonSize
type ButtonVariant
type ButtonShape
interface ButtonStyleProps {
variant?: ButtonVariant
size?: ButtonSize
shape?: ButtonShape
loading?: boolean
full?: boolean
icon?: boolean
disabled?: boolean
color?: string
}
interface ButtonGroupStyleProps { label?: string }Dist Structure
| File | Description |
|---|---|
index.css | Barrel — imports tokens + generated styles |
button.css | Token definitions (variant colors, spinner, group) |
button.g.css | Generated component styles |
index.js / index.d.ts | TypeScript types + runtime constants |
Dependencies
Requires @vibe-labs/design-forms (sizing tokens) and @vibe-labs/design (colors, surfaces, transitions, elevation).
Build
bash
npm run buildUsage Guide
Import
css
@import "@vibe-labs/design-components-buttons";ts
import type { ButtonStyleProps } from "@vibe-labs/design-components-buttons/types";Variants
Variant
Set data-variant on .btn: primary · secondary · ghost · danger · link
Size
Set data-size on .btn: sm · md (default) · lg
Shape
Set data-shape on .btn: omit for default rounded · circle for fully circular
Boolean flags
data-loading— hides label, shows CSS spinnerdata-full— full-width (width: 100%)data-icon— square icon button (removes horizontal padding,aspect-ratio: 1)disabledoraria-disabled="true"— disabled state
Examples
All variants
html
<button class="btn" data-variant="primary">Save changes</button>
<button class="btn" data-variant="secondary">Cancel</button>
<button class="btn" data-variant="ghost">Learn more</button>
<button class="btn" data-variant="danger">Delete account</button>
<button class="btn" data-variant="link">View details</button>Sizes
html
<button class="btn" data-variant="primary" data-size="sm">Small</button>
<button class="btn" data-variant="primary">Medium</button>
<button class="btn" data-variant="primary" data-size="lg">Large</button>Loading state
html
<!-- Spinner replaces text content; aria-busy communicates state -->
<button class="btn" data-variant="primary" data-loading aria-busy="true">
Saving…
</button>Icon button (circle shape)
html
<!-- Square icon button -->
<button class="btn" data-variant="ghost" data-icon aria-label="Settings">
<svg><!-- gear icon --></svg>
</button>
<!-- Circular icon button with scale animation on hover -->
<button class="btn" data-variant="primary" data-shape="circle" data-icon aria-label="Add">
<svg><!-- + icon --></svg>
</button>Full-width
html
<button class="btn" data-variant="primary" data-full>Sign in</button>Button group
html
<!-- Adjacent buttons share borders — inner radii are stripped automatically -->
<div class="btn-group" role="group" aria-label="View mode">
<button class="btn" data-variant="secondary" aria-pressed="true">List</button>
<button class="btn" data-variant="secondary">Grid</button>
<button class="btn" data-variant="secondary">Table</button>
</div>With Vue
Use @vibe-labs/design-vue-buttons for <SbBtn> and <SbBtnGroup> which accept ButtonStyleProps and forward all states to the correct data attributes.