Skip to content

Commit

Permalink
Add CheckboxGroup and RadioGroup components (#830)
Browse files Browse the repository at this point in the history
* add CheckboxGroup, RadioGroup, and InputGroup components

* add changeset

* update snapshots

* improve changeset

* remove unused InputGroup test file

* fixed broken animation

* github-actions[bot] Regenerated snapshots

* rename InputGroup to ControlGroup

* reset snapshots

* reduce Caption and Validation font-size to 100

* rename CSS declaration file

* github-actions[bot] Regenerated snapshots

* add documentation for CheckboxGroup and RadioGroup components

* reduce font-weight on FormControl labels within a ControlGroup

* github-actions[bot] Regenerated snapshots

* update changeset

* update changeset semver bump

* various docs updates based on PR feedback

* leverage Text component

* split stories up into multiple fies

* remove regex

* updated docs to align with prc

* fix tabs in React docs

* fix case

* stop forwarding unused prop to Radio

* correct casing

* modify styles to avoid :global selector

* update animation easing

* update links in docs

* update changeset

* github-actions[bot] Regenerated snapshots

* remove nested describe

---------

Co-authored-by: joshfarrant <[email protected]>
  • Loading branch information
joshfarrant and joshfarrant authored Dec 3, 2024
1 parent c008e13 commit 1f9eb72
Show file tree
Hide file tree
Showing 30 changed files with 1,366 additions and 1 deletion.
49 changes: 49 additions & 0 deletions .changeset/popular-seas-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
'@primer/react-brand': minor
---

New `CheckboxGroup` and `RadioGroup` components to group `Checkbox` and `Radio` components are now available.

`CheckboxGroup`

```jsx
<CheckboxGroup>
<CheckboxGroup.Label>Choose your favorite features</CheckboxGroup.Label>
<FormControl>
<FormControl.Label>Actions notifications</FormControl.Label>
<Checkbox value="actions" />
</FormControl>
<FormControl>
<FormControl.Label>Packages</FormControl.Label>
<Checkbox value="packages" />
</FormControl>
<FormControl>
<FormControl.Label>Codespaces</FormControl.Label>
<Checkbox value="codespaces" />
</FormControl>
</CheckboxGroup>
```

🔗 [Read the documentation for more `CheckboxGroup` examples](https://primer.style/brand/components/RadioGroup/react)

`RadioGroup`:

```jsx
<RadioGroup>
<RadioGroup.Label>Choose your primary workspace</RadioGroup.Label>
<FormControl>
<FormControl.Label>Codespaces</FormControl.Label>
<Radio name="workspace" value="codespaces" />
</FormControl>
<FormControl>
<FormControl.Label>Local environment</FormControl.Label>
<Radio name="workspace" value="local" />
</FormControl>
<FormControl>
<FormControl.Label>Pen and paper</FormControl.Label>
<Radio name="workspace" value="remote" />
</FormControl>
</RadioGroup>
```

🔗 [Read the documentation for more `RadioGroup` examples](https://primer.style/brand/components/RadioGroup/react)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions apps/docs/content/components/CheckboxGroup/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: Checkbox group
description: Checkbox group renders a set of checkboxes.
---

import ComponentLayout from '../../../src/layouts/component-layout'
export default ComponentLayout

import anatomy from './images/anatomy.png'

## Usage

Use checkbox group to allow users to select multiple items from a list of individual items, or to mark one individual item as selected.

### Best practices

- Put checkboxes in a logical order
- If users are only allowed to select a single option, consider using a [radio group](/components/RadioGroup) instead
- Each checkbox's state should be independent from other checkboxes in the group. For example: checking one checkbox should not check or disable any other checkboxes

## Anatomy

<img src={anatomy} alt="Anatomy diagram" />

**Label:** A title that labels the group of options and helps users understand the relationship between the options in the group.

**Required indicator:** Indicates that a selection is required.

**Caption:** May be used to provide additional context about the checkbox group when the label alone is not sufficient

**Options:** A list of options represented using [checkboxes](/components/Checkbox).

**Validation message:** A message explaining why the selection failed validation. See the [form pattern documentation](https://primer.style/ui-patterns/forms/overview#validation-message) for more information on form validation patterns.

## Accessibility

Once a user checks an option from a checkbox group, the result should not be saved or applied until the user has explicitly submitted their input using a "save" or "submit" button. See the [saving pattern guidelines](https://primer.style/ui-patterns/saving) for more information.

## Related components

- [Checkbox](/components/Checkbox): Used to render an individual checkbox control.
- [FormControl](/components/FormControl): Used to group individual controls with an associated label.
- [RadioGroup](/components/RadioGroup): Similar to `CheckboxGroup`, but used for organizing radio controls.
188 changes: 188 additions & 0 deletions apps/docs/content/components/CheckboxGroup/react.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
---
title: Checkbox group
description: Checkbox group renders a set of checkboxes.
source: https://github.com/primer/brand/blob/main/packages/react/src/forms/CheckboxGroup/CheckboxGroup.tsx
figma: 'https://www.figma.com/design/BJ95AjraesmRCWsKA013GS/Primer-Brand?node-id=10467-3273&t=GA5GtEqPtQ9yeRaN-4'
storybook: '/brand/storybook/?path=/story/components-forms-checkboxgroup--playground'
---

import ComponentLayout from '../../../src/layouts/component-layout'
export default ComponentLayout

import {Label} from '@primer/react'
import {PropTableValues} from '../../../src/components'

```js
import {CheckboxGroup} from '@primer/react-brand'
```

## Examples

### Default

`CheckboxGroup` creates a semantic container for multiple related checkboxes.

```jsx live
<CheckboxGroup>
<CheckboxGroup.Label>Choose your favorite features</CheckboxGroup.Label>
<FormControl>
<FormControl.Label>Actions notifications</FormControl.Label>
<Checkbox value="actions" />
</FormControl>
<FormControl>
<FormControl.Label>Packages</FormControl.Label>
<Checkbox value="packages" />
</FormControl>
<FormControl>
<FormControl.Label>Codespaces</FormControl.Label>
<Checkbox value="codespaces" />
</FormControl>
</CheckboxGroup>
```

### With caption

Use `CheckboxGroup.Caption` to provide additional context for the group.

```jsx live
<CheckboxGroup>
<CheckboxGroup.Label>Notification preferences</CheckboxGroup.Label>
<CheckboxGroup.Caption>
Select how you'd like to be notified
</CheckboxGroup.Caption>
<FormControl>
<FormControl.Label>Email notifications</FormControl.Label>
<Checkbox value="email" />
</FormControl>
<FormControl>
<FormControl.Label>Browser notifications</FormControl.Label>
<Checkbox value="browser" />
</FormControl>
<FormControl>
<FormControl.Label>Mobile notifications</FormControl.Label>
<Checkbox value="mobile" />
</FormControl>
</CheckboxGroup>
```
### With validation
`CheckboxGroup.Validation` can display success or error states with appropriate icons.
```jsx live
<Stack direction="vertical" gap="spacious">
<CheckboxGroup>
<CheckboxGroup.Label>Valid selection</CheckboxGroup.Label>
<FormControl>
<FormControl.Label>Option one</FormControl.Label>
<Checkbox value="one" />
</FormControl>
<FormControl>
<FormControl.Label>Option two</FormControl.Label>
<Checkbox value="two" />
</FormControl>
<CheckboxGroup.Validation variant="success">
Great choice!
</CheckboxGroup.Validation>
</CheckboxGroup>
<CheckboxGroup>
<CheckboxGroup.Label>Invalid selection</CheckboxGroup.Label>
<FormControl>
<FormControl.Label>Option one</FormControl.Label>
<Checkbox value="one" />
</FormControl>
<FormControl>
<FormControl.Label>Option two</FormControl.Label>
<Checkbox value="two" />
</FormControl>
<CheckboxGroup.Validation variant="error">
Please select at least one option
</CheckboxGroup.Validation>
</CheckboxGroup>
</Stack>
```
### Visually hidden label
When context is clear, labels can be visually hidden while remaining accessible to screen readers.
```jsx live
<CheckboxGroup>
<CheckboxGroup.Label visuallyHidden>Filter options</CheckboxGroup.Label>
<Stack direction="vertical" gap="regular">
<FormControl>
<FormControl.Label>Show all</FormControl.Label>
<Checkbox value="all" />
</FormControl>
<FormControl>
<FormControl.Label>Show active only</FormControl.Label>
<Checkbox value="active" />
</FormControl>
</Stack>
</CheckboxGroup>
```
### Inline
When space is limited, checkboxes can be arranged horizontally using the [Stack](/components/Stack) component.
```jsx live
<CheckboxGroup>
<CheckboxGroup.Label visuallyHidden>Filter options</CheckboxGroup.Label>
<CheckboxGroup.Caption>
Some inline checkboxes with a visually hidden label
</CheckboxGroup.Caption>
<Stack direction="horizontal" gap="normal" padding="none">
<FormControl>
<FormControl.Label>Choice one</FormControl.Label>
<Checkbox value="one" />
</FormControl>
<FormControl>
<FormControl.Label>Choice two</FormControl.Label>
<Checkbox value="two" />
</FormControl>
<FormControl>
<FormControl.Label>Choice three</FormControl.Label>
<Checkbox value="three" />
</FormControl>
</Stack>
</CheckboxGroup>
```
## Component props
### CheckboxGroup <Label>Required</Label>
| Name | Type | Default | Description |
| :--------- | :--------------------- | :-----: | :--------------------------------------------------------------- |
| `children` | `React.ReactElement[]` | | CheckboxGroup components and FormControl components |
| `id` | `string` | | Sets a custom id. If not provided, a unique id will be generated |
`CheckboxGroup` extends the HTML `fieldset` element and supports all `fieldset` props.
### CheckboxGroup.Label <Label>Required</Label>
| Name | Type | Default | Description |
| :--------------- | :-------- | :-----: | :-------------------------------------- |
| `children` | `string` | | Label text |
| `visuallyHidden` | `boolean` | `false` | Hide label visually but keep accessible |
`CheckboxGroup.Label` extends the HTML `legend` element and supports all `legend` props.
### CheckboxGroup.Caption
| Name | Type | Default | Description |
| :--------- | :------- | :-----: | :----------- |
| `children` | `string` | | Caption text |
`CheckboxGroup.Caption` extends the `span` element and supports all `span` props.
### CheckboxGroup.Validation
| Name | Type | Default | Description |
| :--------- | :--------------------------------------------------------------- | :-----: | :--------------------------------- |
| `children` | `string` | | Validation message |
| `variant` | <PropTableValues values={['error', 'success' ]} addLineBreaks /> | | Sets the validation state and icon |
`CheckboxGroup.Validation` extends the `span` element and supports all `span` props.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions apps/docs/content/components/RadioGroup/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: Radio group
description: Radio group is used to render a short list of mutually exclusive options.
---

import ComponentLayout from '../../../src/layouts/component-layout'

import anatomy from './images/anatomy.png'
export default ComponentLayout

## Usage

Use radio group to allow users to select a single option from a short list of related options.

### Orientation

A vertical orientation makes options easier to visually scan.

### Anatomy

<img src={anatomy} alt="Anatomy diagram" />

**Label:** A title that labels the group of options and helps users understand the relationship between the options in the group

**Required indicator:** Indicates that a selection is required

**Caption:** May be used to provide additional context about the radio group when the label alone is not sufficient

**Options:** A list of mutually exclusive options represented using [radio buttons](/components/Radio)

**Validation message:** A message explaining why the selection failed validation. See the [form pattern documentation](https://primer.style/ui-patterns/forms/overview#validation-message) for more information on form validation patterns.

### Best practices

- Put radio buttons in a logical order
- Only use a radio group for a short list of options: aim for 6 or less options. For longer sets of options, consider using a [select](/components/Select) or an [action menu](/components/ActionMenu)
- Radio buttons cannot be unchecked, so only use a radio group when a selection is required. Consider the following alternatives:
- use a radio group, but with one option that equates to "none of these options"
- use a [checkbox group](/components/CheckboxGroup) that fails validation if more than one option is selected
- If there is an option that's the most likely option to be checked, that option should be checked by default

## Accessibility

- Once a user checks an option from a radio group, the result should not be saved or applied until the user has explicitly submitted their input using a "save" or "submit" button. A radio group is a single tab stop, and the options can be navigated using the arrow keys: this means assistive technologies like a screen reader cannot "read" an option without selecting it. See the [saving pattern guidelines](https://primer.style/ui-patterns/saving) for more information.
- Radio groups must be labeled. The label may be visually hidden, but visible labels are preferred.

## Related components

- [FormControl](/components/FormControl): Used to group form controls with labels
- [Radio](/components/Radio): Individual radio button control
- [CheckboxGroup](/components/CheckboxGroup): For allowing multiple selections
Loading

0 comments on commit 1f9eb72

Please sign in to comment.