> ## Documentation Index
> Fetch the complete documentation index at: https://blacksilva.com/silva-ui/llms.txt
> Use this file to discover all available pages before exploring further.

# Theming

> Apply built-in themes, semantic colours, and custom themes.

# Theming

Silva UI components resolve CSS variables from the nearest theme scope. Use a built-in `Theme` for a ready-made palette, or compile a custom variable class with Vanilla Extract. The same semantic tokens power surfaces, text, component variants, and theme-aware gradients.

## Built-in themes

Available names are `light`, `dark`, `emerald`, `emerald-dark`, and `midnight`. Theme scopes can nest, so a local section can use a different palette without changing the rest of the page.

> [tab] Preview
>
> [Built-in theme preview](https://black-silva.github.io/silva-ui/previews/?example=theming-1)

> [tab] Code
>
> ```tsx theme={null}
> import { Box, Text, Theme } from "silva-ui"
>
> <Theme name="midnight">
>   <Box bg="card" color="primary" p="large" borderRadius="large">
>     <Text>Dark themed content</Text>
>   </Box>
> </Theme>
> ```

## Semantic tokens first

Choose semantic tokens when a colour describes a UI role rather than a specific hue. A `primary` button or `card` surface can change with the active theme without changing component code. Use Radix scale tokens such as `violet9` only when the hue itself is intentional, for example a decorative accent.

| Role | Tokens | Use for |
| - | - | - |
| Actions | `primary`, `primaryHover`, `primaryActive`, `primaryContrast`, `secondary` | Buttons, links, and selected states |
| Surfaces | `background`, `card`, `subtle`, `border`, `overlay` | Page, container, quiet section, and boundaries |
| Content | `muted`, `white`, `black`, `transparent` | Supporting text and explicit utility colours |
| Focus and feedback | `ring`, `info`, `success`, `warning`, `error`, `destructive` | Focus indicators and status messaging |

`themeColors` is the full CSS-variable contract behind these values. `colorTokens` and `darkColorTokens` provide the Radix scale defaults; `lightColors` and `darkColors` provide the semantic defaults for a theme.

## Custom themes with `createTheme`

`createTheme` is Vanilla Extract’s build-time API. It creates a CSS class with the same variable contract as Silva UI. Add that class to a normal wrapper around components and they inherit its token values automatically.

### 1. Add Vanilla Extract

```bash theme={null}
npm install @vanilla-extract/css
npm install -D @vanilla-extract/vite-plugin
```

```ts vite.config.ts theme={null}
import { defineConfig } from "vite"
import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin"

export default defineConfig({
  plugins: [vanillaExtractPlugin()],
})
```

### 2. Create the theme in a CSS module

Use a `*.css.ts` file so Vanilla Extract can compile it. Spreading the Silva UI exports fills the complete token contract, then your semantic overrides define the brand.

```ts src/brand-theme.css.ts theme={null}
import { createTheme } from "@vanilla-extract/css"
import { colorTokens, lightColors, themeColors } from "silva-ui"

export const brandTheme = createTheme(themeColors, {
  ...colorTokens,
  ...lightColors,
  primary: "#7c3aed",
  primaryHover: "#6d28d9",
  primaryActive: "#5b21b6",
  primaryContrast: "#ffffff",
  background: "#fbfaff",
  card: "#ffffff",
  subtle: "#f3f0ff",
  muted: "#6b6580",
  border: "#ded7f5",
  ring: "#7c3aed",
})
```

### 3. Apply the custom scope

> [tab] Preview
>
> [Custom theme preview](https://black-silva.github.io/silva-ui/previews/?example=theming-2)

> [tab] Code
>
> ```tsx theme={null}
> import "silva-ui/style.css"
> import { Button, Card, Paragraph, YStack } from "silva-ui"
> import { brandTheme } from "./brand-theme.css"
>
> export function PricingCard() {
>   return (
>     <div class={brandTheme}>
>       <Card bg="card" borderColor="border" bordered p="large">
>         <YStack gap="medium">
>           <Paragraph color="muted">A custom semantic palette.</Paragraph>
>           <Button>Choose plan</Button>
>         </YStack>
>       </Card>
>     </div>
>   )
> }
> ```

The wrapper provides `primary`, `card`, `border`, and the other variables. Any nested Silva UI component resolves them from that wrapper. You can put it inside a built-in `Theme` or make it the outer application scope.

### Dark custom theme

Start a dark version from the dark defaults.

```ts src/brand-dark-theme.css.ts theme={null}
import { createTheme } from "@vanilla-extract/css"
import { darkColorTokens, darkColors, themeColors } from "silva-ui"

export const brandDarkTheme = createTheme(themeColors, {
  ...darkColorTokens,
  ...darkColors,
  primary: "#a78bfa",
  primaryHover: "#c4b5fd",
  primaryActive: "#8b5cf6",
  primaryContrast: "#1b102e",
  background: "#120b20",
  card: "#1d122d",
  subtle: "#291a3d",
  muted: "#c7bbd9",
  border: "#45315f",
  ring: "#a78bfa",
})
```

## `createThemes` versus `createTheme`

`createThemes` generates plain palette/template value records. It does not emit a CSS class. Use it when generating values, then pass the final record through `createTheme` before applying it to a wrapper. For most apps, start with `themeColors` so custom and built-in themes use the same variable names.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.