Visual States

Every interactive element needs clear visual feedback. This documents hover, active, focus, and disabled states.

Cursor Types

Cursor changes indicate interactivity. Use consistent cursors across the system.

pointerClickable elements
defaultNon-interactive
I
textText selection
not-allowedDisabled
Cursor Rulespointer — Buttons, links, clickable cards — Checkboxes, radio buttons — Any actionable element default — Static content, labels — Informational badges — Non-clickable cards text — Text inputs, textareas — Selectable content not-allowed — Disabled buttons — Disabled inputs — Actions that aren't permitted

Button States

Buttons have four states: default, hover, active (pressed), and disabled.

Primary Button

Default
Primary Button StatesDefault background var(--foreground) oklch(0.145 0 0) color var(--background) oklch(1 0 0) cursor pointer Hover background foreground/90% transition 150ms ease Active (pressed) transform scale(0.98) transition 50ms ease Disabled opacity 50% cursor not-allowed pointer-events none

Secondary Button

Default
Secondary Button StatesDefault background transparent border 1px solid foreground/20% color var(--foreground) cursor pointer Hover background foreground/5% border-color foreground/40% transition 150ms ease Active (pressed) transform scale(0.98) transition 50ms ease Disabled opacity 50% cursor not-allowed

Card Hover Effects

Feature cards have a rich hover effect with lift, glow, and shine.

Default State

Static card with border.

Hover State

Lifted with glow border.

Feature Card HoverTransform Effects translateY(-2px) Subtle lift Shadow 0 8px 16px -6px rgba(0,0,0,0.08) Border Glow (::before pseudo-element) Gradient border appears oklch(0.585 0.233 264 / 0.6) → oklch(0.7 0.2 280 / 0.4) Shine Sweep (::after pseudo-element) White gradient sweeps left to right Duration: 600ms Transition Timing transform, box-shadow, border: 400ms ease-out

Input States

Form inputs have default, focus, error, and disabled states.

Please enter a valid email address.

Input StatesDefault background var(--background) border 1px solid var(--border) cursor text Focus border-color var(--accent) box-shadow 0 0 0 3px oklch(0.585 0.233 264 / 0.2) outline none transition all 150ms ease Error border-color var(--destructive) box-shadow 0 0 0 3px oklch(0.577 0.245 27 / 0.1) Disabled background var(--muted) opacity 50% cursor not-allowed

Focus States (Accessibility)

Focus states are essential for keyboard navigation. They should be visible but not intrusive.

Try pressing Tab to navigate through these elements:

Focus Ring Specification:focus-visible outline 2px solid var(--accent) outline-offset 2px :focus:not(:focus-visible) outline none (Hides focus ring for mouse clicks, shows for keyboard) Why focus-visible? — Shows focus ring only for keyboard users — Mouse users don't see focus ring on click — Better UX while maintaining accessibility

Transition Timing Reference

Consistent timing creates a cohesive feel across the interface.

Timing Scale
50mseaseActive/pressed states (instant feedback)
150mseaseHover states, color changes, focus rings
200msease-outCard lift, docs-card hover
400msease-outFeature card hover (emphasis animations)
600mseaseShine sweep, scroll reveal