shadcn.io is not affiliated with official shadcn/ui
Collection Filter Storefront Block for Radix UI
A faceted parka collection page: a rail with a type toggle, a highest-price slider, grey swatches and size checkboxes, each option with a count that follows the other filters, removable chips, a sort menu and a drawn grid that pages twelve at a time.
Installation
Overview
Let shoppers narrow a collection without losing their place, with this faceted collection page for React with Radix UI. A header names the page, says what Hawthorn & Hare sells and holds a sort Select (Featured, Price, Name). Inside a hairline frame with a plus mark on each corner, a rail at the start groups the filters: a Toggle Group for the type of parka (All, Down, Waxed, Shell), a Slider for the highest price, five greys as swatches and four sizes as Checkboxes. Every option shows a count, worked out as how many parkas that option would give with the other filters kept, so choosing a size changes the counts of the types and colours, and a zero stays on show as 0. Above a grid of drawn parkas in hairline cells, each active filter is a removable chip and Clear all returns focus to the first filter. Twelve parkas fit a page, with Previous and Next under them and a status line that says how many of the fourteen are showing. An empty result is drawn inside the same grid, so nothing jumps. On a phone the rail folds behind a Filters button that counts what is on, and the grid goes two up. It's built from Toggle Group, Slider, Checkbox, Select, Empty, Button and Guides, with a CSS entrance only. For a shop's collection pages and category listings.
FAQ
How do I fill it with my own products?
Edit PARKAS. Each has an id, a name, the price in cents, a type, a grey (the id of one of the greys in GREYS), whether it is the long cut and the sizes still in stock. The swatches, the drawing and the counts are all worked out from those, so a new grey or size only needs adding to its list. The drawings are paths made from the type and the grey; swap the Art component for an img when you have photographs.
How are the counts worked out?
Filters join with AND between groups and OR inside one: a parka passes if it has the chosen type, costs no more than the highest price, has one of the chosen greys (or none are chosen) and has one of the chosen sizes in stock. The count beside an option runs the same test with that group set to the option alone and every other group as it is. That is why the counts sum to more than the total inside a group that allows several, and why an option nobody can pick right now shows 0 instead of vanishing.
How do the chips and Clear all work?
Each chip removes one filter, a type, the price limit, a grey or a size, and moves focus to the next chip, or to the first filter when it was the last. Clear all resets every filter and returns focus to the first filter on a desktop, or to the Filters button on a phone while the rail is folded. The paging goes back to page one whenever a filter or the sort changes.
What stays local, and how do I wire it to a real catalog?
Everything happens in the page: the list is a typed array and the filters run on it. To make it real, send the filter state to your API (or put it in the URL) and fill the grid from the response, keeping the counts from the same call. Keep the twelve cells per page, and the cells that are left empty on a short page, so the layout does not jump. Nothing here is for sale; each product link goes to #.
How does it look on a phone?
The rail turns into a Filters button with the number of active filters, which opens the groups in place under it; the chips stay above the grid and the grid goes two up. While the rail is closed its controls are hidden from the keyboard as well, so Tab does not land on something you cannot see.
Is it accessible?
Type, colour and size are fieldsets with a legend, every swatch is a checkbox named for its grey ("Colour: Graphite") that also gets a visible ring when ticked, the price slider has a name and speaks its value ("Up to $400"), and the status line is a polite live region present from the start that says how many parkas are showing and which page. Colour is never the only signal: a ticked swatch has a ring, a pressed type is filled, and each parka's grey is named in its cell.