Skip to content
Get Started

Component demo // Buttons

Structure, state layers and micro-feedback in pure CSS.

Velora buttons encode hover, active, disabled and focus-visible states with tokens for border radius, shadow glow and scale—no JavaScript event listeners needed.

States Default → Hover → Active → Focus
Motion Scale + shadow micro-feedback
Accessibility 44px targets & visible focus ring
Token-driven Zero JS WCAG AA

Act I // State layers

Default, hover, active, disabled and focus-visible—all from tokens.

Each state maps to a surface token, a border token and an optional shadow token. Swap the theme and every button state recolors automatically.

Default --vl-btn-bg Primary surface + high-contrast text
Hover --vl-btn-bg-hover Lighter tonal tier + shadow glow
Active --vl-btn-bg-active Darker tier + scale(0.97)
Disabled --vl-btn-bg-disabled Muted surface + reduced opacity
.vl-btn--primary {
  background: var(--vl-btn-bg);
  color: var(--vl-btn-text);
}
.vl-btn--primary:hover   { background: var(--vl-btn-bg-hover); }
.vl-btn--primary:active  { background: var(--vl-btn-bg-active); transform: scale(0.97); }
.vl-btn--primary:disabled { background: var(--vl-btn-bg-disabled); opacity: 0.5; }

Each state maps to a dedicated token. Swap the theme and every button state recolors in one pass — no overrides needed.

Act II // Micro-feedback

Subtle scale and shadow transitions give tactile feedback on every interaction.

Hover grows the shadow and lifts the button. Press shrinks it. The entire animation runs on transform and box-shadow—GPU composited, 120fps.

button motion tokens .vl-btn { transition: transform 180ms var(--vl-ease-out), box-shadow 180ms var(--vl-ease-out); } .vl-btn:hover { scale: 1.02; } .vl-btn:active { scale: 0.97; }
Rule

Transform + shadow only.

Never animate width, height, padding or margin on interactive elements.

Act III // Accessible targets

44px minimum touch target and a visible focus ring on every button.

Focus-visible outlines use --vl-focus-ring for consistent styling. Disabled buttons get aria-disabled instead of the disabled attribute when they need to stay in tab order.

min-height: 44px focus-visible ring AA contrast
Touch target 44 × 44px minimum clickable area
Focus ring 2px offset outline on :focus-visible
Contrast 4.5:1 text on button surface

Act IV // Applied buttons

States, motion and accessibility: three layers for every button.

Map each state to a token, animate only transform and shadow, then enforce 44px targets with visible focus rings.

States Default, hover, active, disabled and focus from token pairs.
Motion Scale + shadow micro-feedback at 120fps.
Accessibility 44px targets, focus-visible ring, AA contrast.
Theming Swap the palette and every state recolors automatically.