From c3e483d5786b86b91898f5fae9632b75593f24a9 Mon Sep 17 00:00:00 2001 From: NemisysT Date: Tue, 7 Oct 2025 22:19:41 +0530 Subject: [PATCH] Fix variant selector to allow switching between valid combinations Fixes #1457 The variant selector was preventing users from switching between valid product combinations. The issue was in the isAvailableForSale logic which checked if ALL current options plus the new selection formed a valid combination, creating impossible scenarios (e.g., checking for BLACK+L+WHITE when clicking WHITE from BLACK+L). The fix changes the availability check to only verify if there exists at least one valid variant with the selected option value, regardless of other currently selected options. This allows users to freely switch between any valid combinations. Example: Users can now switch from BLACK+L to WHITE+M without having to first change to an intermediate size. --- components/product/variant-selector.tsx | 37 ++++++++++++++++--------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/components/product/variant-selector.tsx b/components/product/variant-selector.tsx index 5c738af9a7..2400863648 100644 --- a/components/product/variant-selector.tsx +++ b/components/product/variant-selector.tsx @@ -19,6 +19,7 @@ export function VariantSelector({ }) { const { state, updateOption } = useProduct(); const updateURL = useUpdateURL(); + const hasNoOptionsOrJustOneOption = !options.length || (options.length === 1 && options[0]?.values.length === 1); @@ -43,20 +44,30 @@ export function VariantSelector({ {option.values.map((value) => { const optionNameLowerCase = option.name.toLowerCase(); - // Base option params on current selectedOptions so we can preserve any other param state. - const optionParams = { ...state, [optionNameLowerCase]: value }; + // For checking availability, we only consider the current option being changed + // and any other selected options that differ from this one + const testParams = { ...state, [optionNameLowerCase]: value }; - // Filter out invalid options and check if the option combination is available for sale. - const filtered = Object.entries(optionParams).filter(([key, value]) => - options.find( - (option) => option.name.toLowerCase() === key && option.values.includes(value) - ) - ); - const isAvailableForSale = combinations.find((combination) => - filtered.every( - ([key, value]) => combination[key] === value && combination.availableForSale - ) - ); + // Find if there's any variant available with this specific option value + // We check if at least one combination exists where: + // 1. This option has the selected value + // 2. The variant is available for sale + const isAvailableForSale = combinations.some((combination) => { + // Check if this combination has the option value we're testing + if (combination[optionNameLowerCase] !== value) { + return false; + } + + // Check if the combination is available for sale + if (!combination.availableForSale) { + return false; + } + + // For multi-option products, check if there's a valid path: + // A value is clickable if there exists at least one valid combination + // where this option has this value + return true; + }); // The option is active if it's in the selected options. const isActive = state[optionNameLowerCase] === value;