Gavia UIv1.0.0

Дизайн-система

Правила для текста, цветов, отступов и состояний компонентов. Токены и примеры для пяти тем.
60 компонентов447 токенов113 иконок5 тем

01 / Основы

Действия, состояния и группы

Выделяйте одно основное действие. Обозначайте состояние текстом или иконкой вместе с цветом. Объединяйте связанные элементы отступами и общим фоном.

Подписи и состояния

Называйте действие прямо. Показывайте загрузку, ошибку и результат.

Размеры и поведение

Используйте общие размеры и отступы. Одинаковые элементы должны работать одинаково.

Доступность

Клавиатура, видимый фокус, подписи полей и достаточный контраст.

Gavia

Светлая тема со шрифтом Gavia Sans.

Gavia Dark

Тёмная тема с бирюзовым акцентом и шрифтом Gavia Sans.

Classic

Светлая тема с синим акцентом.

Classic Dark

Тёмная тема с цветами для статусов.

Newspaper

Светлая тема с тёплым фоном под бумагу.

Поверхность

Карточки и разделы / elevation-surface

Всплывающий слой

Меню и панели / elevation-floating

02 / Типографика

Роли текста

Размер задаётся ролью. Семантические h1–h6 сохраняют структуру документа; класс определяет внешний вид. Newspaper использует свои шрифты через те же токены.

display

40px / 48px · 700

Display

Главный заголовок вступления; один на экран.

title

28px / 36px · 700

Заголовок страницы

Название страницы и крупного диалога.

heading

20px / 28px · 650

Заголовок раздела

Раздел страницы и самостоятельный блок.

subheading

16px / 24px · 600

Заголовок блока

Карточка, группа полей, небольшой диалог.

body

14px / 20px · 400

Основной текст

Описания, инструкции, текст формы.

small

12px / 18px · 400

Компактный текст

Подписи и вспомогательный текст.

label

13px / 20px · 500

Метка

Короткая подпись действия или поля.

code

12px / 18px · 400

Код и данные

Токены, идентификаторы и технические значения.

Текст основного сценария — body, пояснения — small + text-muted. Ограничивайте длинную строку примерно 60–75 символами. --wl-text-3 оставлен для декоративных деталей.

03 / Сетка и отступы

Шкала отступов

Малая группа — 8 px, поля формы — 16 px, карточка — 24 px, разделы — 48–64 px. Компактная плотность подходит для экранов с большим количеством данных.

none0px
2xs2px
xs4px
sm8px
md12px
lg16px
xl24px
2xl32px
3xl48px
4xl64px

Адаптивная сетка

Карточка A
Карточка B

Карточки автоматически переходят в одну колонку. Контейнер: 1240px.

HTML · примитивы компоновки
<section class="wl-container">
  <div class="wl-stack" data-space="xl">
    <h1 class="wl-text-title">Заголовок страницы</h1>
    <div class="wl-grid" data-space="lg">
      <article class="wl-surface">Содержимое</article>
    </div>
  </div>
</section>
sm: 640 pxmd: 900 pxlg: 1200 px

CSS подключается явно: styles/primitives.css. На узком экране сохраняйте логичный порядок чтения, переносите действия и используйте горизонтальную прокрутку только внутри таблиц.

04 / Токены

Каталог значений

Foundation → semantic → component. Каталог, CSS и типы генерируются из tokens/source.json. Значения ниже соответствуют теме gavia.

CSS · настройка токенов
.page {
  color: var(--wl-text);
  background: var(--wl-bg);
  gap: var(--wl-space-lg);
}
/* Настройка конкретного компонента */
.page-actions { --wl-btn-height: var(--wl-control-height-lg); }
Слой
Категория

Найдено токенов: 171 / 447

Токен / рольСсылкаЗначение
--wl-type-text-rendering

Режим рендеринга текста выбранной темы.

semantic
var(--wl-font-text-rendering)geometricPrecision
--wl-bg

Основная поверхность страницы и контента.

semantic
var(--wl-palette-bg)#faf9f6
--wl-bg-raised

Светлая поверхность карточек и локальных панелей над фоном страницы.

semantic
var(--wl-palette-bg-raised)#fefdfb
--wl-bg-soft

Сгруппированные блоки и вторичные поверхности.

semantic
var(--wl-palette-bg-soft)#eef2f3
--wl-bg-hover

Поверхность интерактивного элемента при наведении.

semantic
var(--wl-palette-bg-hover)#e5ecef
--wl-border

Тонкие разделители поверхностей.

semantic
var(--wl-palette-border)#d5dfe3
--wl-border-2

Усиленная граница группы.

semantic
var(--wl-palette-border-2)#b8c7ce
--wl-text

Основной читаемый текст.

semantic
var(--wl-palette-text)#0f1a23
--wl-text-accent

Акцентный текст ссылок, мягких действий и выбранных пунктов на стандартных и мягких поверхностях.

semantic
var(--wl-palette-text-accent)#326179
--wl-text-accent-hover

Акцентный текст при наведении на ссылки и мягкие действия.

semantic
var(--wl-palette-accent-hover)#326179
--wl-text-2

