Files

126 lines
6.3 KiB
Plaintext

---
title: Segmented control
summary: A segmented control is a row of two or more mutually exclusive options styled as one bar, an alternative to radios or tabs.
description: A set of mutually exclusive options displayed as connected buttons.
source: core/scss/ui/_segmented.scss
sass-vars: segmented-nav
classnames:
component:
- class: nav-segmented
desc: Applied together with nav, turns it into a segmented control
direction:
- class: nav-segmented-vertical
desc: Stacks the segments in a column
size:
- class: nav-sm
desc: Small size
- class: nav-lg
desc: Large size
---
import Example from '@components/Example.astro';
import Icon from '@ui/Icon.astro';
A segmented control is a `nav` element with the `nav-segmented` class, holding `button` or `a` elements with the `nav-link` class.
<Example centered>
<nav class="nav nav-segmented" role="tablist">
<button class="nav-link active" role="tab" data-bs-toggle="tab" aria-selected="true" aria-current="page">First</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Second</button>
<button class="nav-link" disabled role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Disabled</button>
</nav>
</Example>
## Full width
Add `w-100` to the `nav` to stretch the control to the width of its container.
```html
<nav class="nav nav-segmented w-100" role="tablist">...</nav>
```
<Example>
<nav class="nav nav-segmented w-100" role="tablist">
<button class="nav-link active" role="tab" data-bs-toggle="tab" aria-selected="true" aria-current="page">Daily</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Weekly</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Monthly</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Quarterly</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Yearly</button>
</nav>
</Example>
## With emojis
A segment can hold an emoji.
<Example centered>
<nav class="nav nav-segmented" role="tablist">
<button class="nav-link active" role="tab" data-bs-toggle="tab" aria-selected="true" aria-current="page">👦</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">👦🏿</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">👦🏾</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">👦🏽</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">👦🏼</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">👦🏻</button>
</nav>
</Example>
## With icons
A segment can hold an [icon](/ui/components/icon).
<Example centered>
<nav class="nav nav-segmented" role="tablist">
<button class="nav-link active" role="tab" data-bs-toggle="tab" aria-selected="true" aria-current="page"><Icon name="list" /> List</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1"><Icon name="layout" /> Kanban</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1"><Icon name="calendar" /> Calendar</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1"><Icon name="files" /> Files</button>
</nav>
</Example>
## Vertical direction
To create a vertical segmented control, add the `nav-segmented-vertical` class to the `nav` element.
```html
<nav class="nav nav-segmented-vertical" role="tablist">...</nav>
```
<Example centered>
<nav class="nav nav-segmented nav-segmented-vertical" role="tablist">
<button class="nav-link active" role="tab" data-bs-toggle="tab" aria-selected="true" aria-current="page"><Icon name="list" /> List</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1"><Icon name="layout" /> Kanban</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1"><Icon name="calendar" /> Calendar</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1"><Icon name="files" /> Files</button>
</nav>
</Example>
## Sizes
Add `nav-sm` or `nav-lg` to the `nav` to change the size.
```html
<nav class="nav nav-segmented nav-sm" role="tablist">...</nav>
```
<Example centered vertical>
<nav class="nav nav-segmented nav-sm" role="tablist">
<button class="nav-link active" role="tab" data-bs-toggle="tab" aria-selected="true" aria-current="page">List</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Kanban</button>
<button class="nav-link disabled" role="tab" data-bs-toggle="tab" aria-selected="false" aria-disabled="true" tabindex="-1">Calendar</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Files</button>
</nav>
<nav class="nav nav-segmented nav-lg" role="tablist">
<button class="nav-link active" role="tab" data-bs-toggle="tab" aria-selected="true" aria-current="page">List</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Kanban</button>
<button class="nav-link disabled" role="tab" data-bs-toggle="tab" aria-selected="false" aria-disabled="true" tabindex="-1">Calendar</button>
<button class="nav-link" role="tab" data-bs-toggle="tab" aria-selected="false" tabindex="-1">Files</button>
</nav>
</Example>
## Accessibility
- A segmented control that switches panels is a tab list: put `role="tablist"` on the `nav`, `role="tab"` on each button, and link them to the panels with `aria-controls`.
- A segmented control that picks a value is a radio group instead. Use `input type="radio"` with a shared name inside a `fieldset` with a `legend`, so the arrow keys work and the group has a name.
- Do not mix the two. Buttons with `aria-pressed` in a row read as separate toggles, which is not what a segmented control looks like.
- Every segment needs a text label. An emoji or an icon alone leaves the option unnamed - add an `aria-label` if the design has no room for words.