An open API service indexing awesome lists of open source software.

https://github.com/palmerhq/radio-group

845 byte WAI-ARIA 1.1 compliant radio group React component
https://github.com/palmerhq/radio-group

a11y formik forms radio-buttons react react-dom wai-aria

Last synced: about 1 month ago
JSON representation

845 byte WAI-ARIA 1.1 compliant radio group React component

Awesome Lists containing this project

README

          

# `@palmerhq/radio-group`

An accessible [WAI-ARIA 1.1-compliant Radio Group](https://www.w3.org/TR/wai-aria-practices-1.1/#radiobutton) React component.

Radio group demo

- [`@palmerhq/radio-group`](#palmerhqradio-group)
- [Installation](#installation)
- [Usage](#usage)
- [Usage with Formik v2](#usage-with-formik-v2)
- [API Reference](#api-reference)
- [``](#radiogroup-)
- [`labelledBy?: string`](#labelledby-string)
- [`onChange: (value: any) => void`](#onchange-value-any--void)
- [`children: React.ComponentType[]`](#children-reactcomponenttyperadioprops)
- [`value: any`](#value-any)
- [`as?: React.ComponentType`](#as-reactcomponenttype)
- [`autoFocus?: boolean`](#autofocus-boolean)
- [``](#radio)
- [`value: any`](#value-any-1)
- [`onFocus?: () => void`](#onfocus---void)
- [`onBlur?: () => void`](#onblur---void)
- [`as?: React.ComponentType`](#as-reactcomponenttype-1)
- [Underlying DOM Structure](#underlying-dom-structure)
- [Overriding Styles](#overriding-styles)
- [Accessibility Features](#accessibility-features)
- [Authors](#authors)

## Installation

```
yarn add @palmerhq/radio-group
```

Or try it out in your browser on [CodeSandbox](https://codesandbox.io/embed/qxxnwzvy0w)

> Note: This package uses `Array.prototype.findIndex`, so be sure that you have properly polyfilled.

## Usage

```tsx
import * as React from 'react';
import { RadioGroup, Radio } from '@palmerhq/radio-group';
import '@palmerhq/radio-group/styles.css'; // use the default styles

function App() {
const [value, setValue] = React.useState();

return (
<>

Color


setValue(value)}
>
Blue
Red
Green

>
);
}
```

### Usage with Formik v2

```tsx
import * as React from 'react';
import { Formik, Form, useField } from 'formik';
import { RadioGroup, Radio } from '@palmerhq/radio-group';
import '@palmerhq/radio-group/styles.css'; // use the default styles

function FRadioGroup(props) {
const [{ onChange, onBlur, ...field }] = useField(props.name);
return (

);
}

function App() {
return (
{
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 500);
}}
>

Color



Blue
Red
Green



);
}
```

## API Reference

### ``

This renders a `div` and will pass through all props to the DOM element. It's children must be `` components.

#### `labelledBy?: string`

This should match the `id` you used to label the radio group.

```tsx

Color

{/* ... */}

```

#### `onChange: (value: any) => void`

A callback function that will be fired with the `value` of the newly selected item.

```tsx
import * as React from 'react';
import { RadioGroup, Radio } from '@palmerhq/radio-group';
import '@palmerhq/radio-group/styles.css'; // use the default styles

function App() {
const [value, setValue] = React.useState();

return (
<>

Color


setValue(value)}
>
Blue
Red
Green

>
);
}
```

#### `children: React.ComponentType[]`

**Required**

The children of a `` can **ONLY** be `` components. In order to support compliant keyboard behavior, each sibling must know the value of the whole group and so `React.Children.map` is used internally.

```tsx

Color

{/* ... */}

```

#### `value: any`

**Required**

The current value of the radio group. This is shallowly compared to each `value` prop of the child `` components to determine which item is active.

#### `as?: React.ComponentType`

Component to use a the wrapper. Default is `

`.

#### `autoFocus?: boolean`

Whether to autoFocus the selected radio option.

### ``

This renders a `div` with a data attribute `data-palmerhq-radio` and all the relevant perfect aria attributes. The React component will pass through all props to the DOM element.

#### `value: any`

**Required**

The value of the radio button. This will be set / passed back to the `` when the item is selected.

#### `onFocus?: () => void`

Callback function for when the item is focused. When focused, a data attribute `data-palmerhq-radio-focus` is set to `"true"`. You can thus apply the selector to manage focus style like so:

```css
[data-palmerhq-radio][data-palmerhq-radio-focus='true'] {
background: blue;
}
```

#### `onBlur?: () => void`

Callback function for when the item is blurred

#### `as?: React.ComponentType`

Component to use as radio. Default is `

`.

### Underlying DOM Structure

For reference, the underlying HTML DOM structure are all `div`s and looks as follows.

```html



Red


Green


Blue


```

### Overriding Styles

These are the default styles. Copy and paste the following into your app to customize them.

```css
[data-palmerhq-radio-group] {
padding: 0;
margin: 0;
list-style: none;
}

[data-palmerhq-radio-group]:focus {
outline: none;
}

[data-palmerhq-radio] {
border: 2px solid transparent;
border-radius: 5px;
display: inline-block;
position: relative;
padding: 0.125em;
padding-left: 1.5em;
padding-right: 0.5em;
cursor: default;
outline: none;
}

[data-palmerhq-radio] + [data-palmerhq-radio] {
margin-left: 1em;
}

[data-palmerhq-radio]::before,
[data-palmerhq-radio]::after {
position: absolute;
top: 50%;
left: 7px;
transform: translate(-20%, -50%);
content: '';
}

[data-palmerhq-radio]::before {
width: 14px;
height: 14px;
border: 1px solid hsl(0, 0%, 66%);
border-radius: 100%;
background-image: linear-gradient(to bottom, hsl(300, 3%, 93%), #fff 60%);
}

[data-palmerhq-radio]:active::before {
background-image: linear-gradient(
to bottom,
hsl(300, 3%, 73%),
hsl(300, 3%, 93%)
);
}

[data-palmerhq-radio][aria-checked='true']::before {
border-color: hsl(216, 80%, 50%);
background: hsl(217, 95%, 68%);
background-image: linear-gradient(
to bottom,
hsl(217, 95%, 68%),
hsl(216, 80%, 57%)
);
}

[data-palmerhq-radio][aria-checked='true']::after {
display: block;
border: 0.1875em solid #fff;
border-radius: 100%;
transform: translate(25%, -50%);
}

[data-palmerhq-radio][aria-checked='mixed']:active::before,
[data-palmerhq-radio][aria-checked='true']:active::before {
background-image: linear-gradient(
to bottom,
hsl(216, 80%, 57%),
hsl(217, 95%, 68%) 60%
);
}

[data-palmerhq-radio]:hover::before {
border-color: hsl(216, 94%, 65%);
}

[data-palmerhq-radio][data-palmerhq-radio-focus='true'] {
border-color: hsl(216, 94%, 73%);
background-color: hsl(216, 80%, 97%);
}

[data-palmerhq-radio]:hover {
background-color: hsl(216, 80%, 92%);
}
```

## Accessibility Features

- Uses CSS attribute selectors for synchronizing `aria-checked` state with the visual state indicator.
- Uses CSS `:hover` and `:focus` pseudo-selectors for styling visual keyboard focus and hover.
- Focus indicator encompasses both radio button and label, making it easier to perceive which option is being chosen.
- Hover changes background of both radio button and label, making it easier to perceive that clicking either the label or button will activate the radio button.

Keyboard Support



Key
Function




Tab


  • Moves focus to the checked radio button in the radiogroup.

  • If a radio button is not checked, focus moves to the first radio button in the group.





Space


  • If the radio button with focus is not checked, changes the state to checked.

  • Otherwise, does nothing.

  • Note: The state where a radio is not checked only occurs on page load.





Right arrow


  • Moves focus to and checks the next radio button in the group.

  • If focus is on the last radio button, moves focus to the first radio button.

  • The state of the previously checked radio button is changed to unchecked.





Down arrow


  • Moves focus to and checks the next radio button in the group.

  • If focus is on the last radio button, moves focus to the first radio button.

  • The state of the previously checked radio button is changed to unchecked.





Left arrow


  • Moves focus to and checks the previous radio button in the group.

  • If focus is on the first radio button, moves focus to and checks the last radio button.

  • The state of the previously checked radio button is changed to unchecked.





Up arrow


  • Moves focus to and checks the previous radio button in the group.

  • If focus is on the first radio button, moves focus to and checks the last radio button.

  • The state of the previously checked radio button is changed to unchecked.




Role, Property, State, and Tabindex Attributes


Role
Attributes
Element
Usage


radiogroup

div


  • Identifies the div element as a container for a group of radio buttons.

  • Is not focusable because focus is managed using a roving tabindex strategy as described below.






aria-labelledby="[IDREF]"
div
Refers to the element that contains the label of the radio group.


radio

div


  • Identifies the div element as an ARIA radio button.

  • The accessible name is computed from the child text content of the div element.






tabindex="-1"
div


  • Makes the element focusable but not part of the page Tab sequence.

  • Applied to all radio buttons contained in the radio group except for one that is included in the page Tab sequence.

  • This approach to managing focus is described in the section on roving tabindex.






tabindex="0"
div


  • Makes the radio button focusable and includes it in the page Tab sequence.

  • Set on only one radio in the radio group.

  • On page load, is set on the first radio button in the radio group.

  • Moves with focus inside the radio group so the most recently focused radio button is included in the page Tab sequence.

  • This approach to managing focus is described in the section on roving tabindex.






aria-checked="false"
div


  • Identifies radio buttons which are not checked.

  • CSS attribute selectors (e.g. [aria-checked="false"]) are used to synchronize the visual states with the value of the aria-checked attribute.

  • The CSS ::before pseudo-class is used to indicate visual state of unchecked radio buttons to support high contrast settings in operating systems and browsers.






aria-checked="true"
div


  • Identifies the radio button which is checked.

  • CSS attribute selectors (e.g. [aria-checked="true"]) are used to synchronize the visual states with the value of the aria-checked attribute.

  • The CSS ::before pseudo-class is used to indicate visual state of checked radio buttons to support high contrast settings in operating systems and browsers.





## Authors

- Jared Palmer ([@jaredpalmer](https://twitter.com/jaredpalmer))

---

> MIT License