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

# Themes & Modes

> The BEEQ design system supports two themes — **beeq** and **endava** — and two modes — **dark** and **light**. You can apply these styles using HTML attributes or CSS classes.

export const CodeLivePreview = ({code, children, height, removePadding = false, mode = 'shadow'}) => {
  const previewRef = useRef(null);
  const BEEQ_ESM_URL = 'https://esm.sh/@beeq/core/dist/beeq/beeq.esm.js';
  const BEEQ_CSS_URL = 'https://esm.sh/@beeq/core/dist/beeq/beeq.css';
  const BEEQ_ICONS_URL = 'https://esm.sh/@beeq/core/dist/beeq/svg';
  const ensureParentBeeqRuntime = () => {
    if (document.querySelector('script[data-beeq-parent-runtime]')) return;
    const script = document.createElement('script');
    script.type = 'module';
    script.src = BEEQ_ESM_URL;
    script.dataset.beeqParentRuntime = BEEQ_ICONS_URL;
    document.head.appendChild(script);
  };
  const executeSnippetScripts = (root, runtimeWindow, previewRootArg, skipAttr) => {
    root.querySelectorAll('script').forEach(oldScript => {
      if (skipAttr && oldScript.hasAttribute(skipAttr)) return;
      if (oldScript.src) {
        const newScript = runtimeWindow.document.createElement('script');
        newScript.src = oldScript.src;
        oldScript.replaceWith(newScript);
        return;
      }
      runtimeWindow.Function('previewRoot', oldScript.textContent || '')(previewRootArg);
      oldScript.remove();
    });
  };
  const syncIframeMode = iframeDoc => {
    const root = document.documentElement;
    const explicitMode = root.getAttribute('bq-mode');
    const isDark = root.classList.contains('dark');
    const resolvedMode = explicitMode || (isDark ? 'dark' : 'light');
    iframeDoc.documentElement.setAttribute('bq-mode', resolvedMode);
    iframeDoc.body.setAttribute('bq-mode', resolvedMode);
  };
  useEffect(() => {
    if (mode === 'shadow') ensureParentBeeqRuntime();
  }, [mode]);
  useEffect(() => {
    const container = previewRef.current;
    if (!container) return;
    if (removePadding) container.style.padding = '0';
    container.innerHTML = '';
    if (mode === 'iframe') {
      const iframe = document.createElement('iframe');
      iframe.className = 'preview-iframe';
      iframe.style.width = '100%';
      iframe.style.border = '0';
      iframe.style.display = 'block';
      iframe.style.minHeight = height ?? '0px';
      iframe.setAttribute('title', 'Live code preview');
      iframe.setAttribute('loading', 'lazy');
      iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
      container.appendChild(iframe);
      const iframeDoc = iframe.contentDocument;
      const iframeWin = iframe.contentWindow;
      if (!iframeDoc || !iframeWin) return;
      iframeDoc.open();
      iframeDoc.write(['<!doctype html>', '<html>', '<head>', '  <meta charset="utf-8" />', '  <meta name="viewport" content="width=device-width, initial-scale=1" />', '  <style>html,body{margin:0;padding:0;min-height:100%;}</style>', `  <link rel="stylesheet" href="${BEEQ_CSS_URL}" />`, `  <script type="module" src="${BEEQ_ESM_URL}" data-beeq-iframe-runtime="${BEEQ_ICONS_URL}"></script>`, '</head>', '<body>', code, '</body>', '</html>'].join('\n'));
      iframeDoc.close();
      syncIframeMode(iframeDoc);
      const modeObserver = new MutationObserver(() => syncIframeMode(iframeDoc));
      modeObserver.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ['class', 'bq-mode']
      });
      executeSnippetScripts(iframeDoc, iframeWin, iframeDoc, 'data-beeq-iframe-runtime');
      return () => modeObserver.disconnect();
    }
    const shadowRoot = container.shadowRoot ?? container.attachShadow({
      mode: 'open'
    });
    if (!shadowRoot.adoptedStyleSheets.length) {
      const fixSheet = new CSSStyleSheet();
      fixSheet.replaceSync(`
        bq-dropdown::part(panel),
        bq-panel::part(panel),
        bq-select::part(panel),
        bq-date-picker::part(panel) { z-index: 9999; }
        bq-tooltip::part(panel) { position: absolute; }
      `);
      shadowRoot.adoptedStyleSheets = [fixSheet];
    }
    shadowRoot.innerHTML = [`<link rel="stylesheet" href="${BEEQ_CSS_URL}">`, code].join('');
    executeSnippetScripts(shadowRoot, window, shadowRoot);
    return undefined;
  }, [code, mode, height]);
  return <div className="code-live-preview not-prose">
      {}
      <div className="preview" ref={previewRef} style={{
    minHeight: height
  }} />

      {}
      {children && <div className="code">{children}</div>}
    </div>;
};

