Lesson 1 — Design tokens with @theme
What are design tokens?
Design tokens are named values that represent design decisions — colours,
spacing, typography, border radii. Rather than hardcoding #2563eb
throughout your codebase, you name it primary and reference that name
everywhere. The value lives in one place; everything else references
the name.
Tailwind v4 and @theme
In Tailwind v4, design tokens are defined directly in CSS using the
@theme directive. Every variable defined inside @theme automatically
becomes a Tailwind utility class.
|
|
Once defined, Tailwind generates utility classes for every token:
--color-primary → bg-primary, text-primary, border-primary
--color-primary-hover → bg-primary-hover, text-primary-hover
--color-surface → bg-surface, text-surfaceYou use these exactly like standard Tailwind classes:
|
|
Why semantic names matter
bg-blue-600 is a palette value — it describes what the colour looks
like. bg-primary is a semantic value — it describes what the colour
means. This distinction becomes critical when:
- You want dark mode:
bg-blue-600in dark mode looks wrong;bg-primarycan be redefined to something appropriate for dark backgrounds - You want multiple themes: swap the token values and everything repaints
- You want to rebrand: change
--color-primaryonce and every button, link, and badge updates
Typography tokens
Add font and type scale tokens alongside the colour tokens:
|
|
Loading Inter
Add the Inter font via a Google Fonts import at the top of
application.css, before the @import "tailwindcss" line:
|
|
Exercise
Add the full token set above to app/assets/tailwind/application.css and run bin/dev.
Note on how Tailwind v4 generates utilities: Unlike Tailwind v3 which generated all possible utility classes upfront, Tailwind v4 scans your source files and only generates classes that are actually used. This means bg-primary and text-text-muted won’t appear in the compiled CSS until a view or component references them.
To verify your tokens are working, add a temporary test element to any view:
|
|
Run bin/dev, visit the page, and confirm the elements render with the correct colours. Then check app/assets/builds/tailwind.css and search for .bg-primary — it should appear with background-color: #2563eb.
Once verified, remove the test elements. The tokens are working correctly even if they don’t appear in the compiled CSS without a corresponding class reference.