Вторичный читаемый текст и подписи.

semantic
var(--wl-palette-text-2)#5b6470
--wl-text-3

Приглушённые декоративные метаданные; не для обязательных инструкций.

semantic
var(--wl-palette-text-3)#75818c
--wl-accent

Акцент для выбора, ссылок и основных действий.

semantic
var(--wl-palette-accent)#3c7490
--wl-accent-hover

Акцент при наведении.

semantic
var(--wl-palette-accent-hover)#326179
--wl-accent-soft

Цвет роли accent-soft.

semantic
var(--wl-palette-accent-soft)#dfe8eb
--wl-accent-border

Цвет роли accent-border.

semantic
var(--wl-palette-accent-border)#b8cbd3
--wl-accent-soft-hover

Цвет роли accent-soft-hover.

semantic
var(--wl-palette-accent-soft-hover)#d3dfe4
--wl-accent-border-hover

Цвет роли accent-border-hover.

semantic
var(--wl-palette-accent-border-hover)#9eb7c2
--wl-on-accent

Исторический цвет на акцентной поверхности.

semantic
var(--wl-palette-on-accent)#ffffff
--wl-success

Сигнал успешного результата.

semantic
var(--wl-palette-success)#2e9e68
--wl-success-soft

Цвет роли success-soft.

semantic
var(--wl-palette-success-soft)#eaf6f0
--wl-success-border

Цвет роли success-border.

semantic
var(--wl-palette-success-border)#cdeadb
--wl-warn

Сигнал предупреждения.

semantic
var(--wl-palette-warn)#bf8615
--wl-warn-soft

Цвет роли warn-soft.

semantic
var(--wl-palette-warn-soft)#fbf4e2
--wl-warn-border

Цвет роли warn-border.

semantic
var(--wl-palette-warn-border)#f0dfae
--wl-danger

Сигнал опасного действия или ошибки.

semantic
var(--wl-palette-danger)#ab4448
--wl-danger-hover

Цвет роли danger-hover.

semantic
var(--wl-palette-danger-hover)#963c3f
--wl-danger-soft

Цвет роли danger-soft.

semantic
var(--wl-palette-danger-soft)#f7eeed
--wl-danger-soft-hover

Цвет роли danger-soft-hover.

semantic
var(--wl-palette-danger-soft-hover)#f3e5e4
--wl-danger-border

Цвет роли danger-border.

semantic
var(--wl-palette-danger-border)#e5c6c5
--wl-info-text

Цвет роли info-text.

semantic
var(--wl-palette-info-text)#1e3f8f
--wl-ok-text

Цвет роли ok-text.

semantic
var(--wl-palette-ok-text)#1c6b47
--wl-warn-text

Цвет роли warn-text.

semantic
var(--wl-palette-warn-text)#7d5a0e
--wl-err-text

Цвет роли err-text.

semantic
var(--wl-palette-err-text)#ab4448
--wl-mask-bg

Затемнение фона модального окна.

semantic
var(--wl-palette-mask-bg)rgba(15, 26, 35, 0.28)
--wl-avatar-bg

Цвет роли avatar-bg.

semantic
var(--wl-palette-avatar-bg)#253540
--wl-tooltip-bg

Поверхность краткой подсказки.

semantic
var(--wl-palette-tooltip-bg)#0f1a23
--wl-tooltip-text

Текст краткой подсказки.

semantic
var(--wl-palette-tooltip-text)#ffffff
--wl-control-height-md

Роль btn-height.

semantic
var(--wl-dimension-btn-height)40px
--wl-control-height-sm

Роль btn-height-sm.

semantic
var(--wl-dimension-btn-height-sm)32px
--wl-control-height-lg

Роль btn-height-lg.

semantic
var(--wl-dimension-btn-height-lg)48px
--wl-control-height-xs

Роль btn-height-xs.

semantic
var(--wl-dimension-btn-height-xs)26px
--wl-corner-control

Роль btn-radius.

semantic
var(--wl-radius)8px
--wl-corner-control-sm

Роль btn-radius-sm.

semantic
var(--wl-radius-sm)6px
--wl-control-padding-inline

Роль btn-pad-x.

semantic
var(--wl-dimension-btn-pad-x)14px
--wl-type-control-size

Роль btn-font-size.

semantic
var(--wl-dimension-btn-font-size)13.5px
--wl-corner-input

Роль input-radius.

semantic
var(--wl-dimension-input-radius)6px
--wl-focus-shadow

Роль focus-ring.

semantic
0 0 0 3px var(--wl-accent-soft)0 0 0 3px #dfe8eb
--wl-focus-invalid-shadow

Роль focus-ring-danger.

semantic
0 0 0 3px var(--wl-danger-soft)0 0 0 3px #f7eeed
--wl-metric-check-size

Роль check-size.

semantic
var(--wl-dimension-check-size)18px
--wl-metric-switch-width

Роль switch-width.

semantic
var(--wl-dimension-switch-width)36px
--wl-metric-switch-height

Роль switch-height.

semantic
var(--wl-dimension-switch-height)22px
--wl-metric-tag-height

Роль tag-height.