Themes and modes let you adapt the look and feel of your product to match different brand identities and user preferences — making BEEQ suitable for both consumer-facing apps and internal tools.
BEEQ also supports mixing modes within the same layout, so individual sections can use a different color scheme from the rest of the page.

<Note>
  Explore related sections: [Colors](/foundations/colors), [Global CSS Variables](/theming/global-css-variables), and [Customization](/theming/custom-theme).
</Note>

***

## Applying themes

BEEQ lets you apply themes using either HTML attributes (recommended) or CSS classes, ensuring a consistent look for every application.

### Using HTML attributes

Set the `bq-theme` attribute on the `<html>` element (recommended) or the `<body>` tag.

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html bq-theme="beeq">
  <!-- Your content here -->
</html>
```

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html bq-theme="endava">
  <!-- Your content here -->
</html>
```

### Using CSS classes

Alternatively, apply themes using CSS classes directly on the root element.

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html class="beeq">
  <!-- Your content here -->
</html>
```

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html class="endava">
  <!-- Your content here -->
</html>
```

<Note>
  When applying a theme, maintain consistency and avoid mixing different themes throughout the app.
</Note>

***

## Applying modes

Modes let you switch between light and dark color schemes to match user preferences or specific app needs. You can control modes globally or for specific sections using HTML attributes or CSS classes.

### Using HTML attributes

Set the `bq-mode` attribute to control the color scheme.

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html bq-mode="dark">
  <!-- Your content here -->
</html>
```

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html bq-mode="light">
  <!-- Your content here -->
</html>
```

### Using CSS classes

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html class="dark">
  <!-- Your content here -->
</html>
```

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html class="light">
  <!-- Your content here -->
</html>
```

### Combining modes

You can mix and match modes at various levels of your layout. For instance, you might use dark mode for the main section of your app and switch to light mode for a nested component.

```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
<html bq-mode="dark">
  <body>
    <!-- Your content here -->
    <section bq-mode="light">
      <!-- This section applies light mode to all elements and components inside -->
    </section>
  </body>
</html>
```

***

## User's color scheme preferences

**BEEQ does not automatically detect or apply the user's preferred color scheme.** It is up to you to control whether users see light or dark mode in your app. To provide a better experience:

* Make the `prefers-color-scheme` setting your default.
* Allow users to switch this option in your app.
* Remember their choice and apply it when they log in or return to the app.

The `prefers-color-scheme` media query is not used by BEEQ automatically, as not all applications support dark mode, which might cause problems for those that don't.

### Example

Here is a working example showing how to read the user's preferred color scheme on load and let them toggle it using a `bq-switch`.

<Tip>
  Toggle the `bq-switch` in the live preview below to switch between light and dark mode. You can also use the Mintlify top-bar toggle to change the page mode and see how the theme variables adapt.
</Tip>

