KQ-1335 · PRODUCT/GRID

Product Grid

A filterable product grid whose shelf moves instead of snapping: when a facet chip or the sort changes, cards that stay travel to their new cells on glide, leaving cards shrink and fade on the exit ease and arriving ones scale in — together, as a wave timed by each card's new position, or as a cross-fade — while every chip's count and the result total roll on snap. A card's quick view grows out of the card itself: the dialog's rounded clip opens from the card's box while the product art flies to its place on the same glide progress, or it rises as a sheet or slides in from the side. Facets are roving-focus toggle groups, sort is a listbox, and the quick view is a modal dialog that traps focus, closes on Escape and gives focus back to its card.

KQ-1335 · PRODUCT/GRID

Kitchen

16 products

16 of 16 · everything · featured · bag 0

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/product-grid

Props

reflow
"glide" | "wave" | "fade"
default "glide"
How the shelf rearranges: every card glides together, a wave delayed by each card's new position (kept under 600ms), or a cross-fade with no travel.
quickview
"morph" | "sheet" | "side"
default "morph"
How the quick view arrives: grown out of the card, risen as a bottom sheet, or slid in as a side panel (a sheet below 40rem).
density
"compact" | "regular" | "roomy"
default "regular"
Columns and how much each card says: compact drops the rating for more columns, roomy adds the description and lays phone cards out sideways.
products
ProductGridItem[]
default defaultProducts
The shelf: id, name, category, price, compareAt, colour ids, rating, reviews, badge, stock, when it arrived, description and the drawn shape that stands in for its photograph.
colors
ProductGridColor[]
default defaultProductColors
The glazes products come in: id, name and a pigment tint (any CSS colour, ideally at a fixed lightness).
priceBands
ProductGridPriceBand[]
default defaultPriceBands
The price chips: id, label, inclusive min and exclusive max (omit it for no ceiling).
filters / defaultFilters
ProductGridFilters
default —
Categories, colour ids, a price band id and in-stock-only. Controlled or uncontrolled; defaults to nothing set.
onFiltersChange
(filters: ProductGridFilters) => void
default —
Fires from the chip, or Clear filters, that changed the filters, with the whole new set.
sort / defaultSort
"featured" | "price-asc" | "price-desc" | "newest" | "rating"
default "featured"
The order of the shelf. Controlled or uncontrolled.
onSortChange
(sort: ProductGridSort) => void
default —
Fires from the sort menu's choice.
open / defaultOpen
string | null
default null
The product whose quick view is open. Controlled or uncontrolled.
onOpenChange
(id: string | null) => void
default —
Fires as a quick view is opened from a card (its id) or closed by Escape, Close or the scrim (null).
onAddToCart
(id: string, options: { color: string; qty: number }) => void
default —
Quick add on a card (the default colour, one) or Add to bag in the quick view (the chosen colour and quantity).
onOpen
(id: string) => void
default —
View details in the quick view. Without it there is no link.
pageSize
number
default 12
Cards shown before Show more. A new filter or sort starts from the first page.
format
(amount: number) => string
default —
Money. Defaults to Intl currency formatting in locale and currency.
locale
string
default "en-US"
Locale for the default money format.
currency
string
default "USD"
Currency for the default money format.
status
"ready" | "loading" | "error"
default "ready"
Whether the shelf has arrived: skeleton cards while loading, a message and Try again on error.
onRetry
() => void
default —
Try again was pressed after the shelf failed to load.
title
string
default "Kitchen"
The shelf's heading.
label
string
default —
The region's accessible name. Defaults to the title.
sound
boolean
default false
A click for every chip, sort choice, glaze, stepper and add; a swish as a quick view opens (higher) and closes (lower).
disabled
boolean
default false
Browse only: nothing can be filtered, sorted, opened or added.
className
string
default —
Classes for the root; its scroller is at most 560px tall and the quick view covers the root's visible box.