semantic
var(--wl-dimension-tag-height)20px
--wl-metric-chip-height

Роль chip-height.

semantic
var(--wl-dimension-chip-height)30px
--wl-metric-badge-height

Роль badge-height.

semantic
var(--wl-dimension-badge-height)18px
--wl-corner-surface

Роль card-radius.

semantic
var(--wl-radius)8px
--wl-corner-overlay

Роль dialog-radius.

semantic
var(--wl-radius-xl)12px
--wl-layout-drawer-width

Роль drawer-width.

semantic
var(--wl-dimension-drawer-width)420px
--wl-layer-mask

Роль mask-z.

semantic
var(--wl-dimension-mask-z)70
--wl-layer-popover

Роль overlay-z.

semantic
var(--wl-dimension-overlay-z)80
--wl-metric-iconbtn-size-sm

Роль iconbtn-size-sm.

semantic
var(--wl-dimension-iconbtn-size-sm)30px
--wl-metric-sidebar-width

Роль sidebar-width.

semantic
var(--wl-dimension-sidebar-width)68px
--wl-metric-sidebar-expanded-width

Роль sidebar-expanded-width.

semantic
var(--wl-dimension-sidebar-expanded-width)228px
--wl-layer-navigation

Роль sidebar-z.

semantic
var(--wl-dimension-sidebar-z)40
--wl-layer-navigation-modal

Роль sidebar-mobile-z.

semantic
var(--wl-dimension-sidebar-mobile-z)90
--wl-metric-segmented-shadow

Роль segmented-shadow.

semantic
0 1px 2px var(--wl-ink-a08)0 1px 2px rgba(20, 22, 28, 0.08)
--wl-layout-menu-width

Роль menu-width.

semantic
var(--wl-dimension-menu-width)230px
--wl-layout-popover-width

Роль popover-width.

semantic
var(--wl-dimension-popover-width)280px
--wl-layout-command-width

Роль command-width.

semantic
var(--wl-dimension-command-width)580px
--wl-metric-command-max-height

Роль command-max-height.

semantic
var(--wl-dimension-command-max-height)420px
--wl-metric-command-input-height

Роль command-input-height.

semantic
var(--wl-dimension-command-input-height)52px
--wl-layer-command

Роль command-z.

semantic
var(--wl-dimension-command-z)90
--wl-metric-page-header-gap

Роль page-header-gap.

semantic
var(--wl-dimension-page-header-gap)16px
--wl-metric-filter-bar-gap

Роль filter-bar-gap.

semantic
var(--wl-dimension-filter-bar-gap)10px
--wl-metric-filter-drawer-width

Роль filter-drawer-width.

semantic
var(--wl-dimension-filter-drawer-width)380px
--wl-layer-filter

Роль filter-z.

semantic
var(--wl-dimension-filter-z)90
--wl-layer-toast

Роль toast-z.

semantic
var(--wl-dimension-toast-z)100
--wl-status-info-icon

Роль toast-icon-info.

semantic
var(--wl-blue-300)#9cbdf0
--wl-status-success-icon

Роль toast-icon-ok.

semantic
var(--wl-green-400)#4cc38a
--wl-status-warning-icon

Роль toast-icon-warn.

semantic
var(--wl-amber-400)#e0a93e
--wl-status-danger-icon

Роль toast-icon-err.

semantic
var(--wl-palette-danger)#ab4448
--wl-metric-stepper-input-width

Роль stepper-input-width.

semantic
var(--wl-dimension-stepper-input-width)76px
--wl-metric-stepper-btn-width

Роль stepper-btn-width.

semantic
var(--wl-dimension-stepper-btn-width)36px
--wl-metric-slider-height

Роль slider-height.

semantic
var(--wl-dimension-slider-height)6px
--wl-metric-slider-thumb

Роль slider-thumb.

semantic
var(--wl-dimension-slider-thumb)18px
--wl-metric-step-num

Роль step-num.

semantic
var(--wl-dimension-step-num)24px
--wl-metric-table-cell-pad-y

Роль table-cell-pad-y.

semantic
var(--wl-dimension-table-cell-pad-y)11px
--wl-metric-table-cell-pad-x

Роль table-cell-pad-x.

semantic
var(--wl-dimension-table-cell-pad-x)12px
--wl-metric-table-head-pad-y

Роль table-head-pad-y.

semantic
var(--wl-dimension-table-head-pad-y)8px
--wl-metric-stat-bar-height

Роль stat-bar-height.

semantic
var(--wl-dimension-stat-bar-height)3px
--wl-metric-colorpick-sw

Роль colorpick-sw.

semantic
var(--wl-dimension-colorpick-sw)26px
--wl-metric-colorpick-sw-sm

Роль colorpick-sw-sm.

semantic
var(--wl-dimension-colorpick-sw-sm)20px
--wl-metric-colorpick-gap

Роль colorpick-gap.

semantic
var(--wl-dimension-colorpick-gap)8px
--wl-metric-cal-gap

Роль cal-gap.

semantic
var(--wl-dimension-cal-gap)5px
--wl-metric-cal-day-min-h

Роль cal-day-min-h.

