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

Скин компонентов

Уровень скина компонентов перестилизует встроенные компоненты. Он строится на конкретном стеке стилизации и стабильном контракте хуков.

Стек стилизации

Встроенный UI использует четыре технологии вместе:

  • CSS Modules для стилей в области компонента, с хэшированными именами классов, которые явно не являются публичным контрактом.
  • CSS Custom Properties для семантических токенов (--st-*).
  • Cascade Layers для упорядочивания источников истины.
  • Container Queries для макета, адаптирующегося к контейнеру самого компонента, с размерами в rem.

Темы нацеливаются на атрибуты хуков, а не на генерируемые имена классов.

Порядок каскадных слоёв

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

@layer reset, tokens, base, components, plugin-base, theme, user;

Более поздние слои побеждают более ранние, поэтому приоритет таков:

  1. reset — базовый сброс.
  2. tokens — определения токенов.
  3. base — значения по умолчанию на уровне элементов.
  4. components — стили встроенных компонентов.
  5. plugin-base — слой для базовых стилей, предоставляемых плагинами.
  6. theme — скин активной темы.
  7. user — собственные оверрайды пользователя, которые загружаются последними.

Таблица стилей пользовательских оверрайдов всегда загружается последней, поэтому сломанная или навязчивая тема никогда не сможет помешать пользователю переопределить её. В терминах !important: конструкция запрещена в CSS темы, кроме слоя предпочтений доступности, который относится к пользовательским режимам a11y.

Контракт хуков

Темы стилизуют компоненты через четыре атрибута, публикуемых хостом и версионируемых как и остальной SDK:

<div
data-component="chat-message"
data-part="container"
data-role="assistant"
data-state="streaming"
></div>
  • data-component — вид компонента.
  • data-part — структурная часть внутри компонента.
  • data-role — семантическая роль, например роль сообщения.
  • data-state — состояние, например open, closed или streaming.

CSS скина темы тогда выглядит так:

@layer theme {
[data-component='button'][data-variant='primary'] > [data-part='icon'] {
color: var(--st-color-accent-text);
}

[data-component='action-bar'] [data-part='group'][data-role='secondary'] {
color: var(--st-color-text-secondary);
}
}

Пакет @neotavern/theme-sdk экспортирует хелпер dataHook для построения этих объектов атрибутов, чтобы авторы компонентов и авторы тем согласовывали одни и те же имена.

Что не является контрактом

  • Генерируемые имена классов CSS-modules — хэшированные, нестабильные и не входящие в SDK. Тема, нацеленная на них, ломается при следующей сборке.
  • Внутренняя иерархия React — темы не должны зависеть от внутренностей компонентов или порядка DOM сверх документированных хуков.
  • Числовые значения макета — координаты, схемы grid и контрольные точки нельзя стилизовать через контракт токенов; контрольные точки области просмотра живут в реестре, а container queries должны писаться в rem.

Запрещённый CSS

Таблицы стилей тем сканируются до загрузки. Запрещённые конструкции отклоняются при установке и проверке:

  • @import
  • URL javascript: и expression().
  • -moz-binding и behavior:.
  • Удалённые или протокол-относительные URL (url(http:, url(https:, url(//).
  • data:text/html.
  • !important (кроме слоя предпочтений a11y).

Это держит CSS тем чистым, локальным и безопасным. О токенах, на которые скин должен ссылаться, см. Дизайн-токены; об именованных областях, которые может перестилизовать скин, см. Контракт оболочки.