---
title: "Theme System"
description: "Manage colors, radius, icon sets and dark mode through module defaults, the ThemePicker component and the useTheme composable, with build-time font configuration."
canonical_url: "https://nuxt.mhaibaraai.cn/en/docs/getting-started/theme"
---
# Theme System

> Manage colors, radius, icon sets and dark mode through module defaults, the ThemePicker component and the useTheme composable, with build-time font configuration.

## Introduction

Movk Nuxt provides unified runtime theme management on top of [Nuxt UI](https://ui.nuxt.com) theming: colors, radius, fonts, icon sets and dark mode are all centrally controlled and can be interactively adjusted at runtime, with one-click export of CSS variables or configuration code.

Theme capabilities consist of three parts:

- **Module defaults**: Declare available options in `movk.theme` inside `nuxt.config.ts`.
- **ThemePicker component**: A user-facing visual control panel with export support.
- **useTheme composable**: Read and write theme state in scripts, export CSS/config.

## Enable & Disable

The theme module is enabled by default. When disabled, `appConfig` defaults, the theme plugin and the `ThemePicker` component are no longer injected:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  movk: {
    theme: { enabled: false }
  }
})
```

## ThemePicker Component

`ThemePicker` provides visual switching for colors, radius, icon sets and dark mode, and can export the current theme.

> [!TIP]
> See: /docs/components/theme-picker
> 
> View the complete props, events and usage of ThemePicker.

## useTheme

`useTheme` exposes reactive theme state and export methods, suitable for custom theme panels or reading theme values in business logic:

```ts
const {
  color, neutral, radius, icon, mode,
  exportCSS, exportConfig, resetTheme
} = useTheme()

// Read/switch theme
color.value = 'green'
mode.value = 'dark'

// Export current theme
const css = exportCSS()
const config = exportConfig()
```

> [!TIP]
> See: /docs/composables/use-theme
> 
> View all state and methods returned by useTheme.

## Fonts

The font is build-time configuration and does not switch at runtime. One line is all it takes:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  movk: {
    theme: {
      font: 'Alibaba PuHuiTi'
    }
  }
})
```

At build time the module does three things, all served straight from SSR with no runtime JS involved:

- Writes the font stylesheet `<link>` into `<head>`
- Adds a `preconnect` with `crossorigin` for cross-origin fonts
- Injects `@theme { --font-sans }`, appending a fallback stack that covers the system Chinese fonts on macOS, Windows and Linux

Built-in fonts are hosted by [movk-fonts](https://github.com/mhaibaraai/movk-fonts). The value must match the `font-family` in their `@font-face` declarations character for character:

| Value | Stylesheet |
| --- | --- |
| `Alibaba PuHuiTi` | `https://cdn.mhaibaraai.cn/fonts/alibaba-puhuiti.css` |
| `OPPO Sans` | `https://cdn.mhaibaraai.cn/fonts/oppo-sans.css` |

For self-hosted fonts, use the `{ name, href }` form to supply the stylesheet URL:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  movk: {
    theme: {
      font: { name: 'My Font', href: '/fonts/my-font.css' }
    }
  }
})
```

> [!WARNING]
> 
> A wrong 
> 
> name
> 
>  raises no error — it silently falls back to the system font. CSS family matching is case-insensitive, but 
> 
> alibaba-puhuiti
> 
>  and 
> 
> Alibaba PuHuiTi
> 
>  are two different names. A font that is neither built in nor given an 
> 
> href
> 
>  triggers no request at all, and the module warns during development.

The `@theme` injected by the module lands with `@import "@movk/nuxt"`, so any `@theme` written after it overrides `--font-sans`. To control the font entirely from your own CSS, leave `movk.theme.font` unset:

```css [app/assets/css/main.css]
@import "tailwindcss";
@import "@movk/nuxt";

@theme {
  --font-sans: "OPPO Sans", sans-serif;
}
```

> [!NOTE]
> 
> Chinese fonts are split by 
> 
> unicode-range
> 
> , so the browser only downloads the shards holding characters the page actually uses. That is why these fonts 
> 
> must not
> 
>  be handed to 
> 
> @nuxt/fonts
> 
>  — it downloads every shard into the build output at build time, losing both on-demand loading and the CDN cache shared across projects. 
> 
> @movk/nuxt
> 
>  already sets 
> 
> ui.fonts: false
> 
>  by default, so your project never needs to declare it.

## Icon Sets

`ThemePicker` and `useTheme` switch between the Lucide, Phosphor and Tabler icon sets at runtime. Switching only rewrites `appConfig.ui.icons` — no rebuild required.

By default the module feeds the icons used by its own components, plus all three icon sets, into the `@nuxt/icon` build-time bundle, so nothing has to be fetched from the Iconify API at runtime. Each set needs its own `@iconify-json` package to be inlined:

```bash
npx nypm add -D @iconify-json/lucide @iconify-json/ph @iconify-json/tabler
```

> [!NOTE]
> 
> A missing collection never fails the build; its icons simply fall back to on-demand runtime loading. The module warns when the default 
> 
> lucide
> 
>  collection is missing, while 
> 
> ph
> 
>  and 
> 
> tabler
> 
>  — only needed after switching icon sets — are reported as a debug log.

To opt out entirely (for example when your project manages the icon bundle itself), turn it off; movk component icons then load at runtime:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  movk: {
    icon: { clientBundle: false }
  }
})
```

## Radius

`--ui-radius` keeps its three-level precedence: `ThemePicker` selection > `movk.theme.radius` > your project CSS. When omitted, the module does not inject the variable and the `@nuxt/ui` default (`0.25rem`) applies, so your project can override it in its own CSS:

```css [app/assets/css/main.css]
@theme {
  --ui-radius: 0.5rem;
}
```

## Customizing Options

Color aliases, radius steps and neutral colors can all be overridden in `movk.theme`, serving as the value range for `ThemePicker` and `useTheme`:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  movk: {
    theme: {
      colors: ['primary', 'secondary', 'success', 'info', 'warning', 'error'],
      radiuses: [0, 0.125, 0.25, 0.375, 0.5],
      neutralColors: ['slate', 'gray', 'zinc', 'neutral', 'stone']
    }
  }
})
```

> [!TIP]
> See: /docs/getting-started/configuration
> 
> See Module Configuration · Theme for field descriptions

## Export & Reuse

The CSS variables exported by `ThemePicker` and `useTheme.exportCSS()` can be written directly into your project's `main.css`, solidifying runtime debugging results as the default theme:

```css [app/assets/css/main.css]
@import "tailwindcss";
@import "@movk/nuxt";

:root {
  /* Paste variables exported by exportCSS() */
}
```


## Sitemap

See the full [sitemap](https://nuxt.mhaibaraai.cn/sitemap.md) for all pages.
