variant-selection

Variant Selection System

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "variant-selection" with this command: npx skills add saleor/storefront/saleor-storefront-variant-selection

Variant Selection System

Source: Saleor Docs - Attributes - How product/variant attributes work

When to Use

Use this skill when:

  • Modifying variant/attribute selection on product pages

  • Understanding why a variant isn't selectable

  • Adding discount indicators to variant options

  • Debugging "Add to Cart" button state

Instructions

Core Concept: Variants, Not Products

You add VARIANTS to cart, not products. Each variant is a specific attribute combination:

Product Attributes Variant ID

T-Shirt Black + Medium abc123

T-Shirt Black + Large def456

T-Shirt White + Medium ghi789

The checkoutLinesAdd mutation requires a specific variantId . Without selecting ALL attributes, there's no variant to add.

Two Types of Variant Attributes

Saleor distinguishes between two types of variant attributes:

Type variantSelection

Purpose UI Passed to Cart?

Selection VARIANT_SELECTION

Identify which variant (color, size) Interactive picker No - just the variantId

Non-Selection NOT_VARIANT_SELECTION

Describe the variant (material, brand) Display-only badges No - already on variant

Key insight: Neither type is "passed" to checkout. You only pass the variantId . All attributes are already stored on the variant in Saleor.

GraphQL queries use the variantSelection filter:

selectionAttributes: attributes(variantSelection: VARIANT_SELECTION) { ... } nonSelectionAttributes: attributes(variantSelection: NOT_VARIANT_SELECTION) { ... }

Non-selection attributes are display-only - shown as informational badges, not interactive selectors.

File Structure

src/ui/components/pdp/variant-selection/ ├── index.ts # Public exports ├── types.ts # TypeScript interfaces ├── utils.ts # Data transformation & logic ├── variant-selector.tsx # Single attribute selector ├── variant-selection-section.tsx # Main container ├── optional-attributes.tsx # Non-selection attribute badges └── renderers/ ├── color-swatch-option.tsx # Color swatch (circular) └── button-option.tsx # Button for size/text (unified)

Key Functions in utils.ts

Function Purpose

groupVariantsByAttributes()

Extract unique attribute values from variants

findMatchingVariant()

Find variant matching ALL selected attributes

getOptionsForAttribute()

Get options with availability/compatibility info

getAdjustedSelections()

Clear conflicting selections when needed

getUnavailableAttributeInfo()

Detect dead-end selections

For detailed function signatures and usage, see UTILS_REFERENCE.md.

Option States

State Meaning Visual Clickable?

Available In stock Normal ✓

Incompatible No variant with this + current selections Dimmed ✓ (clears others)

Out of stock Variant exists but quantity = 0 Strikethrough ✗

URL Parameter Pattern

Selections are stored in URL params:

?color=black&size=m&variant=abc123 ↑ ↑ ↑ Color sel Size sel Matching variant (set automatically)

The variant param is only set when ALL attributes are selected.

Discount Badges

Options can show discount percentages:

// In utils.ts interface VariantOption { id: string; name: string; available: boolean; hasDiscount?: boolean; // Any variant with this option is discounted discountPercent?: number; // Max discount percentage // ... }

The renderers display a small badge when discountPercent is set.

Examples

Smart Selection Adjustment

When user selects an incompatible option:

State: ?color=red (Red only exists in Size S) User clicks: Size L Result: ?size=l (Red is cleared, not blocked)

Users are never "stuck" - they can always explore all options.

Dead End Detection

const deadEnd = getUnavailableAttributeInfo(variants, groups, selections); // Returns: { slug: "size", name: "Size", blockedBy: "Red" } // UI shows: "No size available in Red"

Custom Renderers

<VariantSelectionSection variants={variants} renderers={{ color: MyCustomColorPicker, size: MySizeChart, }} />

State Machine

The selection system has 5 states with automatic conflict resolution. For the full state diagram and transition rules, see STATE_MACHINE.md.

Quick reference:

State Add to Cart Description

Empty ❌ No selections

Partial ❌ Some attributes selected

Complete ✅ All selected, variant found

Conflict — Auto-clears to Partial

DeadEnd ❌ Selection blocks other groups

Key behavior: When user selects an incompatible option, other selections are cleared automatically (not blocked). Users can always explore all options.

Anti-patterns

❌ Don't enable "Add to Cart" without full selection - Needs variant ID

❌ Don't block incompatible options - Let users click, clear others

❌ Don't assume single attribute - Products can have multiple

❌ Don't use 0 in boolean checks for prices - Use typeof === "number"

❌ Don't make non-selection attributes interactive - They're display-only (badges, not toggles)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

caching-strategy

No summary provided by upstream source.

Repository SourceNeeds Review
General

react-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

ui-components

No summary provided by upstream source.

Repository SourceNeeds Review