Guides
Guides Customization & Theming

Customization & Theming

Configure themes, color modes, and visual appearance of your digital garden

CustomizationBeginner

Prerequisites:

getting-started
ThemingCustomizationCSSDesign

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 themeBlue (~hue 260)
Arctic, north-bluish paletteCyan-blue (~hue 205)
Dark purple/pink palettePink (~hue 320)
Warm pastel colorsMauve (~hue 295)
Warm, playful carnival colorsOrange (~hue 35)
Teal & citrus coastal paletteTeal (~hue 190)
Cool-gray newsprint with a single teal signalTeal signal (~hue 205)
Registry gray, one blue, lowercase mono chrome — after npmxBlue signal (~hue 247)

Click a theme name to apply it live.

Switching Themes

Three ways to change themes:

  1. User menu - Click the user menu → Appearance → pick a theme
  2. Command palette - Press k → Type "theme" → Select theme
  3. Settings page - Visit /settings for 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:

ModeBehavior
LightForce light appearance
DarkForce dark appearance
SystemFollow 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

PropertyTypeDescription
themeRef<ThemeId>Current theme ID
themesThemeConfig[]All available themes
currentThemeComputedRef<ThemeConfig>Current theme config
setTheme(id)(ThemeId) => voidSet theme by ID
cycleTheme()() => voidRotate to next theme
colorModeColorModeAccess 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:

  1. Import in app/assets/css/themes/index.css:
@import "./my-theme.css";
  1. 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',
  },
]
  1. 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:

  1. Open user menu (bottom of sidebar)
  2. Click "Component Catalog"
  3. Browse components by category
  4. 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

FilePurpose
app/assets/css/main.cssBase styles, imports themes
app/assets/css/themes/Theme CSS files
app/composables/use-theme.tsTheme composable
shared/types/theme.tsType definitions
app/pages/settings.vueSettings page UI
app/components/component-catalog.vueComponent browser
app.config.tsNuxt UI color configuration
  • a: Appearance
  • ?: Keyboard shortcuts