> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yoopta.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Themes

> Headless plugins and theme packages for styled block UI

## Overview

The editor and all plugins are **headless** by default: they define structure and behavior but do not ship UI for how block elements look. You can keep them headless (e.g. for custom design) or attach styled UI from a **theme package**.

Available themes:

* **`@yoopta/themes-shadcn`** — Shadcn UI styled components (production ready)
* **`@yoopta/themes-material`** — Material Design styled components (in progress)

Themes provide UI components for plugin elements (e.g. Callout, Code, Image). You can either apply a theme to **all** plugins at once with `applyTheme()`, or attach theme UI to **individual** plugins via `plugin.extend({ elements: ThemeUI })`.

***

## Concept: headless + optional UI

Plugins define their block type, elements, and behavior; they do not require any specific look. Theme packages export:

1. **Per-plugin UI objects** — e.g. `CalloutUI` from `@yoopta/themes-shadcn/callout`, which you pass into `Callout.extend({ elements: CalloutUI })`.
2. **`applyTheme(plugins)`** — a helper that applies the theme’s UI to every supported plugin in the array in one go.

So you can:

* Use plugins as-is (headless) and render elements yourself.
* Use theme UI for a single plugin: `Callout.extend({ elements: CalloutUI })`.
* Use theme UI for all plugins: `applyTheme([Paragraph, Callout, ...])`.

***

## Apply theme to all plugins

Use `applyTheme()` from a theme package to wrap your plugin list; the theme will attach its styled elements to every plugin it supports.

```bash theme={null}
npm install @yoopta/themes-shadcn
```

```tsx theme={null}
import { createYooptaEditor } from '@yoopta/editor';
import { applyTheme } from '@yoopta/themes-shadcn';
import Paragraph from '@yoopta/paragraph';
import Callout from '@yoopta/callout';
import Headings from '@yoopta/headings';

const plugins = applyTheme([
  Paragraph,
  Callout,
  Headings.HeadingOne,
  Headings.HeadingTwo,
  Headings.HeadingThree,
]);

const editor = createYooptaEditor({ plugins, marks: [] });
```

Then pass `plugins` (the result of `applyTheme`) into `createYooptaEditor`. The theme’s CSS is applied by the package; you don’t pass plugins or marks to `<YooptaEditor>`.

***

## Apply theme UI to a single plugin

If you only want themed UI for specific plugins, import the theme’s UI object for that plugin and extend the plugin with `elements`.

**Example: Callout with Shadcn UI**

```tsx theme={null}
import Callout from '@yoopta/callout';
import { CalloutUI } from '@yoopta/themes-shadcn/callout';

const CalloutWithUI = Callout.extend({
  elements: CalloutUI,
});
```

Use `CalloutWithUI` in your plugins array; other plugins can stay headless or use other themes.

Subpaths are available per plugin, for example:

* `@yoopta/themes-shadcn/callout` → `CalloutUI`
* `@yoopta/themes-shadcn/paragraph` → `ParagraphUI`
* `@yoopta/themes-shadcn/embed` → `EmbedUI`
* …and other plugins supported by the theme

***

## @yoopta/themes-shadcn

