Skip to the content

Kongens Nytorv

Metro M1, M2 and M3.

Variants and states

RestHoverPressedFocusDisabled
Default
Default
  • Rest
  • Hover
  • Pressed
  • Focus
  • Disabled

With icons

An icon before the label, in reading order, such as the disruption icon of the kind the chip filters. Hidden from screen readers: the label names the chip.

Props

NameTypeDefaultDescription
selectedboolean—Whether the filter is on, when the caller controls it. Announced as pressed.
defaultSelectedbooleanfalseWhether the filter is on at first, when FilterChip keeps the state itself.
onChange(event: Event, value: boolean, details: Toggle.ChangeEventDetails) => void—Called when a click, Enter or Space turns the filter on or off, with the new state as value; details.reason is 'none', and details.cancel() keeps the state as it was. event is details.event.
disabledbooleanfalseWhether the chip ignores the pointer and the keys. A disabled chip leaves the tab order and keeps its state.
startIconReactNode—An icon before the label, in reading order, such as the disruption icon of the kind the chip filters. Hidden from screen readers: the label names the chip.
countnumber—How many the filter matches, shown after the label as a Count, such as the "3" of "Delays 3". Heard after the label. Shown for 0 too; left out when undefined or not a finite number.
childrenReactNode—The label: the name of what the filter shows, in sentence case, such as "Delays". It stays the same whether the filter is on or off.
classNamestring—Reaches the root. className is merged after pn-FilterChip.
styleCSSProperties—Reaches the root. className is merged after pn-FilterChip.
refRef<HTMLButtonElement>—Reaches the root. className is merged after pn-FilterChip.
selectedboolean, default —
Whether the filter is on, when the caller controls it. Announced as pressed.
defaultSelectedboolean, default false
Whether the filter is on at first, when FilterChip keeps the state itself.
onChange(event: Event, value: boolean, details: Toggle.ChangeEventDetails) => void, default —
Called when a click, Enter or Space turns the filter on or off, with the new state as value; details.reason is 'none', and details.cancel() keeps the state as it was. event is details.event.
disabledboolean, default false
Whether the chip ignores the pointer and the keys. A disabled chip leaves the tab order and keeps its state.
startIconReactNode, default —
An icon before the label, in reading order, such as the disruption icon of the kind the chip filters. Hidden from screen readers: the label names the chip.
countnumber, default —
How many the filter matches, shown after the label as a Count, such as the "3" of "Delays 3". Heard after the label. Shown for 0 too; left out when undefined or not a finite number.
childrenReactNode, default —
The label: the name of what the filter shows, in sentence case, such as "Delays". It stays the same whether the filter is on or off.
classNamestring, default —
Reaches the root. className is merged after pn-FilterChip.
styleCSSProperties, default —
Reaches the root. className is merged after pn-FilterChip.
refRef<HTMLButtonElement>, default —
Reaches the root. className is merged after pn-FilterChip.

Use it

import { FilterChip } from '@mylder/perron'

Ask your agent

get_reference({ library: "base-ui", component: "Toggle" })

Keyboard and ARIA

From the Base UI reference for Toggle and the installed Toggle and useButton. "From" says who does it.

KeyDoesFrom
Tab, Shift+TabMoves focus to the chip and away; a disabled chip is skippedThe browser, and Base UI's native disabled
EnterTurns the filter on or off, through the button's click, and calls onChange with the new stateThe browser; Base UI for a non-button render
SpaceTurns the filter on or off on release, through the button's click, and calls onChange with the new stateThe browser; Base UI for a non-button render

FilterChip adds no keys of its own. A row of chips is a tab stop each, not one composite stop: they are separate filters, not one choice.

ElementRoleAccessible name fromStates announced
rootbutton, native, a toggle button by its aria-pressed; role="button" from Base UI when render gives a non-buttonIts text content: the label's children, then the count, as "Delays 3"; the caller's aria-label or aria-labelledby winaria-pressed, true or false; the native disabled
startIconnone: aria-hidden="true"nonenone
countnone: text inside the chip, Count's generic <span>Part of the chip's namenone

What axe won't catch, from the contract, each with how this component meets it:

  • Everything the eye is told, the ear is told, for every shape each prop accepts: the selected fill is aria-pressed, heard as "pressed" or "not pressed" after the name; the count is text in the name, heard after the label; the icon is aria-hidden, since it sits beside the word it shows (Icons); a disabled chip's tertiary colour is the native disabled.
  • Every landmark and named region has an accessible name: none here; a chip is neither. The group of chips that holds them is the pattern's, which names it.
  • Every default label can be overridden: none here; FilterChip owns no strings.
  • Every shape the type accepts renders, in every variant: children and startIcon render a string, an element and a list alike, on and off and disabled; count renders 0 and larger numbers alike, and nothing for undefined, NaN or Infinity.
  • A hidden copy kept for animation is aria-hidden, and a collapsed region is inert: none here; FilterChip keeps no hidden copy and collapses nothing.
  • Native semantics first: a native <button> with aria-pressed from Base UI's Toggle; with render and nativeButton={false}, Base UI's role="button".
  • Focus moves in reading order and returns on close: each chip is one tab stop in document order, focus stays on the chip it toggles, and it opens nothing to return from.
  • Every target is at least size.target-min square: the smallest target is a chip with a one-word label and no icon or count, size.control (34 px) tall and the word plus space.300 on each side wide.
  • Loops stop when the system asks for less motion: none here; FilterChip has no loop and no transition.

Owned strings

No owned strings: every word comes from the caller, as children, the count, or an aria-label. FilterChip renders its Count only for a finite number (CR-9), so Count's own "Unknown" never shows inside a chip.

Do and don't

For a caller using the component, with the reason. Each row is a rule: a must row's Don't is never right, a should row's needs a reason, and Checked by says what catches the Don't in a caller's code.

RuleLevelDoDon'tChecked by
DD-1mustUse FilterChip for a filter people turn on and off on its own, such as showing delays on the mapUse it to pick one of several views or modes: that is one choice, a SegmentedControl's, and chips would let two be on at oncereview
DD-2mustKeep the label the filter's name, the same on and off, in sentence case: "Delays", "Planned works"Change the label to say the state ("Delays on"): aria-pressed and the fill already say it, and a changing label moves the rowreview
DD-3mustGive the count as count, so every chip's count has Count's shape and is heard after the labelBuild a count into children, or pass a guess when the number is unknown: leave count out, and the chip shows nonereview
DD-4shouldUse the content design words for kinds of disruption and data states, so the chips agree with the rest of MylderCoin a filter name of your own for a kind the table namesreview
DD-5mustLay a row of chips out with flex-wrap: wrap and a gap, and name the group in the pattern that holds itPut chips in a Toolbar or make them one tab stop: each is a filter of its own, reached with Tabreview
DD-6mustUse a Tag to mark a property that can't be pressedUse a FilterChip as a label: a chip invites a press, and one that does nothing misleadsreview
DD-7mustDisable a chip only while its filter can't apply, and say why nearbyDisable a chip to show a count of 0: show the 0, since a disabled chip leaves the tab order and can't explain itselfreview
DD-8mustKeep onChange for the filter's state, and cancel it with details.cancel() when the change must not happenSet aria-pressed yourself or toggle a class: Base UI keeps the state and the attribute in stepreview