Expressive

Getting started

Introduction

Expressive brings Material 3 Expressive's color, motion, shape and type systems to React and Tailwind CSS, as source code you copy into your app and own.

Most component libraries ship as a package: you install it, import from it, and work around it when it doesn't do what you need. Expressive works the other way, like shadcn/ui. A CLI writes the component source into your project. From then on it's your code, and you change it the way you'd change anything else you wrote.

What Expressive adds is a design system underneath: every component reads semantic tokens instead of raw values. Change the seed color, the font or the motion scheme, and everything follows.

What you get

  • Tokens for color, typography, shape, motion, elevation, spacing and interaction, written into lib/expressive/tokens.
  • A color scheme from one seed color, generated with Google's Material color algorithm, in light and dark.
  • A motion layer built on Material's spring tokens. It runs on plain CSS by default, or on Motion or GSAP.
  • 19 components built on Base UI for keyboard, focus and screen reader behavior.
  • A Tailwind v4 bridge, so tokens are ordinary utilities: bg-primary, text-title-large, rounded-shape-large.

How it fits together

src/
├── app/
│   ├── globals.css          # @import "tailwindcss"; @import "./expressive.css"; + your theme
│   └── expressive.css       # tokens → Tailwind utilities
├── components/expressive/   # button.tsx, dialog.tsx, …  (yours to edit)
└── lib/expressive/
    ├── utils.ts, spring.ts, use-motion.ts, adapters/
    └── tokens/              # colors.ts, motion.ts, shape.ts, theme.ts, …

expressive init sets up the tokens, the stylesheet and your theme once. expressive add copies components in. The theme itself is plain CSS variables in your global stylesheet, generated from your seed color.

Next steps