semantic
var(--wl-dimension-cal-day-min-h)60px
--wl-metric-cal-ev-size

Роль cal-ev-size.

semantic
var(--wl-dimension-cal-ev-size)10.5px
--wl-metric-dp-day-size

Роль dp-day-size.

semantic
var(--wl-dimension-dp-day-size)30px
--wl-metric-dp-panel-pad

Роль dp-panel-pad.

semantic
var(--wl-dimension-dp-panel-pad)12px
--wl-metric-upload-drop-pad-y

Роль upload-drop-pad-y.

semantic
var(--wl-dimension-upload-drop-pad-y)26px
--wl-metric-upload-drop-pad-x

Роль upload-drop-pad-x.

semantic
var(--wl-dimension-upload-drop-pad-x)20px
--wl-space-none

Отступ none: 0 px.

semantic
var(--wl-space-0)0px
--wl-space-2xs

Отступ 2xs: 2 px.

semantic
var(--wl-space-2)2px
--wl-space-xs

Отступ xs: 4 px.

semantic
var(--wl-space-4)4px
--wl-space-sm

Отступ sm: 8 px.

semantic
var(--wl-space-8)8px
--wl-space-md

Отступ md: 12 px.

semantic
var(--wl-space-12)12px
--wl-space-lg

Отступ lg: 16 px.

semantic
var(--wl-space-16)16px
--wl-space-xl

Отступ xl: 24 px.

semantic
var(--wl-space-24)24px
--wl-space-2xl

Отступ 2xl: 32 px.

semantic
var(--wl-space-32)32px
--wl-space-3xl

Отступ 3xl: 48 px.

semantic
var(--wl-space-48)48px
--wl-space-4xl

Отступ 4xl: 64 px.

semantic
var(--wl-space-64)64px
--wl-type-display-size

Главный заголовок вступления; один на экран.

semantic
var(--wl-font-display-size)40px
--wl-type-display-line-height

Главный заголовок вступления; один на экран.

semantic
var(--wl-font-display-line-height)48px
--wl-type-display-weight

Главный заголовок вступления; один на экран.

semantic
var(--wl-font-display-weight)700
--wl-type-display-family

Главный заголовок вступления; один на экран.

semantic
var(--wl-font-display-family)"Gavia Sans Core", "Gavia Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif
--wl-type-title-size

Название страницы и крупного диалога.

semantic
var(--wl-font-title-size)28px
--wl-type-title-line-height

Название страницы и крупного диалога.

semantic
var(--wl-font-title-line-height)36px
--wl-type-title-weight

Название страницы и крупного диалога.

semantic
var(--wl-font-title-weight)700
--wl-type-title-family

Название страницы и крупного диалога.

semantic
var(--wl-font-title-family)"Gavia Sans Core", "Gavia Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif
--wl-type-heading-size

Раздел страницы и самостоятельный блок.

semantic
var(--wl-font-heading-size)20px
--wl-type-heading-line-height

Раздел страницы и самостоятельный блок.

semantic
var(--wl-font-heading-line-height)28px
--wl-type-heading-weight

Раздел страницы и самостоятельный блок.

semantic
var(--wl-font-heading-weight)650
--wl-type-heading-family

Раздел страницы и самостоятельный блок.

semantic
var(--wl-font-heading-family)"Gavia Sans Core", "Gavia Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif
--wl-type-subheading-size

Карточка, группа полей, небольшой диалог.

semantic
var(--wl-font-subheading-size)16px
--wl-type-subheading-line-height

Карточка, группа полей, небольшой диалог.

semantic
var(--wl-font-subheading-line-height)24px
--wl-type-subheading-weight

Карточка, группа полей, небольшой диалог.

semantic
var(--wl-font-subheading-weight)600
--wl-type-subheading-family

Карточка, группа полей, небольшой диалог.

semantic
var(--wl-font-subheading-family)"Gavia Sans Core", "Gavia Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif
--wl-type-body-size

Описания, инструкции, текст формы.

semantic
var(--wl-font-body-size)14px
--wl-type-body-line-height

Описания, инструкции, текст формы.

semantic
var(--wl-font-body-line-height)20px
--wl-type-body-weight

Описания, инструкции, текст формы.

semantic
var(--wl-font-body-weight)400
--wl-type-body-family

Описания, инструкции, текст формы.

semantic
var(--wl-font-body-family)"Gavia Sans Core", "Gavia Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif
--wl-type-small-size

Подписи и вспомогательный текст.

semantic
var(--wl-font-small-size)12px
--wl-type-small-line-height

Подписи и вспомогательный текст.

semantic
var(--wl-font-small-line-height)18px
--wl-type-small-weight

Подписи и вспомогательный текст.

semantic
var(--wl-font-small-weight)400
--wl-type-small-family

Подписи и вспомогательный текст.

semantic
var(--wl-font-small-family)"Gavia Sans Core", "Gavia Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif
--wl-type-label-size

Короткая подпись действия или поля.

semantic
var(--wl-font-label-size)13px
--wl-type-label-line-height

Короткая подпись действия или поля.

semantic
var(--wl-font-label-line-height)20px
--wl-type-label-weight

Короткая подпись действия или поля.

