Light and dark

Both modes come from seven custom properties. Write a component once and it works in both.

Edit page

How it works

components/_mode.sass sets custom properties on body and overrides them on body.dark. Components read the properties, so there is no second set of rules for the dark mode.

components/_card.sass
.card
  color: var(--text)
  border: 1px solid var(--line)
  background-color: var(--page)

Properties

PropertyLightDark
--page$white$night
--surface$light$night-surface
--text$dark$night-text
--muted$medium$night-muted
--line$border$night-line
--line-soft$border-soft$night-line
--accent$accent$night-accent

Helpers that follow the mode

bg-page, bg-surface, c-text, c-muted, bc-line and bc-line-soft read the properties. Palette helpers such as bg-white or c-dark keep their exact colour in both modes. c-accent is the one exception: in dark mode it switches to $night-accent, because the light accent is too dark to read there.

The switch

components/Mode.jsx is the button in the header. It keeps the choice in localStorage under avior-mode and falls back to the system setting. An inline script in public/index.html applies the class before the page is painted, so a dark reader never sees a white flash.