KQ-1350 · STOREFRONT

Storefront

A complete store home built around cart-drawer, product-grid and product-detail: the whole store is the bag's page, so the bag slides over it on glide and pulls shut; a hero, a category rail and product rails that scroll-snap and glide a page at a time; a category, a card or See all pushes product-grid's shelf in from the right on glide, and the hero pushes product-detail's page. Quick add throws a dot in the product's glaze to the bag on a true arc — x steady, y thrown up and falling — and when it lands the badge bumps on recoil, its count rolls and the button draws a check on flick. Rails take Left, Right, Home and End, pushed screens go back with Back, Alt+Left, Escape or a 1:1 swipe from their left edge that commits by projection.

KQ-1350 · STOREFRONT

Fernworks Supply

New glazes

The Field Mug, in four colours

Thrown by hand, speckled with iron, and no two alike.

Shop by room

New this season

Thrown this autumn

  • Drift dripper, glass

    €29.00

    4.1(22)

  • Hollow tumbler, set of 2

    €28.00

    4.6(88)

  • Stone mug, pair

    €36.00

    4.7(76)

  • Juniper jar, 1 l

    €19.00

    4.2(64)

  • Pebble serving bowl

    €72.00

    4.6(33)

  • Cinder cup and saucer

    €26.00

    4.3(39)

  • Mesa hand grinder

    €124.00

    4.6(58)

  • Coldbrook bowl

    €24.00

    4.8(150)

Bestsellers

What kitchens keep

  • Fern mug

    €22.00

    4.9(402)

  • Ridge pour-over

    €38.00

    4.7(212)

  • Coldbrook bowl

    €24.00

    4.8(150)

  • Gauge brew scale

    €64.00

    4.4(133)

  • Brook canister

    €34.00

    4.7(120)

  • Basin kettle, 1 l

    €89.00€104.00

    4.8(96)

  • Hollow tumbler, set of 2

    €28.00

    4.6(88)

  • Stone mug, pair

    €36.00

    4.7(76)

home · bag 0 items

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/storefront

Props

rails
number
default 2
How many collections show as rails on the home, 1 to 3.
hero
"banner" | "split" | "off"
default "banner"
The hero: a banner with the copy over the still life, a split with the copy beside it (a banner on a phone), or none, so the category rail leads.
density
"compact" | "regular" | "roomy"
default "regular"
Rail card widths (132, 160 or 196px; narrower on a phone) and how much each says — price only, a rating, or the rating and its glazes; also the shelf's density.
products
ProductGridItem[]
default defaultProducts
The catalogue, in product-grid's shape: categories come from it and every rail, tile and shelf reads it.
colors
ProductGridColor[]
default defaultProductColors
The glazes products come in, as pigments that read in both themes.
collections
StoreCollection[]
default defaultStoreCollections
The rails in order: a title, a line, product ids, and how See all sorts and filters the shelf.
featured
ProductInfo
default defaultProduct
The product the hero opens as a full product page; its glazes paint the hero's still life.
heroCopy
StoreHero
default defaultStoreHero
The hero's eyebrow, title, line and button words.
items / defaultItems
CartLine[]
default []
The lines in the bag, in cart-drawer's shape.
onItemsChange
(items: CartLine[]) => void
default —
Fires from the quick add, shelf, product page or bag that changed the lines, with all of them.
cartOpen / defaultCartOpen
boolean
default false
Whether the bag is open over the store.
onCartOpenChange
(open: boolean) => void
default —
Fires from the Bag button and from the bag's close, Escape, scrim or pull.
screen / defaultScreen
"home" | "product" | `category:${string}` | `collection:${string}`
default "home"
The screen on show: home, the featured product, or the shelf for a category or a collection.
onScreenChange
(screen: StoreScreen) => void
default —
Fires from a tile, a card, See all, the hero, Back, Alt+Left, Escape or the back-swipe.
onAdd
(line: CartLine) => void
default —
Something went in the bag from the store, with the line as it now stands.
onCheckout
(items: CartLine[], total: number) => void | Promise<void>
default —
Checkout was pressed in the bag; a promise holds its button pending.
now
Date | number
default defaultStoreNow
The moment the product page's delivery estimate counts from. Never read from the clock during render.
format
(amount: number) => string
default euros, en-IE
Money everywhere: rails, shelf, product page and bag.
storeName
string
default "Fernworks Supply"
The store's name in the top bar.
status
"ready" | "loading" | "error"
default "ready"
Loading draws placeholder cards; error offers Try again. Passed on to the shelf.
onRetry
() => void
default —
Try again was pressed in the error state.
label
string
default "Store"
The screen's accessible name.
sound
boolean
default false
Play a pop as a quick add lands and a category opens, and a swish for pushes, pops and the bag; the composed pieces play their own. Off unless asked for.
disabled
boolean
default false
Browse only: nothing can be added or bought.
className
string
default —
Classes for the root. It is 560px tall by default; pass a height class to change it.