ui
Eased is a library of motion-first React components for shadcn, installed with the shadcn CLI.
The colours, shadows, radius roles, UI type sizes, springs, utilities (radius-nested, hit-area, focus-ring …) and variants (hover-fine, reduced) every Eased component reads. Installs into your global CSS without touching shadcn/ui's theme or Tailwind's defaults: every raw variable is prefixed --eased-, light follows :root, dark follows .dark.
The named springs (snappy, smooth, bouncy), tweens, a hydration-safe useSafeReducedMotion and press classes every Eased component shares, matching the springs in the Eased stylesheet, plus small DOM and platform helpers (isEditable, useScrollFades, useIsMac) and a true-minus number formatter.
The shell every Eased demo renders in: 420px tall, shrinks to its container, one 48px header style.
An animated undo pill for React and shadcn, with a countdown ring that commits the action only when it runs out.
A file list where deleting a row shows the Undo Pill.
A layout frame for React and shadcn that keeps nested corner radii concentric through CSS variables.
Demo for Concentric Frame.
A billing FAQ with answers of different lengths.
An animated accordion for React and shadcn, built on Base UI Accordion.
A members card: a stacked group with a rolling +N, a list with photos, initials and a failed image, and Invite.
An animated avatar for React and shadcn, with groups that spread apart on hover.
A mail sidebar with rolling unread counts (98 → 99+) and service status badges with a live dot.
An animated badge for React and shadcn, for statuses and counts, with an optional live dot.
An invoice with Send (loading, then “Sent”), Download and a two-step Void.
An animated button for React and shadcn, with a loading state that keeps its width.
The height:auto spring primitive: a wrapper whose height springs to its content, opens and closes with the content fading in after the height lands, and rests at height:auto with no clipping.
Label, description ⇄ error message slot and the bordered input group, on Base UI Field. Focus is the border alone; turning invalid shakes the group once, 6px, and the message swaps with y + blur while its height springs.
One popover per side; each enters toward its trigger and flips on collision.
The motion and material every Eased popup shares: grows from the trigger's transform-origin, enters a few pixels toward the trigger, closes at half the distance and faster, and reverses mid-flight because open and close are transitions. FloatingLayer renders any Base UI popup family (Tooltip, Popover, PreviewCard, Menu) with it.
A three-detent sheet over a map: flicks project onto detents, pulls past the top rubber-band, and the list hands its scroll over to the sheet.