Переключатель темы

sitelo-ui сам определяет тёмный режим по prefers-color-scheme: сайту, которого устраивает следовать за операционной системой, с этой страницы не нужно ничего. Переключатель нужен, чтобы читатель мог это переопределить.

Это один из пяти компонентов, которым нужен скрипт, потому что выбор живёт в localStorage, а прочитать его может только скрипт. Кнопка сама подгружает этот скрипт при первом нажатии.

Подключение

Две вещи в head и кнопка там, где ей место:

import { styles, themeScript, themeToggle } from 'sitelo/ui'

head(
  themeScript(), // применяет сохранённый выбор до первой отрисовки
  styles(),
)

body(
  appBar({ brand: 'Мой сайт' },
    appBarSpacer(),
    appBarActions(themeToggle()),
  ),
)

Третьего файла нет. themeScript() намеренно блокирующий и встроенный — всё отложенное рисуется раньше, а это и есть та самая тёмная вспышка, ради предотвращения которой он существует, — а само переключение едет на кнопке:

<button data-su-theme-toggle
        onclick="import('/su/theme.js').then(m=>m.toggle(this))">

Используйте их в паре. themeScript() заодно и проставляет переключателю aria-pressed при загрузке: ведь ничего ещё не нажимали, и сама кнопка не может знать, какая тема получилась.

Сам переключатель

Иконка — чистый CSS, считанный прямо с атрибута темы, поэтому она верна уже при первой отрисовке, до запуска любого скрипта. Она показывает, на что переключит клик.

stack({ direction: 'row', gap: 'md', align: 'center' },
  themeToggle(),
  themeToggle({ variant: 'soft' }),
  themeToggle({ variant: 'outline' }),
)

Эти кнопки работают — страница подгружает рантайм. Клик выставляет data-su-theme на <html> — это собственный атрибут sitelo-ui, поэтому меняются только компоненты sitelo-ui на этой странице. Остальной сайт следует своему data-theme, который задаёт переключатель в верхней панели. На вашем сайте он был бы один.

В панели приложения

appBar({ brand: 'sitelo' },
  appBarNav(navLink({ href: '#docs', current: true }, 'Документация')),
  appBarSpacer(),
  appBarActions(
    themeToggle(),
    button({ size: 'sm' }, 'Начать'),
  ),
)

Как определяется тема

По порядку: явный data-theme или data-su-theme на любом предке побеждает; если их нет, решает prefers-color-scheme. Оба имени атрибутов учитываются, чтобы sitelo-ui мог жить внутри сайта, у которого уже есть собственный переключатель темы, — ровно так и устроена эта документация.

Управлять самому

Рантайм экспортирует те же функции, которыми пользуется кнопка, — для собственного элемента управления или переключателя из трёх положений: светлая / тёмная / системная.

import { getTheme, setTheme, toggleTheme } from 'sitelo/ui/client'

getTheme()          // 'light' | 'dark' — вычисленная, не сохранённая
toggleTheme()       // переключить
setTheme('dark')    // закрепить
setTheme('system')  // снять переопределение и снова следовать за ОС

Пропсы

ПропТипПо умолчаниюОписание
labelstring'Toggle dark mode'Доступное имя и всплывающая подсказка.
variant'solid' | 'soft' | 'outline' | 'ghost' | 'link''ghost'Вариант кнопки.
color'primary' | 'neutral' | 'success' | 'warning' | 'danger''neutral'Из какой палитры брать цвета.

themeScript() принимает необязательный nonce — для сайта с политикой безопасности содержимого.