Expressive

One color. A whole design system.

Expressive brings Material 3 Expressive's color, motion and shape to React and Tailwind CSS, as components you copy into your app and own. Turn the dial: everything here is generated from that one seed.

$ npx expressive init
Seed color#6750A4

Drag the ring, or use the arrow keys. Scheme: expressive.

Morning mix

Volume 64

Every role, from one seed

Google's Material color algorithm turns your seed into five tonal palettes, then assigns each color role in light and dark. Contrast between a role and its on-role is built in.

primary
secondary
tertiary
neutral
neutralVariant
primarytext: on-primary
primary-containertext: on-primary-container
secondarytext: on-secondary
secondary-containertext: on-secondary-container
tertiarytext: on-tertiary
tertiary-containertext: on-tertiary-container
errortext: on-error
error-containertext: on-error-container

Motion that springs

Movement uses Material's spring tokens instead of fixed durations. Same move, two schemes: expressive overshoots, standard settles. It all runs on CSS unless you pick Motion or GSAP.

expressive
standard

Shapes that respond

Corners are tokens, and they move. Press and hold a shape: it springs toward square, the way Expressive buttons do.

The code is yours

The CLI copies each component's source into your project and rewrites imports to your paths. No package to upgrade around, nothing hidden in node_modules.

npx expressive init
npx expressive add button dialog
npx expressive theme --seed "#0B57D0"
npx expressive diff button
your project
src/
├── components/expressive/
│   ├── button.tsx
│   └── dialog.tsx
└── lib/expressive/
    ├── adapters/
    └── tokens/
        ├── colors.ts
        └── motion.ts
See them all
Button
Checkbox

Start with one command.

Needs React 19 and Tailwind CSS v4. Works with Next.js, Vite, React Router, TanStack Start and Astro.