SusSkin

Механика скина — применяет обнаруженный дескриптор скина к живому дереву VisualElement: layout-листы остаются прикреплены независимо от того, включён скин или нет, поэтому классы композиции .sharq продолжают разрешаться; brand-листы (токены/переопределения) прикрепляются только пока скин включён — именно это означает «выключено → стандартный вид SUS». Необязательный слой component приносит небольшие листы переопределений в каждый компонент, пока скин включён. Классы root/surface переключаются обычным USS, переключая поверхность между glass и paper.
Пакет
SusKit · Сервисы (коммерческий)
SusSkin — обычный статический класс C#, не компонент .sharq. Сам Kit никогда не называет конкретный скин — каждый скин поставляется как собственный ассет-дескриптор (SusSkinAsset) и подключается через ту же механику, будь то бесплатный layout-only скин или платный brand-скин-набор.
Использование
// Fluent SusApp entry — layout sheets always, brand + component sheets and fonts only when enabled
SusApp.Create(document)
.UseSkin(mySkinAsset, enabled: true)
.Run();
// Re-apply on a live root (surface defaults to the descriptor's DefaultSurface)
SusSkin.Apply(root, mySkinAsset, enabled: true, SusSkinSurface.Glass);
// Remove the skin entirely — classes off, layout, brand AND component sheets detached
SusSkin.Off(root, mySkinAsset);| Член | Роль |
|---|---|
UseSkin(skin, enabled) | Fluent-вход SusApp — layout-листы всегда, brand- и component-листы и шрифты при включении |
Apply(root, skin, enabled, surface?) | Переключает классы root/surface, (пере)прикрепляет листы на живом корне, добавляет или снимает слой component — идемпотентно |
Off(root, skin) | Отсоединяет всё, включая layout-листы и слой component — для окончательного ухода из дерева |
AttachLayoutSheets(element, skin) | Только layout-листы, для поддеревьев вне корневой панели приложения |
Дескриптор скина
Скин — это данные: дескриптор sus-skin.<id>.json (схема sus-skin/v1), который разбирает SusSkinAsset. Элементы листов — пути Resources.
{
"schema": "sus-skin/v1",
"id": "myskin",
"class": "myskin-skin",
"sheets": {
"layout": ["SusRuntime/myskin-screens"],
"brand": ["SusRuntime/myskin-tokens", "SusRuntime/myskin-overrides"],
"component": ["SusRuntime/myskin-component-overrides"]
},
"surfaces": { "glass": "myskin-skin--glass", "paper": "myskin-skin--paper" },
"defaultSurface": "glass"
}| Слой | Куда прикрепляется | Когда | Что в нём лежит |
|---|---|---|---|
sheets.layout | Корень скина | Всегда, пока скин присутствует, включён он или нет | Классы композиции для собственного .sharq-обрамления скина |
sheets.brand | Корень скина | Только пока скин включён | Дизайн-токены (custom properties) и переопределения, написанные под классом скина |
sheets.component (необязательный) | Каждый стилизованный компонент под корнем скина, после собственного сгенерированного листа компонента | Только пока скин включён | Небольшие листы только с переопределениями, написанные без префикса класса скина, — без токенов |
Дескриптор без sheets.component оставляет листы стилей каждого компонента ровно такими же, как без скина.
Как побеждают правила бренда
UI Toolkit разрешает конфликт между правилами из разных листов сначала по специфичности. Только при равной специфичности побеждает лист, прикреплённый ниже по иерархии. Каждый стилизованный компонент Kit несёт собственный сгенерированный лист (.g.uss) на самом элементе компонента, поэтому правило бренда на корне с той же специфичностью, что и правило Kit, ему проигрывает — остаётся вид Kit.
Заставить правило бренда победить можно двумя способами.
По умолчанию: переопределения под классом скина
Предваряйте каждое переопределение корневым классом скина (class дескриптора). Один лишний класс поднимает специфичность выше одноклассового правила Kit, и правило побеждает с корня. Это ничего не стоит в рантайме и не требует дополнительного слоя.
/* Loses: (0,1,0) on the root ties with (0,1,0) on the component itself */
.sus-menu-button { border-width: 1px; }
/* Wins: (0,2,0) beats the kit's (0,1,0) */
.myskin-skin .sus-menu-button { border-width: 1px; }Если правило Kit само составное, повторите под префиксом весь селектор Kit. Одноклассового префикса там недостаточно: .myskin-skin .sus-menu-button — это (0,2,0), столько же, сколько у составного .sus-menu-button--flat.sus-menu-button--color-primary в Kit, а ничья достаётся собственному листу компонента.
/* Wins: (0,3,0) beats the kit's compound (0,2,0) */
.myskin-skin .sus-menu-button--flat.sus-menu-button--color-primary { background-color: var(--myskin-accent); }Выключение скина (Apply(root, skin, enabled: false)) снимает класс скина и brand-листы, так что ни одно переопределение с префиксом больше не совпадает, и возвращается вид Kit.
По выбору: слой component
Скин, написанный как веб-CSS — переопределения без префикса класса скина в расчёте на то, что правило равной специфичности победит, — перечисляет такие листы в sheets.component. Пока скин включён, SusSkin добавляет их после собственного сгенерированного листа каждого стилизованного компонента под корнем скина, так что правило равной специфичности побеждает:
/* In a sheets.component sheet, on a SusMenuButton that carries the class my-screen__back-btn:
(0,1,0) now beats the kit's .sus-menu-button (0,1,0) */
.my-screen__back-btn { border-width: 1px; }- Только переопределения, без токенов. Слой добавляется на каждом уровне вложенности, так что держите его небольшим. Custom properties, заданные в
sheets.brandна корне, и так наследуются до каждого компонента. - Выключение возвращает вид Kit. Отключение или снятие скина убирает слой из каждого компонента, в который он был добавлен.
- Применяйте скин к корню приложения. Оверлеи (меню, диалоги, тултипы) получают слой, только если слой оверлеев находится под корнем, к которому применён скин, — используйте
UseSkinнаSusAppилиApplyнаSusApp.Root. Компонент, смонтированный прямо в слой оверлеев вне корня скина, слоя не получает; оверлеи, открытые из компонента под корнем, получают. - Компоненты, созданные позже, подхватывают слой, когда прикрепляются к панели.
Заметки
- Surface — двусторонний выбор —
SusSkinSurface.GlassилиSusSkinSurface.Paper— объявляется в дескрипторе скина какDefaultSurface, переопределяется на вызовApply. - Storybook story Skin (
skin): обнаруживает любой пакет скина, который линкует проект (так же, как окно Skins), и показывает его рядом со стандартным видом SUS, с переключателем «Skin enabled» и переключателем поверхности glass/paper. - Hub shot
kit-skin.png— витрина (ожидает съёмки).