Tailwind CSS интеграция

React Aria предоставляет мощный набор хуков и утилит для создания доступных интерфейсов, при этом не навязывая собственный стиль. В комбинации с Tailwind CSS становится возможным строить интерфейсы, полностью соответствующие современным требованиям доступности, с лаконичным и управляемым визуальным оформлением.

Основные принципы интеграции

  1. Разделение логики и стилей React Aria отвечает за поведение компонентов: управление фокусом, клавиатурные события, aria-атрибуты. Tailwind CSS отвечает исключительно за визуальную часть. Такой подход позволяет использовать один и тот же хук React Aria в разных проектах с разными темами, не дублируя стили.

  2. Использование className совместно с хуками Большинство хуков React Aria возвращают props для элементов: buttonProps, inputProps, listBoxProps и др. Эти props можно спокойно объединять с Tailwind-классами через spread-оператор:

    import { useButton } from '@react-aria/button';
    
    function Button({ children }) {
      let ref = React.useRef();
      let { buttonProps } = useButton({ onPress: () => alert('Clicked') }, ref);
    
      return (
        <button
          {...buttonProps}
          ref={ref}
          className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-300"
        >
          {children}
        </button>
      );
    }

    Здесь React Aria управляет поведением кнопки, а Tailwind обеспечивает визуальный отклик на hover и focus.

  3. Фокус и состояния через Tailwind React Aria предоставляет состояния компонентов: isDisabled, isSelected, isFocused. Tailwind CSS позволяет реагировать на эти состояния с помощью условного добавления классов:

    import { useCheckbox } from '@react-aria/checkbox';
    
    function Checkbox({ children, isSelected }) {
      let ref = React.useRef();
      let { inputProps } = useCheckbox({ isSelected }, ref);
    
      return (
        <label className="flex items-center space-x-2">
          <input
            {...inputProps}
            ref={ref}
            className={`w-5 h-5 border rounded ${isSelected ? 'bg-blue-500' : 'bg-white'} focus:ring-2 focus:ring-blue-300`}
          />
          <span>{children}</span>
        </label>
      );
    }

    В этом примере класс bg-blue-500 применяется динамически, в зависимости от состояния isSelected, поддерживаемого React Aria.

Стилизация сложных компонентов

Меню и выпадающие списки React Aria предоставляет хуки useMenu, useMenuItem и useMenuTrigger для реализации полностью доступного меню. Tailwind CSS позволяет оформлять меню как визуально привлекательный компонент, включая hover и focus эффекты.

import { useMenu, useMenuItem } from '@react-aria/menu';
import { useMenuTrigger } from '@react-aria/menu';

function Dropdown({ items }) {
  let ref = React.useRef();
  let { menuTriggerProps, menuProps, isOpen } = useMenuTrigger({}, ref);

  return (
    <div className="relative inline-block">
      <button {...menuTriggerProps} ref={ref} className="px-4 py-2 bg-gray-700 text-white rounded">
        Открыть меню
      </button>
      {isOpen && (
        <ul {...menuProps} className="absolute mt-2 w-48 bg-white shadow-lg rounded border">
          {items.map((item) => (
            <MenuItem key={item.key} item={item} />
          ))}
        </ul>
      )}
    </div>
  );
}

function MenuItem({ item }) {
  let ref = React.useRef();
  let { menuItemProps, isFocused, isSelected } = useMenuItem({ key: item.key }, null, ref);

  return (
    <li
      {...menuItemProps}
      ref={ref}
      className={`px-4 py-2 cursor-pointer ${isFocused ? 'bg-blue-100' : ''} ${
        isSelected ? 'font-bold' : ''
      }`}
    >
      {item.name}
    </li>
  );
}

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

Динамическое управление стилями

Tailwind CSS предоставляет утилиту clsx или classnames для условного добавления классов в зависимости от состояния, что идеально сочетается с хуками React Aria:

import clsx from 'clsx';

<div
  className={clsx(
    'px-3 py-2 rounded transition',
    isFocused && 'ring-2 ring-blue-400',
    isDisabled && 'opacity-50 cursor-not-allowed'
  )}
>
  Контент
</div>

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

Адаптивные интерфейсы

Tailwind CSS поддерживает медиазапросы и адаптивные классы (sm:, md:, lg:), что позволяет создавать доступные интерфейсы с изменением размеров и расположения элементов, при этом React Aria сохраняет корректное поведение клавиатурной навигации и доступных атрибутов.

Заключение по подходу

Интеграция React Aria и Tailwind CSS обеспечивает полный контроль над поведением и стилями компонентов. React Aria отвечает за доступность, управляемые состояния и взаимодействие с пользователем, а Tailwind CSS делает интерфейс современным, лаконичным и легко адаптируемым под любые темы и устройства. Такой подход позволяет создавать масштабируемые, доступные и визуально привлекательные React-приложения.