Staaarter

Product Detail with Variants

A single-image product hero focused on variant selection: color swatches, a size button group, a real plus/minus quantity stepper, and a heart wishlist toggle, above an Add to cart button. A simpler companion to the gallery variant, for products that only need one photo.

By Staaarter Team
Ecommerce
Docs
Live preview

Docs

Installation

A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its button, media-slot dependencies and any missing npm packages, and installs them straight into your project.

npx shadcn add https://staaarter.com/r/product-detail-with-variants.json

Prefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/ecommerce/ecommerce34.tsx instead.

Usage

The file also exports ecommerce34Demo, the exact props behind the preview above. Spread it to get a working section in one line, then replace it with your own data.

import { Ecommerce34, ecommerce34Demo } from "@/components/blocks/ecommerce/ecommerce34";

export default function Page() {
  return <Ecommerce34 {...ecommerce34Demo} />;
}

Props

PropTypeDefaultDescription
productNamestringnoneProduct title rendered as the page heading.
pricestringnonePre-formatted price, e.g. "$68.00".
descriptionstringnoneProduct description paragraph.
imageMediaSlotImagenoneProduct photo; falls back to a centered placeholder icon when omitted.
colorsColorOption[][]Color swatches rendered as a radio group; hidden entirely when empty.
sizesstring[][]Size labels rendered as a button-style radio group; hidden entirely when empty.
classNamestringnoneExtra classes for the outer section element.

Types

type MediaSlotImage = { src: string; alt: string };

type ColorOption = { name: string; hex: string };

Behavior notes

  • Color/size selection, the quantity stepper, and the wishlist heart are all real client-side state (useState); Add to cart is decorative since there is no cart to add to in this standalone block.
  • The quantity stepper clamps between 1 and 99 and disables the minus button at 1; the current count is announced to assistive tech via aria-live on the count itself.
  • The wishlist button toggles a filled/unfilled heart and its aria-pressed state, but nothing is persisted or sent anywhere.
  • The color swatches are native <input type="radio"> elements visually hidden with sr-only and reskinned via the wrapping <label>, using has-[:checked]/has-[:focus-visible] so keyboard focus is still visible.