Customization & Theming
Configure themes, color modes, and visual appearance of your digital garden
Prerequisites:
Theme System
UXLab uses a CSS Zen Garden-style theming system where themes are purely CSS-based with no component changes required. Seven built-in themes are available — click a name below to apply it live:
| Theme | Description | Primary |
|---|---|---|
| Uses app.config colors (primary + neutral) | Neutral (app.config) | |
| Blue/slate shadcn-inspired theme | Blue (~hue 260) | |
| Arctic, north-bluish palette | Cyan-blue (~hue 205) | |
| Dark purple/pink palette | Pink (~hue 320) | |
| Warm pastel colors | Mauve (~hue 295) | |
| Warm, playful carnival colors | Orange (~hue 35) | |
| Teal & citrus coastal palette | Teal (~hue 190) | |
| Cool-gray newsprint with a single teal signal | Teal signal (~hue 205) | |
| Registry gray, one blue, lowercase mono chrome — after npmx | Blue signal (~hue 247) |
Click a theme name to apply it live.
Switching Themes
Three ways to change themes:
- User menu - Click the user menu → Appearance → pick a theme
- Command palette - Press k → Type "theme" → Select theme
- Settings page - Visit
/settingsfor the visual theme picker
Theme Persistence
- Themes persist in
localStorage['uxlab-theme'] - Applied via
document.documentElement.dataset.theme - Works alongside color mode (light/dark/system)
Color Modes
UXLab supports three color modes via @nuxtjs/color-mode:
| Mode | Behavior |
|---|---|
| Light | Force light appearance |
| Dark | Force dark appearance |
| System | Follow OS preference |
Access via the user menu → Appearance, or the Settings page.
Using the Theme Composable
<script setup lang="ts">
const { theme, themes, setTheme, cycleTheme, colorMode } = useTheme()
</script>
<template>
<!-- Current theme ID -->
<p>Current: {{ theme }}</p>
<!-- Theme selector -->
<button
v-for="t in themes"
:key="t.id"
@click="setTheme(t.id)"
>
{{ t.label }}
</button>
<!-- Cycle through themes -->
<button @click="cycleTheme()">Next Theme</button>
</template>
Composable API
| Property | Type | Description |
|---|---|---|
theme | Ref<ThemeId> | Current theme ID |
themes | ThemeConfig[] | All available themes |
currentTheme | ComputedRef<ThemeConfig> | Current theme config |
setTheme(id) | (ThemeId) => void | Set theme by ID |
cycleTheme() | () => void | Rotate to next theme |
colorMode | ColorMode | Access to color mode |
CSS Variables
Each theme defines these CSS custom properties:
Backgrounds
--ui-bg /* Main background */
--ui-bg-elevated /* Cards, elevated surfaces */
--ui-bg-muted /* Subtle backgrounds */
--ui-bg-accented /* Highlighted areas */
--ui-bg-inverted /* Inverted (dark on light, light on dark) */
Text Colors
--ui-text /* Default text */
--ui-text-muted /* Secondary text */
--ui-text-dimmed /* Tertiary/disabled text */
--ui-text-highlighted /* Emphasized text */
--ui-text-inverted /* Text on inverted backgrounds */
Borders
--ui-border /* Default borders */
--ui-border-muted /* Subtle borders */
--ui-border-accented /* Emphasized borders */
--ui-border-inverted /* Borders on inverted surfaces */
Primary Color Scale
--color-primary-50 /* Lightest */
--color-primary-100
--color-primary-200
--color-primary-300
--color-primary-400
--color-primary-500 /* Base */
--color-primary-600
--color-primary-700
--color-primary-800
--color-primary-900
--color-primary-950 /* Darkest */
Chart Colors
--color-chart-1 /* Data visualization color 1 */
--color-chart-2
--color-chart-3
--color-chart-4
--color-chart-5
Creating Custom Themes
Create a new CSS file in app/assets/css/themes/:
/* app/assets/css/themes/my-theme.css */
:root[data-theme="my-theme"] {
--ui-bg: oklch(0.98 0.01 200);
--ui-text: oklch(0.2 0.02 200);
/* ... other light mode variables */
--color-primary-500: oklch(0.6 0.2 200);
/* ... other primary scale values */
}
.dark[data-theme="my-theme"] {
--ui-bg: oklch(0.15 0.02 200);
--ui-text: oklch(0.95 0.01 200);
/* ... other dark mode variables */
}
Then register it:
- Import in
app/assets/css/themes/index.css:
@import "./my-theme.css";
- Add to
app/composables/use-theme.ts:
export const themes: ThemeConfig[] = [
// ... existing themes
{
id: 'my-theme',
label: 'My Theme',
icon: 'i-tabler-star',
description: 'My custom theme',
},
]
- Update
shared/types/theme.ts:
export type ThemeId = 'system' | 'lyra' | 'nord' | 'dracula' | 'catppuccin' | 'carnival' | 'reef' | 'broadsheet' | 'manifest' | 'my-theme'
Component Catalog
Access the component catalog to preview UI components with the active theme:
- Open user menu (bottom of sidebar)
- Click "Component Catalog"
- Browse components by category
- Use quick theme switch at the top
Categories include:
- Layout - Container, Card, Divider, Skeleton
- Forms - Button, Input, Textarea, Select, Checkbox, Radio, Switch
- Data Display - Table, Badge, Avatar, Icon, Progress
- Navigation - NavigationMenu, Tabs, Breadcrumb, Pagination
- Overlay - Modal, Slideover, DropdownMenu, Tooltip, Popover
- Custom - TechBadge, WorldClock, TimelineEventCard
Design Tokens
Font
JetBrains Mono Variable is used throughout:
--font-sans: 'JetBrains Mono Variable', monospace;
Border Radius
Sharp corners by default:
--ui-radius: 0;
To enable rounded corners, modify app/assets/css/main.css:
:root {
--ui-radius: 0.375rem; /* or your preferred value */
}
File Locations
| File | Purpose |
|---|---|
app/assets/css/main.css | Base styles, imports themes |
app/assets/css/themes/ | Theme CSS files |
app/composables/use-theme.ts | Theme composable |
shared/types/theme.ts | Type definitions |
app/pages/settings.vue | Settings page UI |
app/components/component-catalog.vue | Component browser |
app.config.ts | Nuxt UI color configuration |