Статьи Тематизация книг на Radix Colors и CSS Tokens
Статья

Тематизация книг на Radix Colors и CSS Tokens

Подробное руководство по системе темизации книг в проекте: Radix-шкалы 1..12, семантические токены, scoped-темы и практический workflow.

cssradix-colorsdesign-systemthemingastro

Зачем нужна отдельная система темизации книг

Когда книг становится несколько, у каждой появляется собственный визуальный характер:

  • у одной акцент на «технический» холодный стиль,
  • у другой — тёплый «редакционный» стиль,
  • у третьей — более нейтральная учебная палитра.

Если управлять этим через точечные правки CSS-компонентов, система быстро разваливается: появляются случайные цвета, дублирование и поломки контраста.

Поэтому в проекте используется token-first подход:

  1. У каждой книги есть свой theme.css.
  2. В theme.css настраиваются только переменные.
  3. Компоненты (prose, sidebar, TOC, header) читают только семантические токены.

Архитектура темизации в проекте

1. Где лежит тема книги

Файл темы находится рядом с контентом книги:

src/content/books/<book-id>/theme.css

Примеры:

  • src/content/books/effect/theme.css
  • src/content/books/hexagonal-architecture/theme.css

2. Где тема применяется

На страницах книги корневой контейнер получает атрибуты:

<div data-page-kind="book" data-book-id="effect">...</div>

Тема книги навешивается через селектор:

[data-page-kind='book'][data-book-id='effect'] {
  /* book tokens */
}

Это важно: тема привязана к конкретной книге и не протекает на другие разделы.

3. Как тема подключается

BaseLayout автоматически подключает theme.css книги через bookThemeHref.

Итог: при открытии страницы книги в DOM присутствуют:

  • CSS-файл именно этой книги,
  • корректный data-book-id на корневом контейнере,
  • переменные темы доступны всем дочерним компонентам.

Профили тем в этом проекте

Чтобы книги не выглядели одинаково, у них должны быть разные профили уже на уровне шкал:

  • effect: холодная slate + cyan палитра, более компактный ритм чтения, UI выглядит «технически».
  • hexagonal-architecture: тёплая sand + amber палитра, чуть более «книжная» типографика и увеличенный вертикальный ритм.

Технически это означает, что в theme.css каждой книги отличаются минимум:

  • --book-gray-1..12,
  • --book-accent-1..12,
  • хотя бы часть typography/layout токенов.

Почему именно Radix Colors

Radix использует шкалы 1..12:

  • 1..2 — самые фоновые значения,
  • 3..6 — поверхности и границы,
  • 7..9 — активные/интерактивные состояния,
  • 10..12 — контрастные тексты и выделения.

Такой формат делает тему предсказуемой. Вместо «подбора отдельных hex по месту» ты настраиваешь две шкалы:

  • gray — нейтральная система,
  • accent — акцентная система.

Слой 1: Scale Tokens

В теме книги задаются только шкалы:

[data-page-kind='book'][data-book-id='effect'] {
  --book-gray-1: #0c1118;
  --book-gray-2: #121924;
  /* ... */
  --book-gray-12: #e7f1ff;

  --book-accent-1: #09141a;
  --book-accent-2: #0d1b24;
  /* ... */
  --book-accent-12: #b9ecf7;
}

Слой 2: Semantic Tokens

В global.css семантика выводится из шкал:

--book-color-bg-primary: var(--book-gray-1);
--book-color-bg-secondary: var(--book-gray-2);
--book-color-bg-tertiary: var(--book-gray-3);
--book-color-bg-hover: var(--book-gray-4);

--book-color-text-primary: var(--book-gray-12);
--book-color-text-secondary: var(--book-gray-11);
--book-color-text-muted: var(--book-gray-10);

--book-color-accent: var(--book-accent-9);
--book-color-accent-hover: var(--book-accent-10);
--book-color-accent-muted: var(--book-accent-8);

--book-color-border: var(--book-gray-6);
--book-color-border-hover: var(--book-gray-7);

Плюс есть отдельные токены для типографики и layout.


Слой 3: Component Consumption

Компоненты не знают про gray-7 или accent-10. Они используют только семантику:

  • --color-bg-*
  • --color-text-*
  • --color-accent*
  • --color-border*