Production-ready theme based on [Shadcn UI](https://ui.shadcn.com/). It provides styled elements for paragraph, headings, lists, blockquote, callout, code, image, video, embed, file, table, tabs, steps, accordion, carousel, divider, link, mention, and table-of-contents.

**Install**

```bash theme={null}
npm install @yoopta/themes-shadcn
```

**Apply to all plugins**

```tsx theme={null}
import { applyTheme } from '@yoopta/themes-shadcn';

const plugins = applyTheme([
  Paragraph,
  Headings.HeadingOne,
  Callout,
  // ...
]);
```

**Apply to one plugin**

```tsx theme={null}
import { CalloutUI } from '@yoopta/themes-shadcn/callout';

Callout.extend({ elements: CalloutUI });
```

### CSS Variables

The theme reads from standard [shadcn/ui](https://ui.shadcn.com/) CSS variables (`--background`, `--foreground`, `--card`, `--border`, etc.). If your app already uses shadcn/ui, the theme works out of the box — no extra setup needed.

If you **don't** have shadcn CSS variables defined, import the default variables provided by the package:

```tsx theme={null}
import '@yoopta/themes-shadcn/variables.css';
```

This gives you a complete set of light and dark mode color tokens.

### Dark mode

The theme supports dark mode through CSS variables. When dark mode is active, the variable values change and the editor automatically picks up the new colors (background, text, borders, etc.).

Dark mode activates when any ancestor of the editor has one of these selectors:

* `.dark` class (default for shadcn/ui and Tailwind dark mode)
* `[data-theme="dark"]` attribute
* `[data-yoopta-theme="dark"]` attribute

**Example: toggle dark mode**

```tsx theme={null}
function App() {
  const [isDark, setIsDark] = useState(false);

  return (
    <div className={isDark ? 'dark' : ''}>
      <button onClick={() => setIsDark(!isDark)}>Toggle theme</button>
      <YooptaEditor editor={editor}>
        {/* ... */}
      </YooptaEditor>
    </div>
  );
}
```

Or using a data attribute:

```tsx theme={null}
<div data-theme={isDark ? 'dark' : 'light'}>
  <YooptaEditor editor={editor} />
</div>
```

### Customizing variables

You can override any variable to match your brand. The theme uses HSL values (without the `hsl()` wrapper):

```css theme={null}
:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --card: 0 0% 100%;
  --card-foreground: 222.2 84% 4.9%;
  --popover: 0 0% 100%;
  --popover-foreground: 222.2 84% 4.9%;
  --primary: 221.2 83.2% 53.3%;
  --primary-foreground: 210 40% 98%;
  --secondary: 210 40% 96.1%;
  --secondary-foreground: 222.2 47.4% 11.2%;
  --muted: 210 40% 96.1%;
  --muted-foreground: 215.4 16.3% 46.9%;
  --accent: 210 40% 96.1%;
  --accent-foreground: 222.2 47.4% 11.2%;
  --destructive: 0 84.2% 60.2%;
  --destructive-foreground: 210 40% 98%;
  --border: 214.3 31.8% 91.4%;
  --input: 214.3 31.8% 91.4%;
  --ring: 221.2 83.2% 53.3%;
  --radius: 0.5rem;
}

.dark {
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
  /* ... your dark mode overrides */
}
```

You only need to define the variables you want to change — the rest will use defaults from `variables.css` (if imported) or your existing shadcn/ui setup.

**Full list of variables used by the theme:**

| Variable                                     | Usage                                   |
| -------------------------------------------- | --------------------------------------- |
| `--background`                               | Editor background                       |
| `--foreground`                               | Editor text color                       |
| `--card` / `--card-foreground`               | Card-style blocks (callout, code, etc.) |
| `--popover` / `--popover-foreground`         | Dropdowns, menus, tooltips              |
| `--primary` / `--primary-foreground`         | Primary actions, buttons                |
| `--secondary` / `--secondary-foreground`     | Secondary actions                       |
| `--muted` / `--muted-foreground`             | Muted text, disabled states             |
| `--accent` / `--accent-foreground`           | Hover highlights, accents               |
| `--destructive` / `--destructive-foreground` | Delete actions, errors                  |
| `--border`                                   | Borders                                 |
| `--input`                                    | Input field borders                     |
| `--ring`                                     | Focus rings                             |
| `--radius`                                   | Border radius base value                |

***

## @yoopta/themes-material

Material Design styled components for Yoopta plugins. **In progress** — not all plugins may be covered yet.

**Install**

```bash theme={null}
npm install @yoopta/themes-material
```

**Usage** (same idea as Shadcn: `applyTheme(plugins)` or `plugin.extend({ elements: MaterialUI })` per plugin when the package exposes it).

***

## Summary

| Approach                               | Use case                                        |
| -------------------------------------- | ----------------------------------------------- |
| Headless                               | Custom design; you implement all element UI.    |
| `plugin.extend({ elements: ThemeUI })` | Use theme UI only for specific plugins.         |
| `applyTheme(plugins)`                  | Use theme UI for all supported plugins at once. |

The editor and plugins stay headless; themes only provide optional UI for their elements.
