Темизация приложений

Темизация приложения

Темы Q.Palette основаны на CSS Custom Properties (opens in a new tab): тема — это обычный CSS-файл, который переопределяет значения токенов. Благодаря этому тему можно менять на лету, без перезагрузки страницы и без пересборки приложения. Для токенов Q.Palette зарезервирован префикс --q- — учитывайте это, создавая собственные переменные.

Темизация состоит из двух независимых осей:

ОсьАтрибут на <html>Значения
Темаdata-color-themesoftui (по умолчанию), minimalism, идентификатор вашей темы
Цветовая схемаdata-color-schemelight, dark

Как приложение применяет тему

Рутовое приложение хранит выбранную тему и схему в localStorage, выставляет соответствующие атрибуты на <html> и подгружает CSS-файл темы в заранее объявленный тег <link id="theme-file"> в index.html.

Файл темы берётся из ассетов рутового приложения — assets/themes/<id>.css. Чтобы обновить тему на стенде, нужно обновить ассеты образа.

Посмотреть, как токены работают в живом интерфейсе, можно на странице «Темизация приложения» (opens in a new tab) портала для разработчиков: там значения токенов меняются селектором цвета и сразу применяются к области предпросмотра.

Создание собственной темы

Возьмите за основу готовую тему

Файлы поставляемых тем лежат в пакете @diasoft/qpalette-themes:

node_modules/@diasoft/qpalette-themes/assets/softui.css
node_modules/@diasoft/qpalette-themes/assets/minimalism.css

Скопируйте подходящий файл и переименуйте его, например в my-theme.css.

⚠️

Файл темы самодостаточен: рутовое приложение подменяет содержимое #theme-file целиком, поэтому тема должна содержать полный набор токенов. «Частичную» тему из нескольких переменных сделать нельзя — недостающие токены не подхватятся из другой темы.

Замените идентификатор в селекторах

В скопированном файле укажите идентификатор своей темы:

/* светлая схема */
html[data-color-theme='my-theme']:not(data-color-scheme),
html[data-color-theme='my-theme'][data-color-scheme='light'] {
  /* ... */
}
 
/* тёмная схема */
html[data-color-theme='my-theme'][data-color-scheme='dark'] {
  /* ... */
}

Задайте нужные значения токенов

--q-page-background: #fffdf5;
--q-page-text: #e18e46;
--q-page-text-secondary: hsl(55, 73%, 42%);

Разместите файл темы

Файл кладётся в ассеты рутового приложения — src/assets/themes/my-theme.css.

Зарегистрируйте тему в конфигурации

config.base.json
{
  "theme": {
    "themes": [
      { "name": "My Theme", "id": "my-theme" }
    ]
  }
}

Скелет файла темы

Файл темы состоит из трёх блоков: два по схемам и один общий. Токены, значения которых вы не меняете, оставляйте такими же, как в исходном файле, — удалять их нельзя.

my-theme.css
/* 1. Светлая схема: палитра и цветовые токены компонентов */
html[data-color-theme='my-theme']:not(data-color-scheme),
html[data-color-theme='my-theme'][data-color-scheme='light'] {
  --q-font-family: 'Inter', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Arial, sans-serif;
  --q-is-dark-scheme: 0;
 
  /* палитра */
  --q-base-0: white;
  --q-base-500: #69727b;
  --q-base-1000: black;
  --q-primary-500: #3b82f6;
  --q-primary: var(--q-primary-500);
  /* …остальные рампы и семантические токены — из исходного файла */
 
  /* токены компонентов */
  --q-sidebar-bg: var(--q-content-background);
  --q-sidebar-text: var(--q-content-text);
  /* … */
}
 
/* 2. Тёмная схема: те же токены с другими значениями */
html[data-color-theme='my-theme'][data-color-scheme='dark'] {
  --q-is-dark-scheme: 1;
 
  --q-base-0: black;
  --q-base-500: #969ca3;
  --q-base-1000: white;
  /* … */
}
 
/* 3. Общая часть: размеры, радиусы и типографика — от схемы не зависят */
html[data-color-theme='my-theme'] {
  --q-border-radius-sm: 0.25rem;
  --q-border-radius-md: 0.375rem;
  --q-border-radius-lg: 0.5rem;
  /* … */
}

