Theming
Customize Suite.jl's visual appearance with built-in themes and fine-grained overrides.
How Themes Work
A theme is a named bundle of design tokens — accent color, border radius, font weight, shadow style, and more. Every Suite.jl component accepts a theme keyword argument.
When theme=:default (the default), there is zero overhead — the component renders its standard classes unchanged.
Pre-built Themes
Suite.jl ships with 5 pre-built themes:
| Theme | Accent | Neutral | Radius | Description |
|---|---|---|---|---|
| :default | Purple | Warm | rounded-md | Classic scholarly tones |
| :ocean | Blue | Warm | rounded-lg | Cool professional |
| :minimal | Zinc | Slate | rounded-none | Sharp monospace-friendly |
| :nature | Emerald | Stone | rounded-xl | Organic earthy tones |
| :islands | Blue | Warm | rounded-xl | Floating glass panels, generous curves |
Applying Themes
At render time
Pass the theme kwarg to any component:
# Default theme (purple accent, warm neutrals, rounded-md)
Button("Default Theme")
# Ocean theme (blue accent, rounded-lg)
Button(theme=:ocean, "Ocean Theme")
# Minimal theme (zinc accent, no border radius)
Button(theme=:minimal, variant="outline", "Minimal Theme")
# Nature theme (emerald accent, rounded-xl)
Card(theme=:nature,
CardHeader(CardTitle("Nature Theme")),
CardContent("Emerald accents with stone neutrals")
)
# Islands theme (blue accent, glass panels, rounded-xl)
Card(theme=:islands,
CardHeader(CardTitle("Islands Theme")),
CardContent("Blue accents with glass-panel effects")
)At extraction time
When extracting components, the theme is baked into the generated source code. The output file contains concrete Tailwind classes — no runtime theme lookup needed:
# Extract with ocean theme
Suite.extract(:Button, "src/components/", theme=:ocean)
# → Button.jl uses bg-blue-600 instead of bg-accent-600
# Extract with nature theme
Suite.extract(:Card, "src/components/", theme=:nature)
# → Card.jl uses rounded-xl, stone-* neutrals, emerald-* accents
# (each theme substitutes its own color tokens)Design Tokens
Each theme defines these tokens, which are substituted into component class strings:
| Token | Default | Ocean | Description |
|---|---|---|---|
| accent | purple (accent-*) | blue | Primary interactive color |
| accent_secondary | red (accent-secondary-*) | rose | Destructive/danger color |
| neutral | warm | warm | Background, border, text colors |
| radius | rounded-md | rounded-lg | Default border radius |
| ring | ring-accent-600 | ring-blue-600 | Focus ring color |
| font_weight | font-medium | font-medium | Default font weight |
| shadow | shadow-sm | shadow-md | Default shadow |
Color Token Mapping
Suite.jl maps shadcn/ui's CSS variables to Tailwind utility classes:
| shadcn Variable | Suite.jl Token |
|---|---|
| --background | bg-warm-50 dark:bg-warm-950 |
| --foreground | text-warm-800 dark:text-warm-300 |
| --primary | bg-accent-600 / text-accent-600 |
| --card | bg-warm-100 dark:bg-warm-900 |
| --border | border-warm-200 dark:border-warm-700 |
| --destructive | bg-accent-secondary-600 / text-accent-secondary-600 |
| --ring | ring-accent-600 |
Dark Mode
Every Suite.jl component includes dark mode classes out of the box. Dark mode is toggled by adding the dark class to the <html> element.
Use the ThemeToggle component to add a dark mode toggle to your app:
# In your Layout.jl navbar
ThemeToggle() # Sun/moon toggle button
# Persists preference to localStorage
# Respects system prefers-color-scheme as defaultTherapy.jl's App framework includes a FOUC-prevention script in <head> that applies the saved theme before first paint.
Warm Neutral Palette
The default theme uses a warm neutral palette shared across all GroupTherapyOrg packages: