Подходы к стилизации

React Aria предоставляет мощный набор хуков и компонентов, ориентированных на доступность интерфейсов. Однако библиотека не навязывает конкретный способ стилизации. Стилизация компонентов остаётся гибкой и может быть реализована с использованием стандартных CSS, CSS-in-JS, Tailwind, Styled Components или любых других подходов, которые применяются в React.


Стилизация через классические CSS-классы

Наиболее прямолинейный способ — назначение CSS-классов на элементы, возвращаемые из хуков React Aria. Например, при работе с кнопками через useButton:

import { useButton } from "@react-aria/button";

function Button({ children, ...props }) {
  let ref = React.useRef();
  let { buttonProps } = useButton(props, ref);

  return (
    <button
      {...buttonProps}
      ref={ref}
      className="btn-primary btn-large"
    >
      {children}
    </button>
  );
}

Ключевые моменты:

  • useButton возвращает buttonProps, которые должны быть обязательно применены к элементу для корректной работы доступности.
  • Все визуальные стили полностью отделены от логики и применяются через обычные CSS-классы.
  • Такой подход сохраняет совместимость с существующими CSS-фреймворками и минимизирует вмешательство в структуру DOM.

Инлайн-стили с React

React Aria не запрещает использование инлайн-стилей. Это удобно для динамических значений, которые зависят от состояния компонента. Например, для визуального выделения активного элемента:

import { useTab } from "@react-aria/tabs";

function Tab({ item, state }) {
  let ref = React.useRef();
  let { tabProps } = useTab({ key: item.key }, state, ref);

  return (
    <button
      {...tabProps}
      ref={ref}
      style={{
        padding: "8px 16px",
        backgroundColor: state.selectedKey === item.key ? "#0366d6" : "#f0f0f0",
        color: state.selectedKey === item.key ? "#fff" : "#000",
      }}
    >
      {item.name}
    </button>
  );
}

Особенности инлайн-стилей:

  • Простота применения при динамических условиях.
  • Ограничения на псевдоклассы (:hover, :focus) и медиа-запросы.
  • Используется совместно с хуками состояния React Aria для синхронизации визуальных состояний и доступности.

CSS-in-JS и Styled Components

React Aria прекрасно интегрируется с CSS-in-JS решениями. Например, использование Styled Components позволяет создавать стилизованные компоненты с учётом состояния и пропсов React Aria:

import styled from "styled-components";
import { useButton } from "@react-aria/button";

const StyledButton = styled.button`
  padding: 10px 20px;
  border-radius: 4px;
  background-color: ${({ isActive }) => (isActive ? "#0366d6" : "#e0e0e0")};
  color: ${({ isActive }) => (isActive ? "#fff" : "#000")};
  &:hover {
    background-color: ${({ isActive }) => (isActive ? "#0256b3" : "#d0d0d0")};
  }
  &:focus {
    outline: 2px solid #0366d6;
  }
`;

function Button({ children, ...props }) {
  let ref = React.useRef();
  let { buttonProps } = useButton(props, ref);

  return (
    <StyledButton {...buttonProps} ref={ref} isActive={props.isActive}>
      {children}
    </StyledButton>
  );
}

Преимущества CSS-in-JS:

  • Полная управляемость состояниями компонента.
  • Локальная область видимости стилей без риска конфликтов.
  • Возможность прямого доступа к пропсам для условной стилизации.

Стилизация с использованием Tailwind CSS

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

import { useSwitch } from "@react-aria/switch";

function ToggleSwitch({ isSelected, onChange }) {
  let ref = React.useRef();
  let { inputProps } = useSwitch({ isSelected, onChange }, ref);

  return (
    <label className="inline-flex items-center cursor-pointer">
      <input {...inputProps} ref={ref} className="sr-only" />
      <span
        className={`w-10 h-6 rounded-full transition-colors ${
          isSelected ? "bg-blue-600" : "bg-gray-300"
        }`}
      />
    </label>
  );
}

Особенности Tailwind:

  • Быстрая визуализация состояния через условные классы.
  • Минимизация количества кастомного CSS.
  • Отличная совместимость с хуками React Aria благодаря разделению логики и внешнего вида.

Подход «комбинированной стилизации»

На практике часто используется сочетание нескольких подходов:

  • Базовая структура через CSS-классы.
  • Динамические состояния через инлайн-стили или Styled Components.
  • Вспомогательные утилиты (Tailwind или CSS-модули) для мелких визуальных деталей.

Такой гибридный метод позволяет:

  • Сохранять чистоту DOM и поддерживать доступность.
  • Легко поддерживать дизайн-систему.
  • Гибко изменять внешний вид без переписывания логики компонентов React Aria.

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

React Aria возвращает из хуков свойства состояния (isPressed, isSelected, isDisabled, focusVisible и др.), которые можно напрямую использовать для стилизации:

import { useCheckbox } from "@react-aria/checkbox";

function Checkbox({ isSelected, onChange, children }) {
  let ref = React.useRef();
  let { inputProps, isSelected: ariaSelected } = useCheckbox({ isSelected, onChange }, ref);

  return (
    <label className={`flex items-center cursor-pointer ${ariaSelected ? "font-bold" : ""}`}>
      <input {...inputProps} ref={ref} className="mr-2" />
      {children}
    </label>
  );
}

Выводы по управлению состояниями:

  • Использование состояний из хуков гарантирует корректное соответствие визуальных эффектов и доступности.
  • Любые стили, применяемые к состояниям, должны быть синхронизированы с aria-* атрибутами, возвращаемыми React Aria.
  • Такой подход повышает предсказуемость интерфейсов и упрощает тестирование доступности.