semantic
var(--wl-font-label-weight)500
--wl-type-label-family

Короткая подпись действия или поля.

semantic
var(--wl-font-label-family)"Gavia Sans Core", "Gavia Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif
--wl-type-code-size

Токены, идентификаторы и технические значения.

semantic
var(--wl-font-code-size)12px
--wl-type-code-line-height

Токены, идентификаторы и технические значения.

semantic
var(--wl-font-code-line-height)18px
--wl-type-code-weight

Токены, идентификаторы и технические значения.

semantic
var(--wl-font-code-weight)400
--wl-type-code-family

Токены, идентификаторы и технические значения.

semantic
var(--wl-font-code-family)"SF Mono", ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace
--wl-text-muted

Вспомогательный текст с контрастом не ниже 4.5:1.

semantic
var(--wl-text-2)#5b6470
--wl-focus-color

Видимая обводка клавиатурного фокуса.

semantic
var(--wl-accent)#3c7490
--wl-focus-invalid-color

Обводка фокуса поля с ошибкой.

semantic
var(--wl-danger-hover)#963c3f
--wl-text-danger

Читаемый текст ошибки на основной поверхности.

semantic
var(--wl-err-text)#ab4448
--wl-action-primary-bg

Поверхность основного действия.

semantic
var(--wl-palette-action-primary-bg)#3c7490
--wl-action-primary-hover

Основное действие при наведении.

semantic
var(--wl-palette-action-primary-hover)#376b84
--wl-action-primary-text

Читаемый текст основного действия.

semantic
var(--wl-palette-action-primary-text)#ffffff
--wl-action-danger-bg

Поверхность опасного действия.

semantic
var(--wl-palette-danger)#ab4448
--wl-action-danger-hover

Опасное действие при наведении.

semantic
var(--wl-palette-danger-hover)#963c3f
--wl-action-danger-text

Читаемый текст опасного действия.

semantic
var(--wl-on-accent)#ffffff
--wl-layout-page-max

Ширина контейнера страницы.

semantic
var(--wl-size-page-max)1240px
--wl-layout-page-gutter

Отступ контента от границы страницы.

semantic
var(--wl-space-xl)24px
--wl-layout-grid-gap

Интервал адаптивной сетки.

semantic
var(--wl-space-lg)16px
--wl-elevation-surface

Небольшое возвышение карточки.

semantic
var(--wl-shadow-card)0 1px 3px rgba(15, 26, 35, 0.05)
--wl-elevation-floating

Возвышение плавающей поверхности.

semantic
var(--wl-shadow-pop)0 4px 14px rgba(15, 26, 35, 0.08), 0 16px 44px rgba(15, 26, 35, 0.12)
--wl-motion-fast

Микроотклик кнопки и поля.

semantic
var(--wl-dur-2)0.12s
--wl-motion-normal

Появление небольшой панели.

semantic
var(--wl-dur-4)0.18s
--wl-motion-slow

Крупный модальный переход.

semantic
var(--wl-dur-5)0.2s
--wl-motion-ease

Кривая движения.

semantic
var(--wl-ease)ease
--wl-layout-reading-max

Ширина узкого контейнера для статей и инструкций.

semantic
var(--wl-size-reading-max)72ch
--wl-layout-grid-min

Минимальная ширина колонки wl-grid; внутри узкого контейнера ограничивается 100%.

semantic
var(--wl-size-grid-min)240px
--wl-layer-base

Слой обычного позиционированного контента в его stacking context.

semantic
var(--wl-z-base)0
--wl-layer-sticky

Слой sticky-шапки или навигации; не поднимает элемент над родительским stacking context.

semantic
var(--wl-z-sticky)50
--wl-action-primary-active

Поверхность основного действия при нажатии.

semantic
var(--wl-palette-action-primary-active)#326179
--wl-accent-warm

Дозированный тёплый акцент для иллюстраций, декоративных отметок и небольших деталей.

semantic
var(--wl-palette-accent-warm)#948775
--wl-accent-warm-soft

Фон декоративного тёплого выделения; для текста использовать основную текстовую роль.

semantic
var(--wl-palette-accent-warm-soft)#efebe3
--wl-corner-button

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

semantic
var(--wl-dimension-btn-radius)4px
--wl-corner-button-sm

Скругление кнопок размеров xs и sm.

semantic
var(--wl-dimension-btn-radius-sm)3px
--wl-corner-button-lg

Скругление кнопки размера lg.

semantic
var(--wl-dimension-btn-radius-lg)5px

05 / Компоненты

Публичные контракты

Props, модели, события и слоты берутся из манифеста библиотеки. Размер и плотность меняют геометрию; вариант передаёт смысл действия; состояния отражают его доступность.

Проверьте значение.

Один primary на группу. Danger — для необратимого действия с подтверждением. Loading блокирует повторную отправку; disabled сопровождается объяснением причины рядом.

WlButton

С версии 0.1.0

Кнопка действия с вариантами, размерами и состоянием загрузки.

PropТип / значенияНазначение
variantprimary | secondary | ghost | soft | linkВизуальный вариант кнопки.

По умолчанию: "secondary"

