RTL поддержка

Stimulus — это JavaScript-фреймворк для создания динамических интерфейсов с минимальным количеством кода. При разработке интерфейсов, ориентированных на аудитории с языками, использующими написание справа налево (RTL), важно учитывать особенности DOM, стилей и поведения элементов. Stimulus предоставляет инструменты для управления состоянием элементов и их поведением, что позволяет эффективно адаптировать приложения под RTL.


Определение направления текста

Первым шагом является определение направления текста страницы или конкретного контейнера. В HTML это осуществляется с помощью атрибута dir:

<div dir="rtl" data-controller="text-direction">
  <p>Пример текста справа налево</p>
</div>

Stimulus-контроллер может использовать этот атрибут для динамического изменения поведения компонентов. Например, можно автоматически адаптировать расположение кнопок или элементов интерфейса.

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  connect() {
    this.updateDirection();
  }

  updateDirection() {
    const direction = this.element.getAttribute("dir") || "ltr";
    this.element.dataset.direction = direction;
  }
}

В данном примере контроллер сохраняет направление текста в data-direction, чтобы другие компоненты могли использовать эту информацию.


Динамическая адаптация стилей

Для элементов, требующих изменения расположения в зависимости от направления текста, удобно использовать модификаторы CSS-классов:

export default class extends Controller {
  static targets = ["menu", "button"]

  connect() {
    this.applyDirection();
  }

  applyDirection() {
    const dir = this.element.dataset.direction;
    if (dir === "rtl") {
      this.menuTarget.classList.add("menu-rtl");
      this.buttonTarget.classList.add("button-rtl");
    } else {
      this.menuTarget.classList.remove("menu-rtl");
      this.buttonTarget.classList.remove("button-rtl");
    }
  }
}

CSS может содержать правила, специфичные для RTL:

.menu-rtl {
  float: right;
  text-align: right;
}

.button-rtl {
  margin-left: 0;
  margin-right: 10px;
}

Такой подход позволяет централизованно управлять стилями через Stimulus-контроллеры.


Реакция на изменения направления

В некоторых приложениях направление текста может меняться динамически (например, при переключении языка). Stimulus позволяет отслеживать изменения через мутационные наблюдатели:

export default class extends Controller {
  connect() {
    this.observer = new MutationObserver(() => this.applyDirection());
    this.observer.observe(this.element, { attributes: true, attributeFilter: ["dir"] });
    this.applyDirection();
  }

  disconnect() {
    this.observer.disconnect();
  }

  applyDirection() {
    const dir = this.element.getAttribute("dir") || "ltr";
    this.element.dataset.direction = dir;
  }
}

Это гарантирует, что интерфейс всегда корректно адаптирован под текущее направление текста.


Управление поведением компонентов

Stimulus позволяет изменять не только стили, но и поведение элементов. Например, карусели, всплывающие меню или навигационные панели могут реагировать на направление текста:

export default class extends Controller {
  static targets = ["carousel"]

  connect() {
    this.initializeCarousel();
  }

  initializeCarousel() {
    const dir = this.element.dataset.direction;
    const options = {
      rtl: dir === "rtl",
      loop: true
    };
    new Carousel(this.carouselTarget, options);
  }
}

Таким образом, любой сторонний компонент, поддерживающий RTL, может быть интегрирован через Stimulus-контроллер, а изменение направления текста будет автоматически учитывать конфигурацию.


Работа с динамическими элементами

В приложениях с динамическим добавлением элементов через AJAX или Turbo Streams важно, чтобы новые элементы наследовали правильное направление текста. Контроллеры Stimulus могут быть использованы для автоматической инициализации всех новых элементов:

export default class extends Controller {
  static targets = ["item"]

  connect() {
    this.itemTargets.forEach(item => this.initializeItem(item));
  }

  initializeItem(item) {
    const dir = this.element.dataset.direction;
    item.classList.toggle("rtl", dir === "rtl");
  }
}

Такой подход обеспечивает консистентность интерфейса и упрощает поддержку RTL на крупных страницах с множеством динамических элементов.


Рекомендации по интеграции

  • Использовать единый источник направления текста (dir или data-direction) для всех контроллеров.
  • Стили и поведение компонентов разделять на LTR и RTL версии.
  • Применять MutationObserver для отслеживания динамических изменений dir.
  • Интегрировать сторонние библиотеки с учетом их поддержки RTL через конфигурацию контроллеров.
  • Проверять интерфейс при переключении языков для предотвращения визуальных и функциональных ошибок.

Stimulus предоставляет гибкую и минималистичную систему для управления RTL, сочетая управление DOM с возможностью централизованной адаптации стилей и поведения компонентов. Это позволяет создавать интерфейсы, корректно работающие для всех направлений текста, без избыточного кода и сложной логики.