RTL поддержка

RTL (right-to-left) поддержка в Tom Select строится не через отдельный режим библиотеки, а через сочетание HTML-атрибутов направления текста, CSS-правок и переопределения поведения отдельных элементов интерфейса. Основная логика Tom Select изначально ориентирована на LTR, поэтому корректная адаптация требует учета всех визуальных и интерактивных компонентов: контейнера, инпута поиска, выбранных элементов, выпадающего списка и позиционирования стрелок.

Режим RTL в браузерах активируется через атрибут:

<div dir="rtl">

или на уровне документа:

<html dir="rtl">

При включении RTL браузер автоматически меняет:

  • направление текста
  • выравнивание inline-элементов
  • порядок отображения некоторых flex/grid элементов
  • базовое позиционирование курсора в input

Tom Select наследует часть этого поведения, но значительная часть интерфейса построена на кастомных контейнерах и absolute-positioned элементах, которые требуют ручной корректировки.


Инициализация Tom Select в RTL-контейнере

Стандартная инициализация не отличается от LTR:

new TomSelect("#select", {
  plugins: ["remove_button"],
  persist: false,
  create: false
});

RTL-режим активируется не через конфигурацию, а через DOM:

<div dir="rtl">
  <select id="select" multiple>
    <option value="1">Опция 1</option>
    <option value="2">Опция 2</option>
  </select>
</div>

При такой конфигурации базовые элементы начинают наследовать направление, но визуальная корректность зависит от CSS.


Основные CSS-правки для RTL

Tom Select использует набор классов:

  • .ts-wrapper
  • .ts-control
  • .ts-dropdown
  • .ts-input
  • .item

Для RTL требуется переопределение выравнивания и отступов.

[dir="rtl"] .ts-control {
  text-align: right;
  flex-direction: row-reverse;
}
[dir="rtl"] .ts-wrapper {
  direction: rtl;
}
[dir="rtl"] .ts-dropdown {
  text-align: right;
}

Выравнивание выбранных элементов (multi-select)

В multi-select режиме выбранные элементы отображаются как inline-блоки внутри контейнера .ts-control. В RTL важно инвертировать порядок и отступы:

[dir="rtl"] .ts-control .item {
  margin-left: 0;
  margin-right: 5px;
}

Если используется кнопка удаления:

[dir="rtl"] .ts-control .item .remove {
  margin-left: 0;
  margin-right: 6px;
}

Также важно учитывать порядок вставки элементов: Tom Select добавляет их в DOM в логическом порядке выбора, а визуально RTL может требовать обратного восприятия. При необходимости можно дополнительно управлять сортировкой через onItemAdd.


Поле поиска и курсор

Поиск внутри Tom Select реализуется через input .ts-input. В RTL возникают типичные проблемы:

  • курсор прыгает при вводе латиницы
  • выравнивание placeholder отличается от выбранного текста
  • автопрокрутка не всегда корректна

Корректировка:

[dir="rtl"] .ts-input {
  text-align: right;
}

Дополнительно:

[dir="rtl"] .ts-control input {
  direction: rtl;
}

При смешанном вводе (RTL + LTR текст) иногда требуется принудительно задать:

.ts-input {
  unicode-bidi: plaintext;
}

Плейсхолдер в RTL

Placeholder часто остаётся визуально слева при недостаточной настройке:

[dir="rtl"] .ts-input::placeholder {
  text-align: right;
}

Выпадающий список (dropdown) и позиционирование

Dropdown в Tom Select создаётся как отдельный абсолютный блок .ts-dropdown. В RTL критично корректно настроить:

  1. выравнивание текста
  2. направление списка
  3. позицию относительно контроллера
[dir="rtl"] .ts-dropdown {
  direction: rtl;
  text-align: right;
}

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

Для компенсации:

[dir="rtl"] .ts-dropdown {
  right: 0;
  left: auto;
}

Стрелка раскрытия (caret)

Стрелка dropdown часто позиционируется справа в LTR. В RTL требуется инверсия:

[dir="rtl"] .ts-wrapper::after {
  left: 10px;
  right: auto;
}

Если используется кастомный caret через CSS border-triangle:

[dir="rtl"] .ts-wrapper::after {
  transform: rotate(180deg);
}

Адаптация keyboard navigation

Навигация стрелками вверх/вниз в Tom Select не требует изменений, но визуальная логика меняется:

  • в RTL пользователь ожидает инверсию горизонтальных направлений
  • вертикальная навигация остаётся без изменений
  • горизонтальные элементы (если кастомизированы) требуют ручной обработки

При расширении поведения:

onKeyDown: function (e) {
  if (this.isOpen && document.dir === "rtl") {
    // кастомная логика при необходимости
  }
}

Custom rendering (render) и RTL

Tom Select позволяет переопределять шаблоны через render. Это ключевая точка для полной RTL-адаптации.

new TomSelect("#select", {
  render: {
    option: function (data, escape) {
      return `
        <div class="option-rtl">
          <span class="label">${escape(data.text)}</span>
        </div>
      `;
    },
    item: function (data, escape) {
      return `
        <div class="item-rtl">
          ${escape(data.text)}
        </div>
      `;
    }
  }
});

CSS:

.option-rtl,
.item-rtl {
  text-align: right;
  direction: rtl;
}

Динамическое переключение LTR/RTL

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

function setDirection(dir) {
  document.documentElement.setAttribute("dir", dir);

  const instance = document.querySelector("#select").tomselect;
  instance.refreshOptions(false);
}

После переключения направления важно:

  • обновить dropdown позиционирование
  • пересчитать ширины контейнеров
  • вызвать refreshOptions

Проблемы с flexbox в RTL

Tom Select активно использует flexbox внутри .ts-control. В RTL могут возникать:

  • неправильный порядок элементов
  • смещение input
  • некорректные отступы между item-элементами

Решение:

[dir="rtl"] .ts-control {
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
}

При этом input может потребовать отдельного переопределения:

[dir="rtl"] .ts-control input {
  flex: 1;
}

Анимации и RTL

Если используются transition/animation эффекты dropdown, направление не влияет напрямую, но визуальное восприятие может быть нарушено при:

  • slide-in слева направо
  • fade + translateX

Корректировка:

[dir="rtl"] .ts-dropdown {
  transform-origin: right top;
}

Совместимость с темами и кастомным UI

В системах с темизацией RTL часто ломается при:

  • dark mode + RTL комбинациях
  • кастомных border-radius у control
  • фиксированных ширинах dropdown

Рекомендуется избегать жестких значений:

.ts-wrapper {
  width: 100%;
}

и использовать адаптивные значения:

.ts-dropdown {
  min-width: 100%;
}

Особенности работы с удалением элементов

Кнопка удаления .remove в RTL требует корректировки зоны клика:

[dir="rtl"] .ts-control .item .remove {
  position: relative;
  left: auto;
  right: 0;
}

Также важно учитывать, что визуально кнопка должна быть слева от текста в RTL-логике, а не справа.


Итоговая архитектура RTL-адаптации

Корректная RTL-реализация Tom Select складывается из трёх слоёв:

  • HTML уровень (dir="rtl")
  • CSS уровень (инверсия flex, text-align, positioning)
  • JS уровень (render, refresh, динамическое обновление)

Игнорирование любого из слоёв приводит к частичным дефектам интерфейса: смещённым элементам, некорректному caret или нарушенной логике dropdown.