04 · Components · Stable

Spinner

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

Размеры

SM · MD · LG
SM
16px · 2px stroke
MD
24px · 2.5px stroke
LG
36px · 3px stroke

Токены размеров

Size · Stroke · Цвет
Свойство
SM
MD
LG
Диаметр
16px
24px
36px
Stroke
2px
2.5px
3px
Скорость
700ms linear infinite — единая для всех размеров
Track
var(--ds-stroke-low) — Static/Border/Neutral-Blue/Low (mirror-aware, все 4 темы)
Fill
var(--ds-neutral-fill) — Static/Surface/Neutral-Blue/Accent (mirror-aware)

Задержка показа

default delay=800ms
Паттерн

Зачем нужна задержка

Спиннер по умолчанию появляется через 800ms после монтирования — это CSS-анимация ds-spinner-appear.

  • Быстрые операции (<800ms) — спиннер не успевает появиться, нет мерцания
  • Длинные операции (>800ms) — получают видимый индикатор
  • Управлять через CSS-переменную: --ds-spinner-delay

Немедленный показ: style="--ds-spinner-delay:0ms"

Демо · delay=0ms

Мгновенный показ

Применяется в кнопках и inline-контекстах — пользователь уже инициировал действие и ожидает реакцию.

SM
MD
LG

В контексте кнопки

Loading state · SM spinner
data-loading="center" — иконки слева нет → спиннер заменяет лейбл (лейбл скрыт visibility, ширина кнопки держится)
data-loading="slot" — иконка слева ЕСТЬ → спиннер занимает её место, лейбл остаётся видимым

В loading-состоянии кнопка получает data-disabled и aria-busy="true". Spinner внутри кнопки помечен aria-hidden="true" (пропс decorative, Spinner.tsx:35) — родительская кнопка уже объявляет состояние через aria-busy, и второй голос для скринридера был бы дублем.

Тёмная тема

data-theme="dark"
SM
16px
MD
24px
LG
36px
В кнопке
Dark mode

Track — --ds-stroke-low (Static/Border/Neutral-Blue/Low), индикатор — --ds-neutral-fill (Static/Surface/Neutral-Blue/Accent). Оба mirror-aware: корректно инвертируются во всех 4 темах.

Правила использования

Поведение · Доступность
Применение

Когда использовать

  • Кнопка loading state — вместо иконки слева при отправке формы
  • Inline в карточке — загрузка данных внутри блока (SM или MD)
  • Полностраничная загрузка — LG в центре пустого экрана
  • Skeleton замена — когда структура контента неизвестна заранее
Ограничения

Чего избегать

  • Не используй вместо Progress Bar для длинных операций с известным прогрессом
  • Не показывай несколько спиннеров одновременно на одном экране
  • Не используй для determinate-прогресса — только для async без известного %
  • Не убирай без уведомления — показывай результат (success/error состояние)
Доступность

ARIA паттерн

  • Standalone: role="status" + aria-label="Загрузка"
  • В кнопке: aria-hidden="true", роль не задаётся (кнопка объявляет aria-busy="true")
  • Скрытый текст для screen readers: <span class="sr-only">Загрузка...</span>
  • Кнопка в loading state: обязательно disabled — предотвращает двойную отправку
Размер под контекст

Выбор размера

  • SM (16px) — кнопки SM/MD, inline-индикаторы, тесные UI
  • MD (24px) — кнопки LG/XL, карточки, section-загрузка
  • LG (36px) — полностраничные состояния, модальные загрузки

В кнопке всегда SM — не перевешивает лейбл визуально.

State Explorer

Интерактивный тест состояний