В React Aria условные стили позволяют динамически изменять визуальное
оформление компонентов в зависимости от их состояния: фокуса, выбора,
наведения, активности и других интерактивных состояний. Основной принцип
работы заключается в использовании предоставляемых библиотекой хуков,
которые возвращают объект state и объект
props, включающий атрибуты доступности и события, а также
информацию о текущем состоянии компонента.
Хук useButton позволяет управлять кнопками с учётом
доступности:
import { useButton } from '@react-aria/button';
import { useRef } from 'react';
function MyButton({ children, onPress }) {
let ref = useRef();
let { buttonProps, isPressed } = useButton({ onPress }, ref);
return (
<button
{...buttonProps}
ref={ref}
className={isPressed ? 'button-pressed' : 'button-default'}
>
{children}
</button>
);
}
buttonProps — объект, содержащий все
необходимые атрибуты для кнопки, включая aria-* свойства и
обработчики событий.isPressed — состояние нажатия, которое
удобно использовать для применения условных стилей.Хук useCheckbox обеспечивает управление состоянием
галочек с поддержкой доступности:
import { useCheckbox } from '@react-aria/checkbox';
import { useRef, useState } from 'react';
function MyCheckbox() {
let [isSelected, setSelected] = useState(false);
let ref = useRef();
let { inputProps } = useCheckbox({ isSelected, onChange: setSelected }, ref);
return (
<label className={isSelected ? 'checkbox-checked' : 'checkbox-unchecked'}>
<input {...inputProps} ref={ref} />
Подписка
</label>
);
}
isSelected можно использовать для
изменения классов CSS, цвета фона или отображения иконки состояния.Хук useToggleButton создаёт кнопку с переключаемым
состоянием:
import { useToggleButton } from '@react-aria/button';
import { useRef, useState } from 'react';
function ToggleFavorite() {
let [isSelected, setSelected] = useState(false);
let ref = useRef();
let { buttonProps } = useToggleButton({ isSelected, onChange: setSelected }, ref);
return (
<button
{...buttonProps}
ref={ref}
className={isSelected ? 'favorite-active' : 'favorite-inactive'}
>
{isSelected ? '★' : '☆'}
</button>
);
}
isSelected, что
позволяет менять визуальные индикаторы без сложной логики.mergeProps для условных классовВ сложных компонентах часто нужно объединять несколько наборов
атрибутов и классов. React Aria предоставляет mergeProps
для безопасного комбинирования обработчиков и атрибутов:
import { mergeProps } from '@react-aria/utils';
import { useButton } from '@react-aria/button';
import { useRef, useState } from 'react';
function AdvancedButton({ onPress }) {
let ref = useRef();
let { buttonProps, isPressed } = useButton({ onPress }, ref);
let combinedProps = mergeProps(buttonProps, {
className: isPressed ? 'btn-pressed' : 'btn-default'
});
return <button {...combinedProps} ref={ref}>Нажми меня</button>;
}
useFocus и useHover для динамических
стилейХук useFocus предоставляет состояние фокуса и
обработчики:
import { useFocus } from '@react-aria/interactions';
import { useRef, useState } from 'react';
function FocusInput() {
let ref = useRef();
let [isFocused, setFocused] = useState(false);
let { focusProps } = useFocus({
onFocusChange: setFocused
});
return (
<input
{...focusProps}
ref={ref}
className={isFocused ? 'input-focused' : 'input-blur'}
/>
);
}
isFocused можно использовать для
изменения бордера, тени или других визуальных индикаторов.Хук useHover отслеживает наведение мыши:
import { useHover } from '@react-aria/interactions';
import { useRef, useState } from 'react';
function HoverableBox() {
let ref = useRef();
let [isHovered, setHovered] = useState(false);
let { hoverProps } = useHover({
onHoverChange: setHovered
});
return (
<div
{...hoverProps}
ref={ref}
className={isHovered ? 'box-hovered' : 'box-default'}
>
Наведи на меня
</div>
);
}
isHovered позволяет добавлять анимации, тени
или изменять фон без вмешательства в структуру компонента.Комбинируя useFocus, useHover и
useButton, можно создавать компоненты с комплексными
визуальными состояниями:
import { useButton } from '@react-aria/button';
import { useFocus, useHover } from '@react-aria/interactions';
import { mergeProps } from '@react-aria/utils';
import { useRef, useState } from 'react';
function InteractiveButton({ onPress }) {
let ref = useRef();
let { buttonProps, isPressed } = useButton({ onPress }, ref);
let [isFocused, setFocused] = useState(false);
let [isHovered, setHovered] = useState(false);
let { focusProps } = useFocus({ onFocusChange: setFocused });
let { hoverProps } = useHover({ onHoverChange: setHovered });
let combinedProps = mergeProps(buttonProps, focusProps, hoverProps, {
className: isPressed
? 'btn-pressed'
: isHovered
? 'btn-hovered'
: isFocused
? 'btn-focused'
: 'btn-default'
});
return <button {...combinedProps} ref={ref}>Кнопка</button>;
}
isPressed, isSelected, isFocused,
isHovered.mergeProps.button-pressed, button-hovered.aria-*
атрибутами, предоставляемыми хуками.Такой подход обеспечивает универсальность, упрощает поддержку сложных компонентов и делает визуальные состояния интуитивно понятными как для разработчиков, так и для пользователей с различными потребностями.