Стилизация состояний

React Aria предоставляет мощный инструмент для создания доступных компонентов пользовательского интерфейса, включая детальное управление различными состояниями: hover, focus, pressed, selected, disabled и другими. Стилизация этих состояний важна для обеспечения понятной визуальной обратной связи пользователю и соответствия стандартам доступности.


Хуки для управления состояниями

Библиотека основана на хуках, которые предоставляют доступ к состояниям компонента и атрибутам для правильного взаимодействия с DOM.

useButton

useButton управляет состоянием кнопки, включая фокус, нажатие и отключение:

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

function Button(props) {
  let ref = useRef();
  let {buttonProps, isPressed} = useButton(props, ref);

  return (
    <button
      {...buttonProps}
      ref={ref}
      style={{
        backgroundColor: isPressed ? 'darkblue' : 'blue',
        color: 'white',
        padding: '8px 16px',
        border: 'none',
        borderRadius: '4px',
        cursor: props.isDisabled ? 'not-allowed' : 'pointer',
        opacity: props.isDisabled ? 0.5 : 1
      }}
    >
      {props.children}
    </button>
  );
}

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

  • isPressed позволяет менять стили при удержании кнопки.
  • buttonProps содержит атрибуты для доступности (aria-disabled, обработчики событий).
  • Поддержка isDisabled автоматически блокирует интерактивность.

useHover

Для визуального отображения состояния наведения применяется хук useHover:

import {useHover} from '@react-aria/interactions';
import {useState, useRef} from 'react';

function HoverableDiv() {
  let ref = useRef();
  let {hoverProps, isHovered} = useHover({ref});

  return (
    <div
      {...hoverProps}
      ref={ref}
      style={{
        padding: '20px',
        backgroundColor: isHovered ? 'lightgray' : 'white',
        border: '1px solid black',
        borderRadius: '4px',
        transition: 'background-color 0.2s'
      }}
    >
      Наведи курсор сюда
    </div>
  );
}

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

  • isHovered позволяет динамически менять цвет фона или другие стили.
  • Все события наведения учитываются для сенсорных и мышиных устройств.

useFocus

Состояние фокуса критично для доступности:

import {useFocus} from '@react-aria/interactions';
import {useRef, useState} from 'react';

function FocusableInput() {
  let ref = useRef();
  let {focusProps, isFocused} = useFocus({ref});

  return (
    <input
      {...focusProps}
      ref={ref}
      style={{
        padding: '8px',
        border: '2px solid',
        borderColor: isFocused ? 'blue' : 'gray',
        borderRadius: '4px',
        outline: 'none'
      }}
    />
  );
}

Примечание:

  • isFocused помогает выделять элемент при клавиатурной навигации.
  • focusProps содержит обработчики onFocus и onBlur с поддержкой доступности.

Композиция состояний

React Aria позволяет комбинировать несколько состояний одновременно. Например, кнопка может быть hovered, pressed и disabled:

import {useButton} from '@react-aria/button';
import {useHover} from '@react-aria/interactions';
import {useRef} from 'react';

function InteractiveButton(props) {
  let ref = useRef();
  let {buttonProps, isPressed} = useButton(props, ref);
  let {hoverProps, isHovered} = useHover({ref});

  return (
    <button
      {...buttonProps}
      {...hoverProps}
      ref={ref}
      style={{
        backgroundColor: isPressed ? 'darkblue' : isHovered ? 'lightblue' : 'blue',
        color: 'white',
        padding: '8px 16px',
        border: 'none',
        borderRadius: '4px',
        cursor: props.isDisabled ? 'not-allowed' : 'pointer',
        opacity: props.isDisabled ? 0.5 : 1,
        transition: 'background-color 0.2s'
      }}
    >
      {props.children}
    </button>
  );
}

Особенности композиции:

  • Хуки могут объединяться без конфликта событий.
  • Стили корректно реагируют на комбинации состояний, создавая интуитивно понятный интерфейс.

Использование useToggleState и useCheckboxState

Для компонентов выбора (Checkbox, Switch) важно управлять состоянием выбора:

import {useToggleState} from '@react-stately/toggle';
import {useCheckbox} from '@react-aria/checkbox';
import {useRef} from 'react';

function Checkbox(props) {
  let state = useToggleState(props);
  let ref = useRef();
  let {inputProps} = useCheckbox(props, state, ref);

  return (
    <label style={{display: 'flex', alignItems: 'center', gap: '8px'}}>
      <input {...inputProps} ref={ref} />
      <span style={{fontWeight: state.isSelected ? 'bold' : 'normal'}}>
        {props.children}
      </span>
    </label>
  );
}

Состояния:

  • state.isSelected управляет стилями выбранного элемента.
  • Поддержка aria-checked встроена в inputProps.

Стилизация с условными классами

Часто удобнее управлять классами вместо inline-стилей:

function getButtonClass({isHovered, isPressed, isDisabled}) {
  if (isDisabled) return 'btn disabled';
  if (isPressed) return 'btn pressed';
  if (isHovered) return 'btn hovered';
  return 'btn';
}

CSS пример:

.btn { background-color: blue; color: white; padding: 8px 16px; border-radius: 4px; }
.btn.hovered { background-color: lightblue; }
.btn.pressed { background-color: darkblue; }
.btn.disabled { opacity: 0.5; cursor: not-allowed; }

Такой подход облегчает поддержку и масштабирование стилей, особенно при сложных компонентах с множеством состояний.


Основные принципы стилизации состояний в React Aria

  1. Использовать хуки для управления состояниями, чтобы обеспечить доступность.
  2. Не полагаться только на цвет, добавлять изменения формы, тени или текста для выделения состояний.
  3. Комбинировать хуки для комплексных интерактивных элементов.
  4. Синхронизировать визуальные состояния с атрибутами ARIA, чтобы компоненты были понятны для ассистивных технологий.
  5. Использовать условные классы или inline-стили для наглядной и отзывчивой визуальной обратной связи.

React Aria позволяет создавать полностью доступные и визуально динамичные компоненты, где каждое состояние тщательно контролируется и легко стилизуется. Управление hover, focus, pressed и selected состояниями становится интуитивным благодаря единообразным хукам и интеграции с ARIA-атрибутами.