React Aria предоставляет мощные инструменты для построения доступных пользовательских интерфейсов, концентрируясь на поведении и управлении состоянием компонентов, оставляя стилизацию на усмотрение разработчика. Интеграция CSS-in-JS позволяет создавать динамические стили, тесно связывая их с состоянием компонентов, что особенно полезно при работе с интерактивными элементами, такими как кнопки, вкладки, модальные окна и выпадающие списки.
Для интеграции React Aria с CSS-in-JS чаще всего используют следующие подходы:
Styled Components Позволяет создавать компонентные стили с использованием шаблонных литералов:
import styled from 'styled-components';
const Button = styled.button`
background-color: ${props => props.isPressed ? 'blue' : 'gray'};
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
background-color: ${props => props.isPressed ? 'darkblue' : 'darkgray'};
}
`;Emotion Предоставляет возможность создавать
стили с использованием функций css и styled, а
также динамически изменять их на основе пропсов:
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import { useButton } from '@react-aria/button';
function CustomButton(props) {
let ref = React.useRef();
let { buttonProps, isPressed } = useButton(props, ref);
const buttonStyle = css`
background-color: ${isPressed ? 'blue' : 'gray'};
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
background-color: ${isPressed ? 'darkblue' : 'darkgray'};
}
`;
return <button {...buttonProps} ref={ref} css={buttonStyle}>{props.children}</button>;
}Stitches Предоставляет декларативный синтаксис для создания системных стилей с поддержкой вариаций:
import { styled } from '@stitches/react';
import { useButton } from '@react-aria/button';
const Button = styled('button', {
padding: '8px 16px',
borderRadius: '4px',
border: 'none',
color: 'white',
variants: {
pressed: {
true: { backgroundColor: 'blue' },
false: { backgroundColor: 'gray' },
},
},
'&:hover': {
variants: {
pressed: {
true: { backgroundColor: 'darkblue' },
false: { backgroundColor: 'darkgray' },
},
},
},
});
function CustomButton(props) {
let ref = React.useRef();
let { buttonProps, isPressed } = useButton(props, ref);
return <Button {...buttonProps} ref={ref} pressed={isPressed}>{props.children}</Button>;
}React Aria предоставляет хуки для управления поведением компонентов без привязки к стилям:
useButton — отслеживает состояние нажатия и фокус.useCheckbox — управляет состоянием чекбоксов и
aria-атрибутами.useMenu / useMenuItem — реализует
доступные контекстные меню.Интеграция с CSS-in-JS заключается в передаче этих состояний в пропсы стилей:
const buttonStyle = css`
background-color: ${isPressed ? 'blue' : 'gray'};
outline: ${isFocusVisible ? '2px solid orange' : 'none'};
`;
Важно учитывать focus-visible и другие состояния доступности, чтобы визуальная индикация соответствовала стандартам WCAG.
CSS-in-JS позволяет создавать стили на лету в зависимости от состояния компонента:
Пример с табами:
import { useTab, useTabList } from '@react-aria/tabs';
import { styled } from '@stitches/react';
const TabButton = styled('button', {
padding: '8px 16px',
border: 'none',
borderBottom: '2px solid transparent',
variants: {
selected: {
true: { borderBottomColor: 'blue', fontWeight: 'bold' },
false: { borderBottomColor: 'transparent', fontWeight: 'normal' },
},
},
});
function Tab({ item, state }) {
let ref = React.useRef();
let { tabProps, isSelected } = useTab({ key: item.key }, state, ref);
return (
<TabButton {...tabProps} ref={ref} selected={isSelected}>
{item.name}
</TabButton>
);
}
tw для быстрого
прототипирования.CSS-in-JS и React Aria создают мощное сочетание: доступная логика компонентов управляется React Aria, а динамическая, полностью кастомизируемая стилизация — через CSS-in-JS. Это обеспечивает гибкость, удобство поддержки и соответствие современным стандартам веб-разработки.