<CodeLivePreview
  mode="shadow"
  code={`
<style>
:host {
  flex-direction: column !important;
  align-items: stretch !important;
  padding: 0 !important;
}

.nav-bar {
  display: flex;
  justify-content: center;
  background-color: var(--bq-ui--primary);
  border-bottom: 1px solid var(--bq-stroke--primary);
}

.nav-bar__main {
  flex: 1;
  display: flex;
  align-items: center;
  flex-direction: row;
  justify-content: flex-end;
  gap: var(--bq-spacing-xl);
  padding: var(--bq-spacing-m);
  max-width: 1440px;
}

.nav-bar__mode {
  display: flex;
  align-items: center;
  gap: var(--bq-spacing-xs);
  color: var(--bq-text--primary);
}

.main {
  padding: var(--bq-spacing-m);
}

.main h1 {
  margin-block-end: var(--bq-spacing-l);
  color: var(--bq-text--primary);
}

.content {
  background: var(--bq-ui--alt);
  border: 2px dashed var(--bq-stroke--primary);
  height: 10rem;
  width: 100%;
}
</style>

<header class="nav-bar">
<div class="nav-bar__main">
  <div class="nav-bar__mode">
    <bq-icon name="sun-thin"></bq-icon>
    <bq-switch name="mode"></bq-switch>
    <bq-icon name="moon-fill"></bq-icon>
  </div>
</div>
</header>

<main class="main">
<h1>Dashboard</h1>
<div class="content"></div>
</main>

<script>
(() => {
  const switcher = previewRoot.querySelector('bq-switch[name="mode"]');
  if (!switcher) return;
  const prefersDark = window.matchMedia
    ? window.matchMedia('(prefers-color-scheme: dark)').matches
    : false;
  switcher.checked = prefersDark;
  setThemeMode(prefersDark);
  switcher.addEventListener('bqChange', (event) => {
    setThemeMode(event.detail.checked);
  });
  function setThemeMode(isDark) {
    previewRoot.host.setAttribute('bq-mode', isDark ? 'dark' : 'light');
  }
})();
</script>
`}
>
  <CodeGroup>
    ```css styles.css icon="css" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    .nav-bar {
      display: flex;
      justify-content: center;
      background-color: var(--bq-ui--primary);
      border-bottom: 1px solid var(--bq-stroke--primary);
    }

    .nav-bar__main {
      flex: 1;
      display: flex;
      align-items: center;
      flex-direction: column;
      justify-content: end;
      gap: var(--bq-spacing-xl);
      padding: var(--bq-spacing-m);
      max-width: 1440px;

      @media (min-width: 600px) {
        flex-direction: row;
      }
    }

    .nav-bar__mode {
      display: flex;
      align-items: center;
      gap: var(--bq-spacing-xs);
      color: var(--bq-text--primary);
    }

    .main {
      padding: var(--bq-spacing-m);

      h1 {
        margin-block-end: var(--bq-spacing-l);
      }
    }

    .content {
      background: var(--bq-ui--alt);
      border: 2px dashed var(--bq-stroke--primary);
      height: 10rem;
      width: 100%;
    }
    ```

    ```ts TypeScript icon="js" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import type { BqSwitchCustomEvent } from '@beeq/core';
    import "./styles.css";

    const switcher = document.querySelector('bq-switch[name="mode"]') as HTMLBqSwitchElement | null;
    if (!switcher) {
      throw new Error('bq-switch[name="mode"] not found');
    }

    // Get the user's preferred color scheme when the page loads
    const prefersDark = window.matchMedia
      ? window.matchMedia('(prefers-color-scheme: dark)').matches
      : false;

    // Reflect initial theme mode based on the user's color scheme
    switcher.checked = prefersDark;
    setThemeMode(prefersDark);

    // Handle changes from the BEEQ switch button interaction
    switcher.addEventListener('bqChange', (event: BqSwitchCustomEvent<{ checked: boolean }>) => {
      setThemeMode(event.detail.checked);
    });

    function setThemeMode(isDark: boolean) {
      document.documentElement.setAttribute('bq-mode', isDark ? 'dark' : 'light');
    }
    ```

    ```html HTML icon="html5" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <!DOCTYPE html>
    <html>
      <head>
        <title>BEEQ Theme Mode</title>
        <meta charset="UTF-8" />
      </head>
      <body>
        <header class="nav-bar">
          <div class="nav-bar__main">
            <div class="nav-bar__mode">
              <bq-icon name="sun-thin"></bq-icon>
              <bq-switch name="mode"></bq-switch>
              <bq-icon name="moon-fill"></bq-icon>
            </div>
          </div>
        </header>

        <main class="main">
          <h1>Dashboard</h1>
          <div class="content">
            <!-- Your content -->
          </div>
        </main>

        <script src="index.ts"></script>
      </body>
    </html>
    ```

    ```tsx React icon="react" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { useState, useEffect } from "react";
    import { BqIcon, BqSwitch } from "@beeq/react";
    import "./styles.css";

    export default function App() {
      const [isDark, setIsDark] = useState(
        () => window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false
      );

      useEffect(() => {
        document.documentElement.setAttribute("bq-mode", isDark ? "dark" : "light");
      }, [isDark]);

      const handleModeChange = (event: CustomEvent<{ checked: boolean }>) => {
        setIsDark(event.detail.checked);
      };

      return (
        <>
          <header className="nav-bar">
            <div className="nav-bar__main">
              <div className="nav-bar__mode">
                <BqIcon name="sun-thin" />
                <BqSwitch name="mode" checked={isDark} onBqChange={handleModeChange} />
                <BqIcon name="moon-fill" />
              </div>
            </div>
          </header>
          <main className="main">
            <h1>Dashboard</h1>
            <div className="content" />
          </main>
        </>
      );
    }
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component, OnInit, inject, signal } from "@angular/core";
    import { DOCUMENT } from "@angular/common";
    import { BqIcon, BqSwitch } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqIcon, BqSwitch],
      template: `
        <header class="nav-bar">
          <div class="nav-bar__main">
            <div class="nav-bar__mode">
              <bq-icon name="sun-thin"></bq-icon>
              <bq-switch name="mode" [attr.checked]="isDark() || null" (bqChange)="handleModeChange($event)"></bq-switch>
              <bq-icon name="moon-fill"></bq-icon>
            </div>
          </div>
        </header>
        <main class="main">
          <h1>Dashboard</h1>
          <div class="content"></div>
        </main>
      `,
      styles: [`
        .nav-bar {
          display: flex;
          justify-content: center;
          background-color: var(--bq-ui--primary);
          border-bottom: 1px solid var(--bq-stroke--primary);
        }

        .nav-bar__main {
          flex: 1;
          display: flex;
          align-items: center;
          flex-direction: column;
          justify-content: end;
          gap: var(--bq-spacing-xl);
          padding: var(--bq-spacing-m);
          max-width: 1440px;

          @media (min-width: 600px) {
            flex-direction: row;
          }
        }

        .nav-bar__mode {
          display: flex;
          align-items: center;
          gap: var(--bq-spacing-xs);
          color: var(--bq-text--primary);
        }

        .main {
          padding: var(--bq-spacing-m);

          h1 {
            margin-block-end: var(--bq-spacing-l);
          }
        }

        .content {
          background: var(--bq-ui--alt);
          border: 2px dashed var(--bq-stroke--primary);
          height: 10rem;
          width: 100%;
        }
      `],
    })
    export class AppComponent implements OnInit {
      private readonly document = inject(DOCUMENT);
      readonly isDark = signal(false);

      ngOnInit() {
        const prefersDark = window.matchMedia
          ? window.matchMedia("(prefers-color-scheme: dark)").matches
          : false;
        this.isDark.set(prefersDark);
        this.document.documentElement.setAttribute("bq-mode", prefersDark ? "dark" : "light");
      }

      handleModeChange(event: CustomEvent<{ checked: boolean }>) {
        const isDark = event.detail.checked;
        this.isDark.set(isDark);
        this.document.documentElement.setAttribute("bq-mode", isDark ? "dark" : "light");
      }
    }
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { ref, watch, onMounted } from "vue";
    import { BqIcon, BqSwitch } from "@beeq/vue";

    const isDark = ref(
      window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)").matches : false
    );

    onMounted(() => {
      document.documentElement.setAttribute("bq-mode", isDark.value ? "dark" : "light");
    });

    watch(isDark, (value) => {
      document.documentElement.setAttribute("bq-mode", value ? "dark" : "light");
    });

    function handleModeChange(event: CustomEvent<{ checked: boolean }>) {
      isDark.value = event.detail.checked;
    }
    </script>

    <template>
      <header class="nav-bar">
        <div class="nav-bar__main">
          <div class="nav-bar__mode">
            <BqIcon name="sun-thin" />
            <BqSwitch name="mode" :checked="isDark" @bqChange="handleModeChange" />
            <BqIcon name="moon-fill" />
          </div>
        </div>
      </header>
      <main class="main">
        <h1>Dashboard</h1>
        <div class="content" />
      </main>
    </template>

    <style>
      .nav-bar {
        display: flex;
        justify-content: center;
        background-color: var(--bq-ui--primary);
        border-bottom: 1px solid var(--bq-stroke--primary);
      }

      .nav-bar__main {
        flex: 1;
        display: flex;
        align-items: center;
        flex-direction: column;
        justify-content: end;
        gap: var(--bq-spacing-xl);
        padding: var(--bq-spacing-m);
        max-width: 1440px;

        @media (min-width: 600px) {
          flex-direction: row;
        }
      }

      .nav-bar__mode {
        display: flex;
        align-items: center;
        gap: var(--bq-spacing-xs);
        color: var(--bq-text--primary);
      }

      .main {
        padding: var(--bq-spacing-m);

        h1 {
          margin-block-end: var(--bq-spacing-l);
        }
      }

      .content {
        background: var(--bq-ui--alt);
        border: 2px dashed var(--bq-stroke--primary);
        height: 10rem;
        width: 100%;
      }
    </style>
    ```
  </CodeGroup>
</CodeLivePreview>

***

## Next steps

<CardGroup cols={2}>
  <Card horizontal title="Custom Theme" icon="paintbrush" href="/theming/custom-theme">
    Follow the step-by-step guide to create and apply a fully custom theme to your app.
  </Card>

  <Card horizontal title="Global CSS Variables" icon="palette" href="/theming/global-css-variables">
    Explore the color tokens and base variables that power BEEQ themes and modes.
  </Card>
</CardGroup>
