Variant Selectorcomponent
The component helps you build a form for selecting available variants of a product. It is important for variant selection state to be maintained in the URL, so that the user can navigate to a product and return back to the same variant selection. It is also important that the variant selection state is shareable via URL. The
component provides a render prop that renders for each product option.
Anchor to propsProps
- Anchor to childrenchildren({ option }: { option: ; }) => ReactNoderequired
- Anchor to handlehandlestringrequired
The product handle for all of the variants
- Anchor to optionsoptionsArray<> | undefinedrequired
Product options from the Storefront API. Make sure both
name
andvalues
are a part of your query.- Anchor to productPathproductPathstring
By default all products are under /products. Use this prop to provide a custom path.
- Anchor to selectedVariantselectedVariantMaybe<PartialDeep<ProductVariant>>
An optional selected variant to use for the initial state if no URL parameters are set
- Anchor to variantsvariants| PartialDeep<ProductVariantConnection> | Array<PartialDeep<ProductVariant>>
Product variants from the Storefront API. You only need to pass this prop if you want to show product availability. If a product option combination is not found within
variants
, it is assumed to be available. Make sure to includeand
and
.
- boolean
Should the VariantSelector wait to update until after the browser navigates to a variant.
VariantSelectorProps
- children
({ option }: { option: VariantOption; }) => ReactNode
- handle
The product handle for all of the variants
string
- options
Product options from the [Storefront API](/docs/api/storefront/2025-04/objects/ProductOption). Make sure both `name` and `values` are a part of your query.
Array<PartialProductOption> | undefined
- productPath
By default all products are under /products. Use this prop to provide a custom path.
string
- selectedVariant
An optional selected variant to use for the initial state if no URL parameters are set
Maybe<PartialDeep<ProductVariant>>
- variants
Product variants from the [Storefront API](/docs/api/storefront/2025-04/objects/ProductVariant). You only need to pass this prop if you want to show product availability. If a product option combination is not found within `variants`, it is assumed to be available. Make sure to include `availableForSale` and `selectedOptions.name` and `selectedOptions.value`.
| PartialDeep<ProductVariantConnection> | Array<PartialDeep<ProductVariant>>
- waitForNavigation
Should the VariantSelector wait to update until after the browser navigates to a variant.
boolean
{
/** The product handle for all of the variants */
handle: string;
/** Product options from the [Storefront API](/docs/api/storefront/2025-04/objects/ProductOption). Make sure both `name` and `values` are a part of your query. */
options: Array<PartialProductOption> | undefined;
/** Product variants from the [Storefront API](/docs/api/storefront/2025-04/objects/ProductVariant). You only need to pass this prop if you want to show product availability. If a product option combination is not found within `variants`, it is assumed to be available. Make sure to include `availableForSale` and `selectedOptions.name` and `selectedOptions.value`. */
variants?:
| PartialDeep<ProductVariantConnection>
| Array<PartialDeep<ProductVariant>>;
/** By default all products are under /products. Use this prop to provide a custom path. */
productPath?: string;
/** Should the VariantSelector wait to update until after the browser navigates to a variant. */
waitForNavigation?: boolean;
/** An optional selected variant to use for the initial state if no URL parameters are set */
selectedVariant?: Maybe<PartialDeep<ProductVariant>>;
children: ({option}: {option: VariantOption}) => ReactNode;
}
VariantOption
- name
string
- value
string
- values
Array<VariantOptionValue>
{
name: string;
value?: string;
values: Array<VariantOptionValue>;
}
VariantOptionValue
- isActive
boolean
- isAvailable
boolean
- optionValue
PartialProductOptionValues
- search
string
- to
string
- value
string
- variant
PartialDeep<ProductVariant, {recurseIntoArrays: true}>
{
value: string;
isAvailable: boolean;
to: string;
search: string;
isActive: boolean;
variant?: PartialDeep<ProductVariant, {recurseIntoArrays: true}>;
optionValue: PartialProductOptionValues;
}
PartialProductOptionValues
PartialDeep<ProductOptionValue>
PartialProductOption
PartialDeep<
Omit<ProductOption, 'optionValues'> & {
optionValues: Array<PartialProductOptionValues>;
}
>
Example code
examples
Example code
description
I am the default example
JavaScript
import {VariantSelector} from '@shopify/hydrogen'; import {Link} from 'react-router'; const ProductForm = ({product}) => { return ( <VariantSelector handle={product.handle} options={product.options} variants={product.variants} > {({option}) => ( <> <div>{option.name}</div> <div> {option.values.map( ({value, isAvailable, to, isActive, variant}) => ( <Link to={to} prefetch="intent" className={ isActive ? 'active' : isAvailable ? '' : 'opacity-80' } > {value} <br /> {variant && `SKU: ${variant.sku}`} </Link> ), )} </div> </> )} </VariantSelector> ); };
TypeScript
import {VariantSelector} from '@shopify/hydrogen'; import type {Product} from '@shopify/hydrogen/storefront-api-types'; import {Link} from 'react-router'; const ProductForm = ({product}: {product: Product}) => { return ( <VariantSelector handle={product.handle} options={product.options} variants={product.variants} > {({option}) => ( <> <div>{option.name}</div> <div> {option.values.map( ({value, isAvailable, to, isActive, variant}) => ( <Link to={to} prefetch="intent" className={ isActive ? 'active' : isAvailable ? '' : 'opacity-80' } > {value} <br /> {variant && `SKU: ${variant.sku}`} </Link> ), )} </div> </> )} </VariantSelector> ); };