toneneutral | accent | info | success | warning | dangerСемантический цвет, независимый от варианта оформления.
sizexs | sm | md | lgРазмер кнопки.

По умолчанию: "md"

densitydefault | compactВ режиме compact высота кнопки меньше.

По умолчанию: "default"

loadingbooleanПоказывает загрузку вместо иконки и блокирует нажатие.

По умолчанию: false

disabledbooleanОтключает кнопку.

По умолчанию: false

blockbooleanРастянуть на всю ширину контейнера.

По умолчанию: false

typebutton | submit | resetНативный type кнопки.

По умолчанию: "button"

ptobjectАтрибуты внутренних элементов Gavia UI.
asunionЯвно выбирает отрисовку ссылки; href или to тоже включают этот режим.
hrefstringАдрес ссылки, передаваемый в WlLink.
tounionНазначение маршрута приложения, которое обрабатывает настроенный адаптер ссылок.
iconPositionunionРасполагает иконку перед основным слотом или после него.

Слоты

  • default — Текст или другое содержимое кнопки.
  • icon — Иконка слева (скрывается при loading).

События

  • click — MouseEvent

Пример

variant
tone
size
density

Нажатий: 0

Фокус: вне примера · указатель: вне примера

Hover и нажатие проверяйте мышью; focus — клавиатурой. Выбор, открытие и закрытие меняют v-model. Настройки выше можно сочетать.

Варианты и состояния · 22
Показать Vue-код
<script setup lang="ts">
import { WlButton, WlIcon } from "gavia-ui";
import { ref } from "vue";
const count = ref(0);
</script>

<template>
  <div class="wl-stack" data-space="md">
    <div>
      <WlButton  @click="count++"><template #icon><WlIcon name="plus" /></template>{{ "Добавить" }}</WlButton>
    </div>
    <p role="status" class="wl-text-small">{{ "Нажатий:" }} {{ count }}</p>
  </div>
</template>

06 / Паттерны

Формы, данные и панели

Компоненты отвечают за отображение и взаимодействие. Валидацию, запросы и бизнес-правила задаёт приложение. Примеры на этой странице работают без сервера.

Форма с валидацией

Как к вам обращаться
Например: name@example.com

Правила формы

  1. Видимая подпись связана с контролом через id.
  2. Подсказка и ошибка связаны через aria-describedby.
  3. При отправке фокус переходит к первой ошибке.
  4. Введённые данные сохраняются после ошибки.
  5. Результат действия объясняется текстом.

WlField передаёт id, invalid и ariaDescribedby через scoped slot. Placeholder дополняет подпись.

Четыре состояния данных

МатериалСостояние
Правила типографикиГотово
Каталог токеновГотово
Контракты компонентовГотово

Действие в боковой панели

Drawer открывается поверх страницы. Escape закрывает панель, фокус возвращается к кнопке открытия. Анимацию можно задать для приложения или отдельной панели.

07 / Рецепты

Примеры сценариев

Шесть примеров с кодом для копирования: состояния данных, отмена, ошибки и повторные действия. Сценарии проверяются вместе с компонентами.

Поиск, фильтры, сортировка и страницы. Создание и редактирование в Drawer, подтверждение удаления и Toast.

Материалы команды

Документы, договорённости и исследования.
12 материалов
Фильтры материалов
МатериалСтатусДействия
Доступы и ролиВ работе
Доступы и роли · 12В работе
Доступы и роли · 8В работе
План исследованияВ работе

Найдено: 12 · страница 1 из 3

Показать Vue-код
<script setup lang="ts">
import { useWlConfirm, useWlToast, WlButton, WlDrawer, WlEmpty, WlField, WlFilterBar, WlInput, WlPageHeader, WlPagination, WlPill, WlSelect, WlTable, type WlTableColumn, WlTag } from "gavia-ui";
import { computed, nextTick, ref, watch } from "vue";
type Material = { id: number; title: string; status: string };
const materials = ref<Material[]>(Array.from({ length: 12 }, (_, index) => ({
  id: index + 1, title: ["Руководство команды", "План исследования", "Правила ревью", "Доступы и роли"][index % 4] + (index < 4 ? "" : ` · ${index + 1}`),
  status: index % 2 ? "progress" : "done"
})));
const search = ref("");
const status = ref<string | null>(null);
const order = ref<string | null>("asc");
const page = ref(1);
const confirm = useWlConfirm();
const toast = useWlToast();
const filtered = computed(() => materials.value.filter((item) =>
  item.title.toLocaleLowerCase("ru").includes(search.value.toLocaleLowerCase("ru")) && (!status.value || item.status === status.value))
  .sort((a, b) => a.title.localeCompare(b.title, "ru") * (order.value === "desc" ? -1 : 1)));
