Анимации и переходы

В Slim Select визуальные переходы построены вокруг состояния раскрытия компонента. Основной элемент интерфейса — контейнер выпадающего списка — переключается между состояниями open и closed, при этом вся анимационная логика реализуется через CSS-классы, добавляемые и удаляемые библиотекой во время жизненного цикла компонента.

Ключевой класс состояния:

  • .ss-open — активное раскрытое состояние
  • .ss-main — базовый контейнер инстанса
  • .ss-content — контейнер списка опций

Переход между состояниями не управляется JavaScript напрямую через таймеры или requestAnimationFrame. Вместо этого Slim Select опирается на стандартные CSS transition/animation механизмы, что позволяет полностью кастомизировать поведение без вмешательства в логику библиотеки.

Типовой подход к анимации раскрытия:

.ss-content {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transform: translateY(-6px);
  transition: max-height 200ms ease, opacity 200ms ease, transform 200ms ease;
}

.ss-main.ss-open .ss-content {
  max-height: 240px;
  opacity: 1;
  transform: translateY(0);
}

Использование max-height вместо height: auto обусловлено ограничениями CSS-переходов: анимация невозможна для auto, поэтому применяется ограниченный числовой диапазон.


Управление плавностью и кривыми переходов

Slim Select не навязывает собственные easing-функции. Все параметры сглаживания определяются через CSS transition-timing-function. Это позволяет адаптировать поведение компонента под общий дизайн-системный стандарт проекта.

Часто используемые кривые:

  • ease — универсальная плавность
  • ease-out — быстрый старт и плавное завершение
  • cubic-bezier(0.4, 0, 0.2, 1) — Material Design-подобная динамика
  • linear — используется редко, чаще для технических состояний

Пример настройки единого поведения:

.ss-content {
  transition: max-height 220ms cubic-bezier(0.4, 0, 0.2, 1),
              opacity 180ms ease-out,
              transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
}

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


Анимация выбора элемента

При выборе значения Slim Select обновляет DOM без полной перерисовки компонента. Отображение выбранных элементов (chips/tag-style элементы) также может быть анимировано через CSS.

Основные состояния:

  • добавление выбранного элемента
  • удаление выбранного элемента
  • обновление текста внутри selection box

Рекомендуемый подход — использовать transition для появления/исчезновения элементов через opacity и transform.

.ss-value {
  display: inline-flex;
  opacity: 0;
  transform: scale(0.95);
  transition: opacity 150ms ease, transform 150ms ease;
}

.ss-value.ss-enter {
  opacity: 1;
  transform: scale(1);
}

.ss-value.ss-leave {
  opacity: 0;
  transform: scale(0.9);
}

Хотя Slim Select не всегда автоматически добавляет классы ss-enter и ss-leave в стандартной конфигурации, подобное поведение реализуется через внешнее управление DOM или кастомные расширения.


Плавность скролла внутри списка

При большом количестве опций контейнер .ss-list становится прокручиваемым. В этом случае важна не только анимация появления, но и поведение scroll-состояний.

.ss-list {
  max-height: 240px;
  overflow-y: auto;
  scroll-behavior: smooth;
}

scroll-behavior: smooth влияет на программную прокрутку при навигации по списку с клавиатуры или при вызове методов API, если они вызывают изменение активного элемента.

Дополнительно может применяться подсветка активного элемента:

.ss-option.ss-highlighted {
  background: rgba(0, 0, 0, 0.06);
  transition: background 120ms ease;
}

Синхронизация анимаций с состоянием компонента

Slim Select обновляет UI синхронно с изменением состояния, однако CSS-анимации могут завершаться позже логического состояния компонента. Это создаёт необходимость учитывать рассинхронизацию DOM и визуального состояния.

Типичный паттерн:

  • JavaScript меняет класс состояния мгновенно
  • CSS завершает переход самостоятельно
  • финальное состояние DOM уже установлено до окончания анимации

Это важно при кастомных модификациях, например, если требуется блокировать повторное открытие до завершения закрытия.

Пример защитного подхода:

selectInstance.on('close', () => {
  const el = document.querySelector('.ss-main');
  el.classList.add('ss-closing');

  setTimeout(() => {
    el.classList.remove('ss-closing');
  }, 220);
});

Анимации фокуса и навигации с клавиатуры

При навигации по списку с помощью стрелок изменяется активный элемент. Это состояние обычно подсвечивается классом .ss-highlighted, который также может быть анимирован.

.ss-option {
  transition: background-color 120ms ease, color 120ms ease;
}

.ss-option.ss-highlighted {
  background-color: #e9f2ff;
}

Плавность здесь играет важную роль при быстром перемещении по списку, снижая визуальную «дёрганность».


Оптимизация производительности анимаций

Для предотвращения лишних перерисовок используются свойства, которые не вызывают layout recalculation:

  • transform
  • opacity

Следует избегать анимации:

  • height (кроме ограниченного max-height)
  • top/left
  • box-shadow в сложных списках

Оптимальный набор для Slim Select:

.ss-content {
  will-change: transform, opacity;
}

will-change используется точечно, так как при избыточном применении может увеличивать потребление памяти GPU.


Интеграция анимаций с темизацией

Анимации Slim Select часто зависят от цветовой схемы интерфейса. В тёмных и светлых темах одинаковые transition-значения могут давать разный визуальный эффект.

Пример адаптивного подхода:

[data-theme="dark"] .ss-option.ss-highlighted {
  background-color: rgba(255, 255, 255, 0.08);
}

[data-theme="light"] .ss-option.ss-highlighted {
  background-color: rgba(0, 0, 0, 0.06);
}

Сами анимации остаются идентичными, изменяется только визуальная база.


Пользовательские анимационные пресеты

Slim Select допускает полное переопределение визуального поведения через CSS, что позволяет формировать разные «режимы движения» интерфейса.

Примеры пресетов:

Минималистичный режим

.ss-content {
  transition: none;
}

Мягкое появление

.ss-content {
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 300ms ease, transform 300ms ease;
}

.ss-main.ss-open .ss-content {
  opacity: 1;
  transform: translateY(0);
}

Пружинящий эффект

.ss-content {
  transition: transform 260ms cubic-bezier(0.34, 1.56, 0.64, 1),
              opacity 200ms ease;
}

Поведение при мгновенных изменениях состояния

При программном изменении значения через API Slim Select анимации раскрытия обычно не запускаются, так как отсутствует переход между UI-состояниями открытия списка. Однако визуальные обновления выбранных значений могут сопровождаться CSS-transition эффектами.

Это разделяет два уровня:

  • структурные анимации (open/close)
  • контентные анимации (выбор/удаление/обновление)

Такое разделение позволяет избежать конфликтов между состояниями компонента и CSS-переходами DOM-элементов.