Перейти к содержимому

Пресеты тем

Пять встроенных пресетов — это предлагаемое по умолчанию эстетическое решение lh-ui: каждый берёт основной цвет из традиционной китайской палитры и дополняет его полным набором светлой и тёмной цветовых схем.

Пресет name Идентификатор labelEn Описание Светлый основной цвет
青花瓷 (сине-белый фарфор) 'cerblue' LhCerblue Ceramic Blue Подглазурная роспись сине-белого фарфора, изящная и спокойная Нет
松花绿 (зелёный сосны) 'songhua' LhSonghua Pine Green Бамбуковая роща, полная жизни Да
朱砂 (киноварь) 'zhusha' LhZhusha Vermilion Красный киноварный цвет традиционных печатей, торжественный Нет
水墨 (тушь) 'shuimo' LhShuimo Ink Wash Тушевая живопись, сдержанная и минималистичная Нет
藤黄 (gamboge) 'golden' LhGolden Golden Autumn Жёлтый цвет клёнов поздней осени, тёплый и золотистый Да
青花瓷cerblue · Ceramic Blue

青花瓷釉下彩,清雅素净

选中项主色底文字
--lh-primary-color
#2B4C7C
--lh-primary-color-hover
#3D649E
--lh-primary-color-active
#1F3A5F
--lh-primary-color-bg
#E8EDF3
--lh-primary-color-border
#D4DCE8
松花绿songhua · Pine Green

竹林修竹,生机勃勃

选中项主色底文字
--lh-primary-color
#5B8C5A
--lh-primary-color-hover
#7BB079
--lh-primary-color-active
#4F8F4C
--lh-primary-color-bg
#E8F5E8
--lh-primary-color-border
#D0E8CF
--lh-color-on-primary
#101410
--lh-selected-color
#456F44
朱砂zhusha · Vermilion

传统印章朱砂红,喜庆庄重

选中项主色底文字
--lh-primary-color
#B23A3A
--lh-primary-color-hover
#C45050
--lh-primary-color-active
#9A3030
--lh-primary-color-bg
#FDF0F0
--lh-primary-color-border
#F0D8D8
水墨shuimo · Ink Wash

水墨丹青,素雅极简

选中项主色底文字
--lh-primary-color
#2C2C2C
--lh-primary-color-hover
#5A5A5A
--lh-primary-color-active
#1A1A1A
--lh-primary-color-bg
#F5F5F5
--lh-primary-color-border
#E0E0E0
藤黄golden · Golden Autumn

深秋枫黄,温暖金黄

选中项主色底文字
--lh-primary-color
#B8860B
--lh-primary-color-hover
#D4A843
--lh-primary-color-active
#A87F0A
--lh-primary-color-bg
#FBF6EA
--lh-primary-color-border
#F0E8D0
--lh-color-on-primary
#1E1A16
--lh-selected-color
#82600A

Пять базовых ключей (есть у всех пресетов)

Заголовок раздела «Пять базовых ключей (есть у всех пресетов)»
{
'--lh-primary-color': '...',
'--lh-primary-color-hover': '...',
'--lh-primary-color-active': '...',
'--lh-primary-color-bg': '...',
'--lh-primary-color-border': '...',
}

Два дополнительных ключа у пресетов со светлым основным цветом

Заголовок раздела «Два дополнительных ключа у пресетов со светлым основным цветом»

songhua (松花绿 (зелёный сосны)) и golden (藤黄 (gamboge)) — светлоосновные; контрастность белого текста на них не дотягивает до AA, поэтому для них обязательно добавить ещё два ключа:

Ключ Назначение
--lh-color-on-primary Цвет текста на кнопке основного цвета (для светлого основного цвета используется чёрный)
--lh-selected-color Цвет текста выделенного пункта (контрастность активного цвета в качестве текста на фоне при наведении недостаточна — цвет отдельно затемняется)

Почему это необходимо: светлоосновная кнопка с белым текстом даёт контрастность всего 3.x:1, что не достигает AA 4.5:1. Гейт verify:theme это пресечёт.

Пример с 松花绿 (зелёный сосны): в комментариях к исходному коду зафиксированы причины исправлений:

  • --lh-color-on-primary: 松花绿 (зелёный сосны) — светлый основной цвет, контрастность белого текста всего 3.93:1; чёрный текст даёт 4.73:1
  • --lh-selected-color: активный цвет в качестве текста на фоне при наведении даёт всего 3.48:1, для выделенного пункта цвет затемняется отдельно (на цвет фона активной кнопки это не влияет)
  • --lh-primary-color-active: исходный #4B7A4A давал 3.70:1 → #4F8F4C даёт 4.75:1

Для 藤黄 (gamboge) аналогично: белый текст 3.25:1 → чёрный текст 5.31:1; текст выделения 3.41:1 → затемнён до #82600A; active #9A7208 3.94:1 → #A87F0A 4.70:1.