const pageCount = computed(() => Math.max(1, Math.ceil(filtered.value.length / 4)));
const visibleRows = computed(() => filtered.value.slice((page.value - 1) * 4, page.value * 4));
watch([search, status, order], () => {
  page.value = 1;
});
watch(pageCount, (count) => {
  page.value = Math.min(page.value, count);
});
const columns: readonly WlTableColumn<Material>[] = [{ key: "title", label: "Материал" }, { key: "status", label: "Статус" }, { key: "actions", label: "Действия", kind: "virtual" }];
function clear(): void {
  search.value = "";
  status.value = null;
}
const editing = ref(false);
const editingId = ref<number | null>(null);
const title = ref("");
const titleError = ref("");
let nextId = 13;
function edit(item?: Material): void {
  editingId.value = item?.id ?? null;
  title.value = item?.title ?? "";
  titleError.value = "";
  editing.value = true;
}
async function save(): Promise<void> {
  titleError.value = title.value.trim() ? "" : "Введите название.";
  if (titleError.value) {
    await nextTick();
    document.getElementById("recipe-material-title")?.focus();
    return;
  }
  const current = materials.value.find((item) => item.id === editingId.value);
  if (current) current.title = title.value.trim();
  else materials.value.push({ id: nextId++, title: title.value.trim(), status: "progress" });
  editing.value = false;
  toast.ok("Материал сохранён");
}
function remove(id: number): void {
  const item = materials.value.find((entry) => entry.id === id);
  if (!item) return;
  confirm.confirmDanger({
    header: "Удалить материал?", message: `«${item.title}${"» будет удалён."}`, acceptLabel: "Удалить", rejectLabel: "Отмена",
    accept: () => {
      materials.value = materials.value.filter((entry) => entry.id !== id);
      toast.ok("Материал удалён");
    }
  });
}
</script>

<template>
  <section class="wl-stack" data-space="lg" aria-label="Список материалов">
    <WlPageHeader
      title="Материалы команды"
      description="Документы, договорённости и исследования."
      :heading-level="2"
      size="md"
    >
      <template #meta><WlTag>{{ materials.length }} {{ "материалов" }}</WlTag></template>
      <template #actions><WlButton variant="primary" @click="edit()">{{ "Создать материал" }}</WlButton></template>
    </WlPageHeader>
    <WlInput
      v-model="search"
      type="search"
      placeholder="Найти материал"
      aria-label="Найти материал"
    />
    <WlFilterBar
      :active-count="Number(Boolean(status))"
      aria-label="Фильтры материалов"
      panel-title="Фильтры материалов"
      @clear="clear"
    >
      <WlSelect
        v-model="status"
        :options="[{ label: 'Готово', value: 'done' }, { label: 'В работе', value: 'progress' }]"
        option-label="label"
        option-value="value"
        aria-label="Статус материалов"
        placeholder="Все статусы"
      />
      <WlSelect
        v-model="order"
        :options="[{ label: 'Название А–Я', value: 'asc' }, { label: 'Название Я–А', value: 'desc' }]"
        option-label="label"
        option-value="value"
        aria-label="Порядок материалов"
      />
      <template #summary><WlTag
        v-if="status"
        removable
        remove-label="Убрать фильтр статуса"
        @remove="status = null"
      >{{ status === 'done' ? "Готово" : "В работе" }}</WlTag></template>
    </WlFilterBar>
    <div
      v-if="filtered.length"
      class="ds-material-table"
      role="region"
      aria-label="Материалы команды"
      tabindex="0"
    ><WlTable :columns="columns" :value="visibleRows" :pt="{ root: { style: { minWidth: '640px' } } }">
      <template #cell-status="{ value }">
        <WlPill
          :tone="value === 'done' ? 'success' : 'info'"
          :label="value === 'done' ? 'Готово' : 'В работе'"
        />
      </template>
      <template #cell-actions="{ row }"><div class="wl-inline" data-space="xs"><WlButton
        size="sm"
        variant="ghost"
        :aria-label="`${'Редактировать '}${row.title}`"
        @click="edit(materials.find((item) => item.id === row.id))"
      >{{ "Изменить" }}</WlButton><WlButton
        size="sm"
        variant="ghost"
        tone="danger"
        :aria-label="`${'Удалить '}${row.title}`"
        @click="remove(Number(row.id))"
      >{{ "Удалить" }}</WlButton></div></template>
    </WlTable></div>
    <WlEmpty
      v-else
      icon="search"
      title="Материалы не найдены"
      description="Измените запрос или сбросьте фильтры."
    ><template #action><WlButton @click="clear">{{ "Сбросить поиск" }}</WlButton></template></WlEmpty>
    <div class="wl-inline" data-space="md">
      <WlPagination v-if="filtered.length" v-model:page="page" :page-count="pageCount" />
      <p class="wl-text-small wl-text-muted" role="status">
        {{ "Найдено:" }} {{ filtered.length }} {{ "· страница" }}
        {{ page }} {{ "из" }} {{ pageCount }}
      </p>
    </div>
    <WlDrawer v-model:visible="editing" :header="editingId ? 'Редактирование материала' : 'Новый материал'">
      <form
        id="recipe-material-form"
        class="wl-stack"
        data-space="lg"
        @submit.prevent="save"
      >
        <WlField
          id="recipe-material-title"
          v-slot="field"
          label="Название"
          required
          :error="titleError"
        ><WlInput
          :id="field.id"
          v-model="title"
          :invalid="field.invalid"
          :aria-describedby="field.ariaDescribedby"
          maxlength="120"
        /></WlField>
        <p class="wl-text-small wl-text-muted">{{ "Чтобы применить изменения, нажмите «Сохранить»." }}</p>
      </form>
      <template #footer>
        <WlButton variant="ghost" @click="editing = false">{{ "Отмена" }}</WlButton>
        <WlButton variant="primary" type="submit" form="recipe-material-form">{{ "Сохранить" }}</WlButton>
      </template>
    </WlDrawer>
  </section>