Это позволяет менять визуальный язык книги без переписывания компонентов.


Что можно настраивать кроме цветов

Система поддерживает не только палитру.

Типографика чтения

  • --book-prose-font-size
  • --book-prose-line-height
  • --book-prose-paragraph-spacing
  • --book-prose-heading-h1-size
  • --book-prose-heading-h2-size
  • --book-content-title-size

Макет

  • --book-layout-sidebar-width
  • --book-layout-toc-width
  • --book-layout-header-height

Шрифты

  • --book-font-sans
  • --book-font-mono

То есть у книги можно поменять не только цвет, но и «ритм» чтения.


Практический workflow для новой темы

  1. Скопируй существующий theme.css из ближайшей по стилю книги.
  2. Подбери gray 1..12 (сначала фон/текст, потом промежуточные ступени).
  3. Подбери accent 1..12 (ориентируйся на link/hover/active).
  4. Пройди страницу главы и проверь:
    • sidebar,
    • TOC,
    • кодовые блоки,
    • таблицы,
    • blockquote,
    • навигацию предыдущая/следующая.
  5. Донастрой типографику (font-size, line-height, h1/h2).

Как проверить, что темы книг действительно разные

Минимальная проверка:

diff -u src/content/books/effect/theme.css src/content/books/hexagonal-architecture/theme.css

Если diff пустой, книги визуально будут практически одинаковыми.

Дополнительно проверь в браузере:

  1. Страницы двух книг должны иметь разный data-book-id на корневом контейнере.
  2. У каждой книги должен подгружаться свой theme.css.
  3. В DevTools значения --book-accent-9 и --book-gray-1 должны отличаться.

Чеклист качества темы

  • Текст gray-12 читается на фоне gray-1 без напряжения.
  • gray-11 и gray-10 различимы как secondary/muted.
  • Акцент accent-9 хорошо читается в inline-ссылках.
  • Hover (accent-10) визуально отличается, но не «кричит».
  • Границы (gray-6, gray-7) видимы, но не перегружают интерфейс.
  • Кодовые блоки и таблицы остаются читаемыми.

Типичные ошибки

Ошибка 1: Настройка только accent, без нейтральной шкалы

Результат: цвета «красивые», но UI остаётся случайным.

Ошибка 2: Слишком близкие gray-10/11/12

Результат: исчезает иерархия текста.

Ошибка 3: Слишком яркий accent-9

Результат: ссылки и активные элементы доминируют над контентом.

Ошибка 4: Тема определяется вне scoped-селектора книги

Результат: тема протекает на другие страницы.

Ошибка 5: theme.css у разных книг скопирован без изменений

Результат: формально файлов несколько, но визуально тема одна и та же.


Минимальный шаблон theme.css

[data-page-kind='book'][data-book-id='my-book'] {
  --book-gray-1: #111113;
  --book-gray-2: #18191b;
  --book-gray-3: #212225;
  --book-gray-4: #272a2d;
  --book-gray-5: #2e3135;
  --book-gray-6: #363a3f;
  --book-gray-7: #43484e;
  --book-gray-8: #5a6169;
  --book-gray-9: #696e77;
  --book-gray-10: #777b84;
  --book-gray-11: #b0b4ba;
  --book-gray-12: #edeef0;

  --book-accent-1: #0d1520;
  --book-accent-2: #111927;
  --book-accent-3: #0d2847;
  --book-accent-4: #003362;
  --book-accent-5: #004074;
  --book-accent-6: #104d87;
  --book-accent-7: #205d9e;
  --book-accent-8: #2870bd;
  --book-accent-9: #0090ff;
  --book-accent-10: #3b9eff;
  --book-accent-11: #70b8ff;
  --book-accent-12: #c2e6ff;

  --book-prose-font-size: 16px;
  --book-prose-line-height: 1.8;
  --book-layout-sidebar-width: 272px;
  --book-layout-toc-width: 232px;
}

Итог

Тематизация книг должна быть не «набором случайных цветов», а устойчивой системой:

  • Scale tokens (Radix 1..12),
  • semantic aliases,
  • component-level consumption,
  • scoped application по книге.

Так можно быстро создавать визуально разные книги без регрессий в читабельности и без ручного переписывания компонентов.