Skip to content
docs-sitekit

Menu

Type to search the docs.

↑ ↓ move · Enter open · Esc close

CatalogFilter

A text field and tag buttons that narrow the cards of an index page, with the state in the address.

Preview

src/examples/catalog-filter/example.astro
---
import { collectTags, filterText, tagKey } from "@/domain/filter";
import CatalogFilter from "@/presentation/components/site/catalog-filter.astro";
import { CardGrid, ItemCard } from "@/presentation/components/site/item-card";

const cards = [
  { title: "getting-started", description: "Create a site.", tags: ["Setup", "Guide"] },
  { title: "deploying", description: "Publish to GitHub Pages.", tags: ["Guide"] },
  { title: "design-tokens", description: "Colors, radius and fonts.", tags: ["Design"] },
];
---

<CatalogFilter tags={collectTags(cards)} total={cards.length} />
<CardGrid>
  {
    cards.map((card) => (
      <ItemCard
        href="#"
        title={card.title}
        description={card.description}
        data-filter-item
        data-filter-tags={JSON.stringify(card.tags.map(tagKey))}
        data-filter-text={filterText(card)}
      />
    ))
  }
</CardGrid>

Add to your site

npx docs-sitekit add catalog-filter

It writes these files, and keeps a file you changed:

  • src/presentation/components/site/catalog-filter.astro
  • src/presentation/filter/catalog-filter.ts
  • src/domain/filter/index.ts
  • src/domain/filter/catalog-filter.ts
  • src/domain/filter/tags.ts

It requires nothing else from the registry.

Props

Built from the TypeScript types and the TSDoc comments of the component, so they cannot drift from the code.

Props of catalog-filter
KeyTypeDefaultAllowed valuesDescription
tagsTagOption[]required-One button per tag, from collectTags.
totalnumberrequired-How many cards the page has, for the first status line.

About

A bar above the cards of an index page, to narrow the page you are already on. Search finds a page across the site, the filter narrows this one. It is built from the tags in the frontmatter of the pages that the grid shows:

---
tags: [Setup, Guide]
---

The index layout, collection-index.astro, uses it and is yours to edit. In the preview above the cards carry the data-filter-item, data-filter-tags and data-filter-text attributes that the script reads. A page shows one bar, because the script takes the first one. The preview changes the address of this page, as the filter does on an index.

  • It appears only when a page of the index has a tag. An index without tags looks and works as before.
  • The text field keeps the cards that contain every word, in the title, the description or the tags, whatever the case and the accents.
  • The tag buttons are toggle buttons. With several tags selected a card needs all of them.
  • The state is in the address, ?tag=setup&tag=guide&q=card, so a filtered view can be shared, and loading that address shows it. A tag button adds a history entry, so the back button undoes it. Typing replaces the current entry, so one search does not fill the history.
  • The matching is a set of pure functions in src/domain/filter/, the same ones that build the page and run in the browser.
  • sitekit add catalog-filter restores its component, its script and the matching rules.

Accessibility

  • Without JavaScript every card is shown and the bar is not. The bar is hidden in the HTML, and a one line script right after it shows it, so it is in the first paint and nothing moves.
  • The tag buttons have aria-pressed. The text field has a visible label.
  • The status line is a polite live region that says “N of M shown.” A state with no match says “Nothing matches this filter.” and shows a “Clear filter” button.
  • Every control is at least 44 px, and the focus ring is the one of the rest of the site.

Source

Edit this page

Last updated