Skip to main content

Design system components

BlogCategoryFilter

Single-select tag filter for the blog archive: a labelled group of toggle chips with an implicit All, three visual treatments, optional per-tag counts and an optional collapsed mode.

Status: stable. Group: navigation. Markdown version: /design-system/components/blog-category-filter.md

When to use

Category filter control for the blog archive. Blog-scoped variant; for generic list pages use CategoryFilter.

When not to use

  • Do not use this for generic list pages; that is CategoryFilter.

Look-alikes

  • CategoryFilter: Do not use this for generic list pages; that is CategoryFilter.

Props

BlogCategoryFilter props
PropTypeDefaultDescriptionRequired
tagsstring[]noneArray of unique tags.Yes
selectedTagstring | nullnoneCurrently selected tag (null means "All")Yes
onTagChange(tag: string | null) => voidnoneCallback when tag selection changes.Yes
showCountsbooleanfalseShow post counts per tag.No
tagCountsRecord<string, number>{}Tag counts object.No
variant"pills" | "underline" | "minimal"pillsStyle variant.No
size"sm" | "md" | "lg"mdSize variant.No
collapsiblebooleanfalseCollapse to the selected chip and a disclosure button; expanding shows every chip and picking one collapses back to it.No
classNamestringnoneCustom className.No

Variants

  • Available variants: pills, underline, minimal (default pills).
  • Available sizes: sm, md, lg (default md).

Invalid combinations

The contract records no invalid combinations.

Keyboard

BlogCategoryFilter keyboard behaviour
KeyBehaviour
TabMoves to and through the filter buttons.
Enter/SpaceOr click activates the focused filter.
GeneralWith collapsible, a disclosure button is the first child of the group; Enter/Space or click shows or hides the chips.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

BlogCategoryFilter rules
LevelRuleHow it is checked
MUSTARIA: Role=group labelled via blogFilterByTag; each filter is a toggle button with aria-pressed.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Single-select: exactly one filter has aria-pressed=true at a time (visual + aria-pressed convey the active filter)Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: With collapsible, the disclosure button carries aria-expanded (no aria-controls: it sits inside the group) and an aria-label from blogFilterAllTopics; its caret icon is aria-hidden.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTEvery documented keyboard interaction works as specified.Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-04.
MUST NOTMaintainers: Do not invent parallel primitives inside this folder.Release review; not machine-checked.

Install and import

  • In-repo only. BlogCategoryFilter is not exported from @digitaltableteur/react, so there is no public import path.