Corex UI
Pagination
Tailwind
Accordion

# Theming

Corex UI design system is built to be fully themeable.
We offer over different themes, each available in light and dark modes.

neo, uno, duo, leo

# Apply Theme

To apply a theme globally, add the following attributes to your <html> tag replacing neo and light by the theme name and mode:

<html data-theme="neo" data-mode="light"></html>
            

Then, import the desired theme CSS:

@import "@corex-ui/design/themes/neo/light.css";
            @import "@corex-ui/design/themes/neo/dark.css";
            @import "@corex-ui/design/themes/uno/light.css";
            @import "@corex-ui/design/themes/uno/dark.css";
            @import "@corex-ui/design/themes/duo/light.css";
            @import "@corex-ui/design/themes/duo/dark.css";
            @import "@corex-ui/design/themes/leo/light.css";
            @import "@corex-ui/design/themes/leo/dark.css";
            

# Theme Switching

Corex UI supports dynamic theme and mode switching using:

  • Select component for themes
  • Toggle Group component for modes

We also synchronize all components through the Machine API when a value changes.

Finally, an inline script is required to prevent Flash of Unstyled Content (FOUC).

  1. Add HTML
<div
              id="selecter-theming"
              class="select-js select select--sm hidden lg:flex"
              data-on-value-change="update-selecter"
              data-close-on-select="false"
              data-no-trigger-update="true"
            >
              <div data-part="root" class="max-w-(--container-micro-sm)">
                <div data-part="control" class="max-w-(--container-micro-sm)">
                  <div data-part="label" class="sr-only">Select theme</div>
                  <button data-part="trigger" class="gap-ui-gap-sm">
                    Theme
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke-width="1.5"
                      stroke="currentColor"
                    >
                      <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        d="m19.5 8.25-7.5 7.5-7.5-7.5"
                      ></path>
                    </svg>
                  </button>
                </div>
                <div data-part="positioner">
                  <ul data-part="content" class="scrollbar">
                    <li data-part="item" data-value="neo" class="flex items-center gap-2">
                      <span data-part="item-text" data-value="neo">Neo</span>
                    </li>
                    <li data-part="item" data-value="uno" class="group">
                      <span data-part="item-text" data-value="uno">Uno</span>
                    </li>
                    <li data-part="item" data-value="duo">
                      <span data-part="item-text" data-value="duo">Duo</span>
                    </li>
                    <li data-part="item" data-value="leo">
                      <span data-part="item-text" data-value="leo">Leo</span>
                    </li>
                  </ul>
                </div>
              </div>
            </div>
            <script>
              try {
                const theme = localStorage.getItem("data-theme");
                console.log;
                const switcher = document.querySelector("#selecter-theming");
                if (switcher && theme) {
                  switcher.setAttribute("data-default-value", theme);
                }
              } catch (_) {}
            </script>
            
            <div
              id="switcher-theming"
              class="toggle-group toggle-group-js toggle-group--sm hidden lg:flex"
              data-on-value-change="update-switcher"
            >
              <div data-part="root" class="rounded-full">
                <button
                  data-part="item"
                  data-value="dark"
                  aria-label="Toggle light mode"
                  class="group data-[state=on]:bg-ui data-[state=on]:text-ui--text aspect-square rounded-full p-0"
                >
                  <svg
                    aria-hidden="true"
                    xmlns="http://www.w3.org/2000/svg"
                    xmlns:xlink="http://www.w3.org/1999/xlink"
                    version="1.1"
                    width="256"
                    height="256"
                    viewBox="0 0 256 256"
                    xml:space="preserve"
                  >
                    <g
                      style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;"
                      transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)"
                    >
                      <rect
                        x="42"
                        y="0"
                        rx="0"
                        ry="0"
                        width="6"
                        height="15.79"
                        style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: currentColor; fill-rule: nonzero; opacity: 1;"
                        transform=" matrix(1 0 0 1 0 0) "
                      />
                      <rect
                        x="42"
                        y="74.21"
                        rx="0"
                        ry="0"
                        width="6"
                        height="15.79"
                        style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: currentColor; fill-rule: nonzero; opacity: 1;"
                        transform=" matrix(1 0 0 1 0 0) "
                      />
                      <rect
                        x="0"
                        y="42"
                        rx="0"
                        ry="0"
                        width="15.79"
                        height="6"
                        style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: currentColor; fill-rule: nonzero; opacity: 1;"
                        transform=" matrix(1 0 0 1 0 0) "
                      />
                      <rect
                        x="74.21"
                        y="42"
                        rx="0"
                        ry="0"
                        width="15.79"
                        height="6"
                        style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: currentColor; fill-rule: nonzero; opacity: 1;"
                        transform=" matrix(1 0 0 1 0 0) "
                      />
                      <path
                        d="M 74.698 11.059 l -15.71 15.71 C 54.99 23.689 50.129 22 45 22 c -12.682 0 -23 10.318 -23 23 c 0 5.13 1.689 9.991 4.769 13.989 L 11.059 74.698 l 4.242 4.242 L 78.94 15.301 L 74.698 11.059 z"
                        style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: currentColor; fill-rule: nonzero; opacity: 1;"
                        transform=" matrix(1 0 0 1 0 0) "
                        stroke-linecap="round"
                      />
                      <rect
                        x="15.76"
                        y="10.87"
                        rx="0"
                        ry="0"
                        width="6"
                        height="15.79"
                        style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: currentColor; fill-rule: nonzero; opacity: 1;"
                        transform=" matrix(0.7071 -0.7071 0.7071 0.7071 -7.7721 18.7634) "
                      />
                      <rect
                        x="68.24"
                        y="63.34"
                        rx="0"
                        ry="0"
                        width="6"
                        height="15.79"
                        style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: currentColor; fill-rule: nonzero; opacity: 1;"
                        transform=" matrix(0.7071 -0.7071 0.7071 0.7071 -29.5071 71.2363) "
                      />
                    </g>
                  </svg>
                </button>
              </div>
            </div>
            <script>
              try {
                const mode = localStorage.getItem("data-mode");
                const switcher = document.querySelector("#switcher-theming");
                if (switcher) {
                  switcher.setAttribute("data-default-value", mode);
                }
              } catch (_) {}
            </script>
            

