@adrienlcp/react-aria
What every react-aria app of mine repeats: a className merge that follows the render state, and a Sass focus ring on data-focus-visible
Works with
- React Aria
- React
- TypeScript
- Sassoptional peer
Install
pnpm add @adrienlcp/react-ariaExports
Grouped by the section of the documentation that explains them. A row leads to its section.
Merging a className1 export
A focus ring: focus5 exports
$ring-widthConfigure once, in the app's own_focus.sass:@forward '@adrienlcp/react-aria/focus' with ($ring-color: var(--focus)).@adrienlcp/Sassreact-aria/ focus $ring-color@adrienlcp/Sassreact-aria/ focus $ring-offset@adrienlcp/Sassreact-aria/ focus ringreact-aria stampsdata-focus-visibleon keyboard focus only, and on the element it styles: a control built over a hidden input rings through it alone.@adrienlcp/Sassreact-aria/ focus ring-insetThe ring drawn inside the box, for an element a clipping ancestor would cut.@adrienlcp/Sassreact-aria/ focus
Documented in the source only1 export
Documentation
The README and the documents beside it, as written in the repository.
OverviewREADME.md
What every app of mine built on
react-aria-components repeats,
kept in one version across them. React 19 and react-aria-components are
peers; Sass is an optional one, for the focus module.
pnpm add @adrienlcp/react-ariaMerging a classNameREADME.md
import { composeClassName } from '@adrienlcp/react-aria'
import { Button as AriaButton, type ButtonProps } from 'react-aria-components'
export const Button = ({ className, isWide, ...props }: ButtonProps & { isWide?: boolean }) => (
<AriaButton {...props} className={composeClassName(className, 'button', isWide && 'wide')} />
)react-aria lets className be a function of the component's render state, so
the merge is a function too, built on react-aria's own composeRenderProps: it
puts the component's own class names first, resolves the caller's against the
render state, and drops the falsy ones. It fits a react-aria component, never a
plain DOM element, where a template literal does.
A focus ring: focusREADME.md
ring and ring-inset draw the outline on [data-focus-visible], which
react-aria stamps on keyboard focus only, and on :focus-visible, for a native
element. A control built over a hidden input — a switch, a checkbox — only
rings through the attribute, since the focused element is the invisible input.
@use '@adrienlcp/react-aria/focus'
.button
@include focus.ring
&[data-hovered]:not([data-disabled])
background: var(--hover)ring-inset draws inside the box, for an element a clipping ancestor would
cut. Configure the ring once, in the app's own _focus.sass, and have
components @use that file:
@forward '@adrienlcp/react-aria/focus' with ($ring-color: var(--focus), $ring-offset: 3px, $ring-width: 3px)$ring-width (2px), $ring-color (currentColor) and $ring-offset
(3px) are the defaults. There is no hover mixin: react-aria's
[data-hovered] already ignores the hover a touch screen emulates after a tap,
so a hover style is a plain &[data-hovered] rule.
Resolved through the sass export condition, which Vite reads; with the Sass
CLI, use pkg:@adrienlcp/react-aria/focus and --pkg-importer=node.