# Custom Themes

> Themes are used to style elements of the Data Studio including colors and fonts.

Themes are used to style the Data Studio. They can be used to change the colors, fonts, and other visual elements of the Data Studio.

![Directus' default theme](/img/91797ca8-68fa-4231-b143-8d5e134e9981.webp)

## Theme Entrypoint

The `index.js` or `index.ts` file exports an object that is read by Directus. It contains properties that control how a theme is displayed and what rules are applied when it is enabled.

### Entrypoint Example

```js
import { defineTheme } from "@directus/extensions-sdk";

export default defineTheme({
  id: "custom",
  name: "My Custom Theme",
  appearance: "dark",
  rules: {
    background: "tomato",
  },
});
```

### Properties

<table>
<thead>
  <tr>
    <th>
      Property
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        id
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      A unique identifier for this extension.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        name
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      The displayed name for this panel in the Data Studio.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        appearance
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      To which appearance mode the theme belongs to - <code>
        light
      </code>
      
       or <code>
        dark
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        rules
      </code>
    </td>
    
    <td>
      object
    </td>
    
    <td>
      A set of theming rules from the theme schema.
    </td>
  </tr>
</tbody>
</table>

### Available Rules

Rules that are configured in the `rules` property adhere to the rules section of the [theme schema](https://github.com/directus/directus/blob/main/packages/types/src/extensions/themes.ts).

```js
rules: {
    borderRadius: '24px',
    shell: {
        background: 'rebeccapurple'
    }
}
```

<callout icon="material-symbols:warning-rounded" color="warning">

**Theme schema changes in Directus 12**
The studio design refresh in Directus 12 reorganized the theme schema. Custom themes referencing the removed rules will silently lose those overrides — update your theme to the new tokens:

- `navigation.background`, `navigation.backgroundAccent`, `navigation.borderWidth`, `navigation.borderColor`, `header.background`, `header.borderWidth`, and `header.borderColor` → moved to the new `shell.*` scope (e.g. `shell.background`, `shell.backgroundAccent`, `shell.borderWidth`, `shell.borderColor`). The corresponding CSS variables changed from `--theme--navigation--*` / `--theme--header--*` to `--theme--shell--*`.
- `header.headline.foreground` and `header.headline.fontFamily` were removed along with the underlying `headline` slot. The CSS variables `--theme--header--headline--foreground` and `--theme--header--headline--font-family` no longer exist.
- `borderColorFocus`, `boxShadowHover`, and `boxShadowFocus` were removed in favor of the new `focusRingColor` token. Interface extensions targeting `--theme--form--field--input--border-color-focus` or `--theme--form--field--input--box-shadow-focus` should migrate to `--theme--form--field--input--focus-ring-color`.
- `navigation.project.background`, `navigation.project.borderWidth`, and `navigation.project.borderColor` were removed and no longer have any effect.
- `section.toggle.borderWidth` and `section.toggle.borderColor` were removed in favor of section-level border tokens.
- `defineLayout()` no longer exposes `headerShadow` or `sidebarShadow`; `boxShadow` was removed from the header theme rules.

</callout>

Any rules that are not defined will fallback to the default theme for it's appearance. See the
([`default dark theme`](https://github.com/directus/directus/blob/main/packages/themes/src/themes/dark/default.ts) and
[`default light theme`](https://github.com/directus/directus/blob/main/packages/themes/src/themes/light/default.ts)).

We recommend using TypeScript for this extension type. The `defineTheme` function is typed to properly check and auto-complete all available rules.

Custom Themes include only the allowed rules, and do not include custom CSS.

### Theme Usage in the Directus Data Studio

Every rule is automatically inserted in the app's root element as a CSS variable which are used across the app's
components. For example, the JSON path `navigation.modules.button.foregroundActive` will be available as
`var(--theme--navigation--modules--button--foreground-active)`.

<callout icon="i-lucide-info">

**Property Names**
Nested objects are separated by `--`, and camelCase values are transformed to hyphen-case (`foregroundActive` becomes `foreground-active`).

</callout>

Because each rule is used as a CSS variable, each rule value should be valid CSS. This also means you can use any CSS
functions in the rules.

## Using User Theming Options as a Development Tool

The Theming Options customization interface found in the global appearance settings and user detail page uses theming
rules. For easier extension development, you can use this interface to configure your theme, and then save the output to your theme extension by using the "Copy Raw Value" option above the interface.

## Google Fonts

The `fontFamily` rules take any valid CSS `font-family` value. To load a Google Font, wrap the font name in a set of
quotes `""`. This is still valid CSS, but if the font-name is wrapped in quotes, Directus will automatically try
downloading it through Google Fonts. For example:

```js
// Use the locally installed font called "Comic Sans MS"
fontFamily: "Comic Sans MS, sans-serif";

// Use the Google font "Yesteryear"
fontFamily: '"Yesteryear", sans-serif';
```

When using a Google Font, ensure the configured weight is available for the selected font.
