Filterable collection
Task#
Use this pattern when readers need to scan a bounded collection and narrow it by values already present in the data. It is used for publications, the talks archive, and recommendations. It is not a site search: filtering acts on an already-rendered, known collection rather than an index of every page.
Composition#
The page starts with the standard Page header. A Filter row is optional: use it only when it meaningfully narrows the collection. Results use a Data table when readers compare columns, or a semantic list when entries are narrative. Pagination is added only when the chosen result model needs it.
Content and data#
Keep the dataset as the authority. Filter keys must be stable values in that data, while visible labels may be localized or derived by the layout. Each dataset needs a deliberate result shape: publications are comparable rows, talks are sortable archival records, and recommendations are individual quotations. Do not force all three into the same card or table markup.
Responsive behaviour#
Filter controls wrap or scroll horizontally according to their documented filter-row variant. Tables keep their minimum readable width inside the shared scroll region; narrative results remain a single vertical list. Filtering and client-side paging preserve the page’s reading flow at every width rather than replacing results with a separate mobile interface.
Implementation#
The page layout derives filter items and result rows from one data file, then passes the controls to data-page/filter-row.html. Publications use data-table-* attributes with sortable rows and data-page/table-pagination.html; the talks archive has an older, equivalent data-talks-* controller; recommendations filter a semantic list. The shared CSS supplies the visual states, and assets/js/site.js changes only the currently visible results.
Pattern manifest
- Kind
- Pattern
- Category
- Collection
- Status
- Implemented
- Content and data
- one structured data source with stable filter values and visible labelsa result presentation chosen by the data: table for comparison, list for narrative entriesan explicit empty state whenever a filter can hide every result
- Accessibility
- native buttons for filters with a named filter navigation landmarkan announced result count or empty state after a filter changes visibilitynative table or list semantics retained while results are filtered, sorted, or paged
- Implementation
- Partial:
layouts/partials/entry-title-block.htmllayouts/partials/data-page/filter-row.htmllayouts/partials/data-page/table-wrap.htmllayouts/partials/data-page/table-pagination.htmlLayout:layouts/publications/publications.htmllayouts/talks/archive.htmllayouts/about/recommendations.htmlData:data/publications.ymldata/talks.ymldata/recommendations.ymlCSS:assets/css/site.cssJavaScript:assets/js/site.js - Related patterns
- Reference index
Accessibility#
- The filter row is a named navigation landmark containing native buttons. An active state is exposed with the component’s documented ARIA behaviour; colour is never the only signal.
- A filter update announces either the visible result count or the empty state through a polite live region. Do not replace the whole results region without a status message.
- Tables keep their headers, scopes, and scroll-region name. List implementations retain
<ol>or<ul>and<li>semantics instead of simulating a list with generic containers. - Sorting controls are real buttons with an exposed sort direction. Pagination uses native links or buttons and announces the currently visible range.
- Use this pattern only for a known, bounded dataset. For global content discovery, use Search; for jumps to repeated sections already visible on a page, use the Reference index.