Kaufmann Commerce UI / Storefront family
Top Bars
One headless hook, two interchangeable bars, two shared sub-views — the same pluggable shape as the cart family.
A family, not two components
Both bars are surfaces over useStoreChrome, which owns the cart count, the cart's disclosure state and the search query — everything that arrives over the event seam. Each composes the same BrandBlock and CartTrigger sub-views. What differs is only how much a page needs to say.
Because they answer the same seam, swapping one for the other is a one-line page change: CartPopover anchors to .k-cart-trigger and finds whichever bar is present, with nothing to reconfigure.
| Surface | Carries | Use for |
|---|---|---|
StoreHeader | Announcement, mobile menu, navigation, search, cart | The storefront itself |
StoreBar | Brand, one optional link, search, cart | Focused pages — checkout-like flows, a single Offer, an account shell |
AdminBar | — | Planned with the admin shell (roadmap S8). Not built; nothing here claims it is. |
StoreHeader
The full storefront bar: announcement, navigation that collapses into a touch-friendly menu below 760px, search and cart.
Store content begins here.
StoreBar
The minimal bar: brand, one optional link back, search and cart. No navigation, because a focused page should not invite the user back out of the room they came to stand in.
A focused page — one Offer, or a checkout-like flow.
---
import { StoreBar, StoreHeader } from "@kaufmann/ui";
---
<!-- The full storefront bar -->
<StoreHeader client:load brand={brand} navigation={navigation} announcement="…" />
<!-- The minimal one, for a focused page. Same seam, one-line swap. -->
<StoreBar client:load brand={brand} action={{ id: "back", label: "Back to the shop", href: "/storefront/" }} />What the bars share
The hook renders nothing and holds only what every bar needs. StoreHeader's mobile menu stays in StoreHeader, because StoreBar has no navigation to disclose — a headless hook that grew a menu would be serving one surface at the other's expense.
// Both bars are surfaces over one headless hook.
import { useStoreChrome, BrandBlock, CartTrigger } from "@kaufmann/ui";
const { cartCount, cartOpen, query, setQuery, openCart } = useStoreChrome();
// …and compose the same two sub-views:
<BrandBlock brand={brand} />
<CartTrigger label="Cart" count={cartCount} expanded={cartOpen} onOpen={openCart} />