Настройка через конфигурацию

Раздел theme в config.json управляет и списком доступных тем, и тем, что именно увидит пользователь.

ПолеНазначение
theme.themesСписок тем в панели настроек: name и id каждой темы
theme.themeФиксирует тему: выбор темы в панели настроек скрывается
theme.schemeФиксирует цветовую схему: выбор схемы в панели настроек скрывается
theme.defaultThemeТема при первом посещении, пользователь может её сменить
theme.defaultSchemeСхема при первом посещении
config.base.json
{
  "theme": {
    "defaultScheme": "light",
    "defaultTheme": "softui",
    "themes": [
      { "name": "SoftUI", "id": "softui" },
      { "name": "Минимализм", "id": "minimalism" },
      { "name": "My Theme", "id": "my-theme" }
    ]
  }
}

Что применяется при старте

Сначала приложение собирает список доступных тем, затем выбирает из него тему и цветовую схему. Список берётся из первого непустого источника:

  1. themes — устаревший вариант записи на верхнем уровне конфигурации;
  2. theme.themes;
  3. список по умолчанию — SoftUI и Минимализм.

Тема и схема выбираются независимо друг от друга, по одному и тому же правилу — первое заданное значение сверху вниз:

ПриоритетТемаЦветовая схема
1theme.theme — фиксация, выбор в настройках скрытtheme.scheme — фиксация, выбор в настройках скрыт
2выбор пользователя из localStorage, если такая тема есть в спискевыбор пользователя из localStorage
3theme.defaultThemetheme.defaultScheme
4первая тема из спискаlight

Список тем формируется всегда, даже когда тема зафиксирована через theme.theme: он остаётся источником запасного значения и наполняет панель настроек там, где выбор доступен.

Совместимость со старыми конфигурациями: color.scheme читается как тема, color.theme — как схема, color.defaultScheme и color.defaultTheme — как значения по умолчанию для них же. Эти поля объявлены устаревшими и будут удалены в 9.0.0 — используйте раздел theme.

Структура файла темы

Файл темы состоит из четырёх частей:

  1. Палитра светлой схемы — цветовые рампы и семантические токены под [data-color-scheme='light'].
  2. Палитра тёмной схемы — те же токены под [data-color-scheme='dark'].
  3. Цветовые токены компонентов--q-button-*, --q-input-*, --q-sidebar-* и т. д.
  4. Размерные токены — размеры, отступы, радиусы и типографика. Они не зависят от схемы и задаются один раз.

Токены именуются по шаблону --q-<группа>[-модификатор][-шаг|состояние]. Рампа каждого цвета содержит шаги от -0 (белый) до -1000 (чёрный), алиас без шага, полупрозрачные варианты -transparent-* и тени -shadow-*:

--q-primary-50: #e8f1f8;
--q-primary-500: #3b82f6;
--q-primary-900: #061725;
--q-primary: var(--q-primary-500);
--q-primary-transparent-100: rgba(29, 113, 184, 0.1);

Компонентные токены, как правило, ссылаются на семантический слой, а не на конкретные цвета — так тема остаётся согласованной:

--q-sidebar-bg: var(--q-content-background);
--q-sidebar-text: var(--q-content-text);
--q-sidebar-hover: var(--q-primary-500);
--q-sidebar-active-bg: var(--q-primary-transparent-100);
--q-sidebar-active-text: var(--q-primary-700);
--q-sidebar-border: var(--q-content-border);
--q-sidebar-icon: var(--q-base-500);
⚠️

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

Полный перечень токенов смотрите прямо в файлах поставляемых тем — softui.css и minimalism.css пакета @diasoft/qpalette-themes. Это точный и всегда актуальный источник: набор токенов меняется вместе с версией Q.Palette.

Проверка результата

Откройте приложение и переключите тему в панели настроек. Убедитесь, что на элементе <html> выставлены ожидаемые data-color-theme и data-color-scheme, а в <link id="theme-file"> подставлен адрес вашего файла. Значения конкретных токенов удобно смотреть в инструментах разработчика, на селекторе html.

Если тема не применилась, проверьте: совпадает ли id в конфигурации с идентификатором в селекторах файла, доступен ли файл по своему адресу (вкладка Network), и не зафиксирована ли другая тема через theme.theme.