Skip to the content
BooleanPress UI

Dark mode

Turn on the dark theme with a class on the root element; every component and overlay follows.

The dark class

The dark theme applies inside any element with the class dark. Put it on <html>:

<html class="dark">

Dialogs, menus, popovers and selects render at the end of <body>, outside your app's root. With the class on <html>, they turn dark with the rest of the page; on an inner element, they would stay light.

Set color-scheme too, so the browser draws scroll bars and native controls to match:

:root { color-scheme: light; }
:root.dark { color-scheme: dark; }

Follow the system setting

To follow the reader's system setting, and keep their choice when they make one, set the class before the first paint with a small script in <head>:

<script>
  const choice = localStorage.getItem("theme") // "light", "dark" or null for the system's
  const dark = choice ? choice === "dark" : matchMedia("(prefers-color-scheme: dark)").matches
  document.documentElement.classList.toggle("dark", dark)
</script>

Running it before your app's bundle avoids a flash of the light theme for a reader who chose dark.

Your dark palette

theme.css has dark values for every token. To brand the dark theme, give the tokens values in the .dark block of brand.css; a token you leave out there keeps its light brand value or the dark default. Theming builds both blocks, and bui-contrast checks the dark theme as well as the light one.

Toasts

The toast region draws its own close button. Pass the same theme to it, so the button matches: <Toaster theme={dark ? "dark" : "light"} />. Its default, "system", follows the system setting rather than your class.