VariantSelector
Description
Displays product variant options (size, color, etc.) with automatic availability detection. Updates URL and page data when options are selected. Supports custom rendering for attributes and options.
Import
import { VariantSelector } from '@components/frontStore/catalog/VariantSelector';
Usage
import { VariantSelector } from '@components/frontStore/catalog/VariantSelector';
import { ProductProvider } from '@components/frontStore/catalog/ProductContext';
import { FormProvider, useForm } from 'react-hook-form';
function ProductPage({ product }) {
const methods = useForm();
return (
<ProductProvider product={product}>
<FormProvider {...methods}>
<VariantSelector />
</FormProvider>
</ProductProvider>
);
}
Props
| Name | Type | Required | Description |
|---|---|---|---|
| AttributeRenderer | React.ComponentType | No | Custom attribute group renderer |
| OptionRenderer | React.ComponentType | No | Custom option item renderer |
Type Definitions
ProcessedAttribute
interface ProcessedAttribute {
attributeId: number;
attributeCode: string;
attributeName: string;
options: Array<{
optionId: number;
optionText: string;
available: boolean; // Can be selected with current selections
}>;
selected: boolean;
selectedOption: number | null;
}
Custom Renderer Props
AttributeRenderer Props
interface VariantAttributeGroupProps {
attribute: ProcessedAttribute;
options: Array<AttributeOption & { available: boolean }>;
onSelect: (attributeCode: string, optionId: number) => Promise<void>;
OptionItem?: React.ComponentType<VariantOptionItemProps>;
}
OptionRenderer Props
interface VariantOptionItemProps {
option: AttributeOption & { available: boolean };
attribute: ProcessedAttribute;
isSelected: boolean;
onSelect: (attributeCode: string, optionId: number) => Promise<void>;
}
Examples
Basic Usage
import { VariantSelector } from '@components/frontStore/catalog/VariantSelector';
import { ProductProvider } from '@components/frontStore/catalog/ProductContext';
import { FormProvider, useForm } from 'react-hook-form';
function ProductDetail({ product }) {
const methods = useForm();
return (
<ProductProvider product={product}>
<FormProvider {...methods}>
<div className="product-options">
<VariantSelector />
</div>
</FormProvider>
</ProductProvider>
);
}
Custom Option Renderer
import { VariantSelector } from '@components/frontStore/catalog/VariantSelector';
function CustomOptionItem({ option, isSelected, onSelect, attribute }) {
return (
<button
onClick={() => onSelect(attribute.attributeCode, option.optionId)}
disabled={!option.available}
className={`
option-btn
${isSelected ? 'selected' : ''}
${!option.available ? 'disabled' : ''}
`}
>
{option.optionText}
{!option.available && <span className="unavailable-badge">×</span>}
</button>
);
}
function ProductVariants() {
return <VariantSelector OptionRenderer={CustomOptionItem} />;
}
Custom Attribute Renderer
import { VariantSelector } from '@components/frontStore/catalog/VariantSelector';
function CustomAttributeGroup({ attribute, options, onSelect, OptionItem }) {
return (
<div className="variant-group">
<h3 className="attribute-name">
{attribute.attributeName}
{attribute.selected && <span className="checkmark">✓</span>}
</h3>
<div className="options-grid">
{options.map(option => (
<OptionItem
key={option.optionId}
option={option}
attribute={attribute}
isSelected={attribute.selectedOption === option.optionId}
onSelect={onSelect}
/>
))}
</div>
</div>
);
}
function ProductVariants() {
return <VariantSelector AttributeRenderer={CustomAttributeGroup} />;
}
Color Swatches
import { VariantSelector } from '@components/frontStore/catalog/VariantSelector';
function ColorSwatch({ option, isSelected, onSelect, attribute }) {
// Assuming option has a color hex value
const colorCode = option.colorCode || '#ccc';
return (
<button
onClick={() => onSelect(attribute.attributeCode, option.optionId)}
disabled={!option.available}
className={`
color-swatch
${isSelected ? 'ring-2 ring-blue-500' : ''}
${!option.available ? 'opacity-30 cursor-not-allowed' : ''}
`}
style={{ backgroundColor: colorCode }}
title={option.optionText}
>
{isSelected && <span className="checkmark">✓</span>}
</button>
);
}
function ProductPage() {
return (
<VariantSelector
OptionRenderer={ColorSwatch}
/>
);
}
Related Components
- ProductContext - Product data provider
- AddToCart - Add to cart component