Advanced Variant Selector
A configurable product-options panel: native radio color swatches shown in each color's real value, size buttons that disable per the currently selected color's stock, and a material dropdown with its own price delta. Changing any option updates the displayed price and the 'in stock' message from a fixed stock lookup table.
Docs
Installation
A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its button dependencies and any missing npm packages, and installs them straight into your project.
npx shadcn add https://staaarter.com/r/advanced-variant-selector.jsonPrefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/ecommerce/ecommerce16.tsx instead.
Usage
The file also exports ecommerce16Demo, 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 { Ecommerce16, ecommerce16Demo } from "@/components/blocks/ecommerce/ecommerce16"; export default function Page() { return <Ecommerce16 {...ecommerce16Demo} />; }
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| productName | string | "Heavyweight Crewneck Sweatshirt" | Product name heading. |
| basePrice | number | 4800 | Base price in cents, before any material price delta. |
| image | { src: string; alt: string } | undefined | Product photo; falls back to a placeholder when unset. |
| colors | ColorOption[] | [] | Color swatches, each rendered with its own real value as the swatch background. |
| sizes | string[] | [] | Size labels, in display order. |
| materials | MaterialOption[] | [] | Material choices for the select, each with its own price delta. |
| stockByVariant | Record<string, number> | {} | Stock count keyed by `${colorName}-${sizeLabel}`; a missing key is treated as 0 (out of stock). |
| className | string | none | Extra classes for the outer section element. |
Types
interface ColorOption { name: string; value: string; // real CSS color, e.g. a hex code } interface MaterialOption { label: string; priceDelta: number; // cents, relative to basePrice }
Behavior notes
- Color, size, and material are all real useState, and every one of them feeds the displayed price and stock message live, not just for show.
- Color swatches are real native `<input type="radio">` elements grouped by name, visually hidden with sr-only and styled entirely through the sibling label (a `has-[:checked]` ring shows the active swatch, `has-[:focus-visible]` shows a keyboard focus ring); each swatch's background is the color's own real hex value, the one documented exception to this repo's semantic-token-only rule since the swatch's whole point is showing the actual product color.
- Size buttons are the same radio-as-button pattern, but a size becomes a real disabled input (not just muted styling) when stockByVariant has 0 (or no entry) for `${selectedColor}-${size}`, so it cannot be selected by mouse or keyboard while that color is active.
- Switching color re-checks the currently selected size against the new color's stock; if that combination is out of stock, selection jumps to the first in-stock size for the new color instead of leaving a disabled size selected.
- The material `<select>` adds its own priceDelta on top of basePrice; the displayed price recomputes immediately on change, it is not restricted to whole-dollar deltas.
- The stock message has three states driven by the current color+size combination's count: 'Out of stock in this combination' at 0, an amber 'Only N left in stock' at 5 or fewer, and a plain 'N in stock' otherwise; it's wrapped in aria-live="polite" so screen reader users hear updates as they change options.
- Add to cart is disabled whenever the current combination has 0 stock, but otherwise has no real cart wiring.
More Ecommerce Blocks
View all →wishlist-manager
Wishlist Manager
Saved-items list with stock-status badges, move-to-cart and remove actions, and a real empty state.
product-information-tabs
Product Information Tabs
Tabbed product details with Description, Features, Specifications, Reviews, and Shipping panels.
collection-showcase-grid
Collection Showcase Grid
A large featured-collection hero card alongside a grid of smaller supporting collection tiles.
shop-by-brand-grid
Shop by Brand Grid
A grid of bordered brand tiles with a wordmark-style name, product count, and a hover affordance.
sale-countdown-timer
Sale Countdown Timer
A live days/hours/minutes/seconds countdown in default, compact, or full-width banner layouts.
gift-card-redemption-form
Gift Card Redemption Form
A code-entry form that validates against a fixed list of demo gift cards and shows a real success or error state.