Product and order
Screens for the shopper: a product detail page and an order detail with delivery progress.
Installation & usage
npx @youj/cli add commerce-product-detailAlso installs accordion, async-button, badge, breadcrumb, card, carousel, commerce-product-card, commerce-product-render, field, icon-heart, icon-rotate-ccw, icon-ruler, icon-shopping-cart, icon-star, icon-store, icon-truck, number-input, toggle, typography, youj-presets, youj-ui-core.
The CLI copies the block to blocks/commerce/product-detail.tsx with every component it uses, so it’s yours to edit.
Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:
'use client'
import Link from 'next/link'
import { ProductDetail, type ProductDetailProps } from '@/blocks/commerce/product-detail'
export function ProductDetailView({ product, breadcrumbs, perks, sections }: Pick<ProductDetailProps, 'product' | 'breadcrumbs' | 'perks' | 'sections'>) {
return (
<ProductDetail
product={product}
breadcrumbs={breadcrumbs}
perks={perks}
sections={sections}
copy={{ breadcrumb: 'Shop' }}
linkComponent={Link}
onAddToCart={async (line) => {
// await your API here; the block shows progress until it settles
}}
onSave={(product, saved) => {
// your code
}}
/>
)
}Description
Let shoppers see a product from every side in the color they pick, choose a size and know when it will arrive.
Help customers check an order and see where it is on its way to them, with its items, details, a return flow in a dialog and a menu of actions.
Code
Product Detail, the Product detail story: the files youj add writes.
blocks/commerce
Reference
Props12 props, 3 types
Props
| Prop | Type | |
|---|---|---|
product | ProductThe product; required in practice. default a sample kettle (swap in yours) | a sample kettle (swap in yours) |
onAddToCart | (line: { product: Product; color: string; size?: string; quantity: number }) => Promise<unknown>Resolve once the line is in the cart; reject to shake the button. default a short demo wait | a short demo wait |
onSave | (product: Product, saved: boolean) => voidHears "Save for later" being turned on or off. | – |
breadcrumbs | { label: string; href: string; }[]The trail above the title, as links. Default: Shop › the product's category. | – |
sizeGuideHref | string | nullThe size guide's page; default '#size-guide' | '#size-guide' |
perks | ProductPerk[]The delivery panel's lines. Default: free delivery (arriving three working days from | – |
sections | ProductSection[]The folds at the foot. Default: details, shipping and returns. | – |
today | Date | numberToday, for the delivery day. default the demo's day | the demo's day |
currency | stringAn ISO 4217 code. default 'USD' | 'USD' |
locale | stringA BCP 47 locale for prices, dates and counts. default 'en-US' | 'en-US' |
linkComponent | ElementTypeRenders breadcrumb and size-guide links, e.g. Next.js default 'a' | 'a' |
copy | Partial<ProductDetailCopy>Any of the page's strings, to rewrite or translate. | – |
Product
| Prop | Type | |
|---|---|---|
idRequired | string | – |
nameRequired | string | – |
image | stringA photo's URL: it pictures the product (a colorway's own | – |
angle | stringThe product from its other side; hover and keyboard focus turn to it. | – |
focus | readonly [number, number]Where the product sits in its photos, in percent from the top start: a crop of another shape keeps it in frame. default `[50, 50]` | `[50, 50]` |
href | stringThe product's page. default `#<id>` | `#<id>` |
categoryRequired | string | – |
priceRequired | number | – |
compareAt | number | – |
ratingRequired | number | – |
reviewsRequired | number | – |
badge | string | – |
colorsRequired | Colorway[]The colorways it's sold in; the first is the default. | – |
sizes | string[] | – |
soldOut | string[]Sizes out of stock right now. | – |
descriptionRequired | string | – |
ProductPerk
| Prop | Type | |
|---|---|---|
iconRequired | ComponentType<{ size?: number }> | – |
titleRequired | string | – |
detailRequired | string | – |
ProductSection
| Prop | Type | |
|---|---|---|
idRequired | string | – |
titleRequired | string | – |
bodyRequired | ReactNode | – |
Strings32 keys for copy
Strings
copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.
breadcrumbphotosviewsslidethumbratedreviewseachwasnowcolorsizesizeGuidesoldOutquantityaddToCartaddingaddedaddErrorsavefreeDeliveryarrivespickUppickUpDetailreturnsreturnsDetaildetailsdetailsBodyshippingshippingBodyreturnsTitlereturnsBodyBuilt from10 components, 1 blocks
Built from
Built on
Accessibilityheadings, controls, dialogs
Accessibility
Product detail has one h1. The size choices are radio inputs with a label each (a sold-out size says so in its label), the gallery is a labelled carousel whose slides are labelled by position, and the rating is read as text. Order detail is a main under a header with labelled sections for items, details and shipment, and the shipment progress is a list with a status region. The return flow opens in a dialog that closes with Escape, and row actions sit in a menu with arrow-key navigation. Links and buttons are real a and button elements with the kit’s focus ring.