Archive

@sushindustries/ui

A filterable grid with categories, subcategories and tags, that leaves routing to you.

8 min read
View as MarkdownEdit on GitHub

Props

PropTypeDefaultDoes
categoriesreadonly ArchiveCategory[]-The chips, in the order given. One with no items still gets a chip, counted zero.
itemsreadonly ArchiveItem[]-Everything, before filtering. Category counts come from here, so they hold steady as filters narrow.
active?string"all"Current category filter id, or "all".
activeTag?string-Current tag filter, if any. Narrows within the active category.
hrefForCategory(id: string) => string-Builds the href for a filter chip. The route owns routing, not this.
hrefForTag?(tag: string | undefined) => string-Builds the href for a tag chip. Pass undefined to clear the tag.
page?number-1-based page within the filtered result. Absent means "no pagination".
pageSize?number24Items per page when page is set.
hrefForPage?(page: number) => string-Builds the href for a page number. Required when page is set.
renderPageLink?PaginationProps["renderLink"]-Rendered around every page number, forwarded to PaginationPaginationPages as links with first and last always reachable. The window everyone already knows, and nothing that breaks middle-click.@sushindustries/ui · docs untouched. Without it page links are plain anchors, which a client-side router does not intercept - every page click becomes a full document load.
renderLink(props: { kind: "category" | "tag" | "item"; id: string; href: string; className: string; "data-tone"?: string; children: ReactNode; }) => ReactNode-Renders the link wrapper, so the host can use its router's Link. kind and id are passed alongside the plain href because a typed router needs the route pattern and its params, not a path that has already been resolved - handing Link a resolved /components/reveal gets an anchor with the right href whose click is intercepted and then silently fails to match /components/$slug. The href stays for hosts that just want an anchor.
emptyLabel?string"Nothing here yet."Replaces the grid when the filters match nothing. The chips stay, so the reader can undo.

Notes

page, pageSize and hrefForPage are one feature, not three - pagination is on only when page is set, and hrefForPage is required at that point because there is no page number without a link to reach it. Leave page unset for an unpaginated grid; pageSize and hrefForPage are then ignored.

hrefForTag works the same way for the tag row: absent, no tag chips render at all, regardless of whether items carry tags. A grid that cannot link to a tag has nothing useful to say about one.

renderLink is called for three different kinds - category, tag, itemItemOne row of a list: tile, title, description, meta - the nav panel's anatomy, extracted for reuse.@sushindustries/ui · layout - with the same shape each time. A host that only handles one kind correctly will find the others silently rendering plain anchors or nothing, since renderLink is the only thing standing between a chip and a route.

UsesPaginationPaginationPages as links with first and last always reachable. The window everyone already knows, and nothing that breaks middle-click.@sushindustries/ui · docsIconIconThe glyph set, generated from a Markdown table where every drawing carries its reason. One component, typed names, no icon font.@sushindustries/ui · content
Mentioned inBadgePagination