Жёсткое требование при добавлении нового пресета со светлым основным цветом: обязательно задаются --lh-color-on-primary и --lh-selected-color, иначе гейт AA 4.5:1 в verify:theme завершится неудачей.

import { LH_THEME_PRESETS, getThemePreset, getThemeVars } from '@lh-ui/share/theme'
LH_THEME_PRESETS // Все пять
getThemePreset('cerblue') // Объект LhCerblue
getThemePreset('not-exists') // undefined
getThemeVars('cerblue')?.['--lh-primary-color']
import { buildPresetStyleText, LH_PRESET_THEME_STYLE_ID } from '@lh-ui/share/theme'
function applyPreset(name: LhThemePresetName) {
const vars = getThemeVars(name)
if (!vars) return
const text = buildPresetStyleText(vars)
let style = document.getElementById(LH_PRESET_THEME_STYLE_ID)
if (!style) {
style = document.createElement('style')
style.id = LH_PRESET_THEME_STYLE_ID
document.head.appendChild(style)
}
style.textContent = text // Заменяет, а не дописывает: при переключении темы старые пользовательские стили не остаются
}

Ключевые моменты (см. ограничение инъекции в обзоре системы тем): создавать можно только элементы <style>, а не встроенный style на documentElement — иначе цветовая палитра тёмной темы исказится.

<!-- lh-ui-plus / lh-ui-vue2 -->
<lh-config-provider theme="cerblue">
<App />
</lh-config-provider>

Prop theme принимает LhThemePresetName, а внутри компонента выполняется описанная выше логика инъекции. Страница настройки темы и ThemeStudio на сайте docs проходят по LH_THEME_PRESETS и автоматически выводят все пресеты — после добавления нового пресета страницы документации в библиотеках править вручную не нужно.

import { registerTheme, getThemePreset } from '@lh-ui/share/theme'
registerTheme({
name: 'my-brand',
label: 'Брендовый цвет',
labelEn: 'Brand',
description: 'Основной брендовый цвет компании',
vars: {
'--lh-primary-color': '#722ED1',
'--lh-primary-color-hover': '#9254DE',
'--lh-primary-color-active': '#531DAB',
'--lh-primary-color-bg': '#F9F0FF',
'--lh-primary-color-border': '#D3ADF7',
// Для светлоосновного пресета нужно добавить ещё два:
// '--lh-color-on-primary': '#101410',
// '--lh-selected-color': '#...',
},
})
getThemePreset('my-brand') // Зарегистрировали — можно использовать

Семантика registerTheme:

  • Одноимённое переопределение: registerTheme({ name: 'cerblue', ... }) перекроет встроенный пресет 青花瓷 (сине-белый фарфор) — это сделано осознанно, чтобы сторона бизнеса могла настроить тему по умолчанию, не трогая компоненты.
  • Новые имена добавляются в конец массива: порядок LH_THEME_PRESETS — «пять встроенных + зарегистрированные».
  • Реестр — состояние уровня модуля: импортировали — им пользуются; на всё приложение один экземпляр.

Процесс добавления нового встроенного пресета

Заголовок раздела «Процесс добавления нового встроенного пресета»
  1. Добавить объект LhThemePreset в src/theme/themes/index.ts (как минимум пять --lh-primary-*; для пресета со светлым основным цветом обязательно добавить --lh-color-on-primary и --lh-selected-color).
  2. Добавить в массив LH_THEME_PRESETS и дополнить имя в реэкспорте src/theme/index.ts.
  3. Запустить pnpm test (в theme.spec есть регрессия согласованности пресетов) + pnpm verify:theme (гейт AA 4.5:1).
  4. Приложить changeset; страница настройки темы в документации библиотеки автоматически выведет новый пресет.

Важно: vars служат только для потребления в runtime на JS; основной цвет, используемый в компонентных SCSS, по-прежнему находится в styles/theme/common/variables.scss — при переопределении основного цвета встроенной темы менять нужно в двух местах (в theme.spec есть регрессия).

Строковые значения пресетов (name: 'cerblue') — это конфигурационные значения, которые пользователи пишут в theme ConfigProvider; их изменение сломает все downstream-конфигурации — это один из пунктов реестра исключений из правил именования. Соответствующие TS-идентификаторы тем не менее несут префикс (LhCerblue).

  • Незарегистрированное имя возвращает undefined: getThemePreset / getThemeVars не выбрасывают исключений — слою UI нужно не забывать проверять на пустоту.
  • --lh-primary-color-active и --lh-selected-color — разные вещи: первый — это цвет фона нажатой кнопки, второй — цвет текста в списках / выделенных пунктах. В пресетах со светлым основным цветом контрастность активного цвета в качестве текста выделения недостаточна — именно поэтому нужен отдельный --lh-selected-color.
  • Тёмная тема пресетов с тёмным основным цветом осветляется автоматически: buildPresetDarkVars определяет, что контрастность основного цвета относительно тёмного фона страницы #1A1A2E ниже 3, и осветляет его (см. Обзор системы тем).

Copyright © 2024-2026 FengMo WenXue