</template>

<style scoped>
.ds-material-table { overflow: auto; max-width: 100%; }
</style>

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

Подключение стилей, темы и сервисов
// main.ts — CSS подключается явно; тему задаёт data-wl-theme на html.
import { createApp } from "vue";
import { WlConfig, WlToastService, WlConfirmationService, createWlPt, wlLocaleRu } from "gavia-ui";
import "gavia-ui/styles/reset.css";
import "gavia-ui/styles/base.css";
import "gavia-ui/styles/primitives.css";
import "gavia-ui/themes/white.css";
import "gavia-ui/themes/graphite.css";
import "gavia-ui/themes/newspaper.css";
import "gavia-ui/styles/fonts/gavia.css";
import "gavia-ui/themes/gavia.css";
import "gavia-ui/themes/gavia-dark.css";
import App from "./App.vue";

document.documentElement.dataset.wlTheme = "white";

// WlConfig merges application pt with defaults; local component pt is applied last.
const pt = createWlPt({ button: { root: { "data-ui": "action" } } });
createApp(App).use(WlConfig, { locale: wlLocaleRu, motion: true, pt })
  .use(WlToastService).use(WlConfirmationService).mount("#app");

// App.vue: импортируйте WlToast/WlConfirmDialog и смонтируйте по одному
// контейнеру рядом со страницей. Уведомления и подтверждения используют их.
// <template><YourPage /><WlToast /><WlConfirmDialog /></template>

08 / Сложный контент

Длинный текст и большие списки

Длинный русский текст, восемь тегов, 80 вариантов выбора, 20 строк таблицы, ограниченные даты и вложенные оверлеи. Изменяйте ширину окна и размер текста.

Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований

Сузьте окно, чтобы посмотреть перенос заголовка, кнопок и метаданных.
Исследование 1Исследование 2Исследование 3Исследование 4Исследование 5Исследование 6Исследование 7Исследование 8
8 выбрано
Укажите понятное название материала, чтобы участники из разных команд могли найти его через поиск и отличить от похожих материалов.
1–31 октября 2026.
Длинное названиеИдентификатор
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 1research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 2research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 3research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 4research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 5research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 6research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 7research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 8research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 9research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 10research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 11research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 12research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 13research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 14research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 15research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 16research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 17research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 18research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 19research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz
Договорённости международной распределённой команды по совместной подготовке материалов и проведению исследований · 20research_material_without_spaces_2026_10_01_abcdefghijklmnopqrstuvwxyz

09 / Доступность

Клавиатура, контраст и фокус

Контраст текста — от 4.5:1, индикатора фокуса — от 3:1. Отчёт проверяет перечисленные пары токенов; пользовательские цвета и весь экран проверяются отдельно.

Клавиатура

Tab — переход. Enter / Space — действие. Стрелки — выбор. Escape — закрытие оверлея. Фокус виден и возвращается после закрытия.

Движение

motion: false выключает переходы. Системное prefers-reduced-motion действует во всех темах. Анимация не меняет смысл или время жизни данных.

Текст и цель

Иконка действия получает aria-label. Ошибка объясняет следующий шаг. Цель на touch-экране: ориентир 44 × 44 px; выбирайте lg и достаточные интервалы.

Пара / gaviaФактМинимум
Основной текст16.73:14.5:1
Вспомогательный текст5.7:14.5:1
Текст на вторичной поверхности15.63:14.5:1
Основное действие5.13:14.5:1
Основное действие: hover5.84:14.5:1
Основное действие: active6.73:14.5:1
Опасное действие5.75:14.5:1
Опасное действие: hover6.97:14.5:1
Подсказка17.61:14.5:1
Информационное сообщение7.8:14.5:1
Успешное сообщение5.84:14.5:1
Предупреждение5.73:14.5:1
Сообщение об ошибке5.04:14.5:1
Фокус на странице4.87:13:1
Ссылка на странице6.39:14.5:1
Фокус на вторичной поверхности4.55:13:1
Текст на поднятой поверхности17.33:14.5:1
Вспомогательный текст на поднятой поверхности5.9:14.5:1
Фокус на поднятой поверхности5.05:13:1
Акцентный текст на поднятой поверхности6.62:14.5:1
Акцентный текст на вторичной поверхности5.97:14.5:1
Акцентный текст на выбранной поверхности5.41:14.5:1
Акцентный текст на мягкой поверхности при наведении4.95:14.5:1

Новые токены проходят tokens:check. Паттерны проверяются в Chromium, Firefox, WebKit и мобильном Chromium. Перед релизом также проверяются типы, архив и изолированный потребитель.

Gavia UI · Vue 3 · API компонентов · документация в docs/design-system.md