Inline script immediately after HTML ensures current values are populated from localStorage.

  1. Add TypeScript
const ids = ["switcher-theming", "switcher-other"];
            const elements = ids
              .map((id) => document.getElementById(id))
              .filter(Boolean) as HTMLElement[];
            
            elements.forEach((el) => {
              el.addEventListener("update-switcher", (event) => {
                const { value } = (event as CustomEvent<{ value: string[] }>).detail;
                const mode = value?.[0] ?? "light";
            
                document.documentElement.setAttribute("data-mode", mode);
                localStorage.setItem("data-mode", mode);
            
                const source = event.currentTarget as HTMLElement;
                elements.forEach((other) => {
                  if (other !== source) {
                    other.dispatchEvent(
                      new CustomEvent("toggle-group:set-value", { detail: { value } }),
                    );
                  }
                });
              });
            });
            
            const selecterIds = ["selecter-theming", "selecter-other"];
            const selecterElements = selecterIds
              .map((id) => document.getElementById(id))
              .filter(Boolean) as HTMLElement[];
            
            selecterElements.forEach((el) => {
              el.addEventListener("update-selecter", (event) => {
                const { value } = (event as CustomEvent<{ value: string[] }>).detail;
                const theme = value?.[0] ?? "neo";
            
                document.documentElement.setAttribute("data-theme", theme);
                localStorage.setItem("data-theme", theme);
            
                const source = event.currentTarget as HTMLElement;
                selecterElements.forEach((other) => {
                  if (other !== source) {
                    other.dispatchEvent(
                      new CustomEvent("select:set-value", { detail: { value } }),
                    );
                  }
                });
              });
            });
            
  1. Add Inline Script to Prevent FOUC

Add this script at the very top of your <head>:

<script>
              try {
                const themeStored = localStorage.getItem("data-theme");
                const theme = themeStored || "neo";
                document.documentElement.setAttribute("data-theme", theme);
                if (!themeStored) {
                  localStorage.setItem("data-theme", theme);
                }
                const modeStored = localStorage.getItem("data-mode");
                const prefersDark = window.matchMedia(
                  "(prefers-color-scheme: dark)",
                ).matches;
                const mode = modeStored || (prefersDark ? "dark" : "light");
                document.documentElement.setAttribute("data-mode", mode);
                if (!modeStored) {
                  localStorage.setItem("data-mode", mode);
                }
              } catch (_) {}
            </script>
            
  1. Import Components

Import Toggle Group and Select components in your main.ts

import "@corex-ui/static/components/select";
            import "@corex-ui/static/components/toggle-group";
            
  1. Import CSS

Import Toggle Group and Select style and all themes needed in your style.css

@import "@corex-ui/design/themes/neo/light.css";
            @import "@corex-ui/design/themes/neo/dark.css";
            @import "@corex-ui/design/themes/uno/light.css";
            @import "@corex-ui/design/themes/uno/dark.css";
            @import "@corex-ui/design/themes/duo/light.css";
            @import "@corex-ui/design/themes/duo/dark.css";
            @import "@corex-ui/design/themes/leo/light.css";
            @import "@corex-ui/design/themes/leo/dark.css";
            
            @import "@corex-ui/design/components/select.css";
            @import "@corex-ui/design/components/toggle-group.css";
            

You can also add a background to your body <body class="typo bg-root">

# Custom Dark Variant

If you wish to use the Tailwind custom variant such as dark: you must add the following to your main css

@custom-variant dark (&:where([data-mode=dark], [data-mode=dark] *));
            

# Automatic Mode Switching

If you want to automatically switch modes based on the user’s system preference you can use the following script

<script>
              try {
                const stored = localStorage.getItem("data-mode");
                const prefersDark = window.matchMedia(
                  "(prefers-color-scheme: dark)",
                ).matches;
                const mode = stored || (prefersDark ? "dark" : "light");
                document.documentElement.setAttribute("data-mode", mode);
            
                if (!stored) {
                  localStorage.setItem("data-mode", mode);
                }
              } catch (_) {}
            </script>
            

This setup ensures that:

  • Themes and modes are synchronized across all components.
  • User preferences are stored in localStorage.
  • The page prevents FOUC on load.
  • Automatic mode switching respects system preferences.