Same Centra fashion PDP, same sticky purchase bar. The old pattern disabled the primary CTA until a size was chosen. Sometimes the label flipped to Choose size and the button did nothing useful. Shoppers tap once, assume the site is broken, and leave.
The new pattern splits enablement from validation. primaryEnabled ignores missing size. It still respects pending state, hard disabled flags, and notify mode. The label can still read Choose size. The button stays clickable.
ProductPurchaseSelectionProvider keeps sizeRequiredError. submitAddToCart with no size sets the error and returns early. Picking a size clears it. The red hint renders only when multiSize && sizeRequiredError && !sizeSelected. No invisible reserved space before the first miss.
Sticky bar wiring matters on mobile. Press add with no size: call submitAddToCart (sets the error), open the variant sheet, then focusSizeControl() through a ProductStickyCartSizeFocusTarget ref registered on the size control. The shopper lands on the chips instead of hunting for why nothing happened.
ProductInfoActions went presentational. Parent passes cartLabel, primaryEnabled, primaryIcon, and showSizeRequiredHint. resolvePrimaryPurchaseUiState centralizes notify mode, icons, and hint visibility so PDP, sticky bar, and quick add share one truth.
Shop the Look needed the same mutex discipline. Add to cart accepts item arrays under one lock so parallel pin adds from Add all do not race Centra line creation.
Validate size on submit, not on render
The primary button stays pressable. Tap Add to cart without a size to set the error, show the hint, and open the variant sheet.
Size
Hint renders only when multiSize && sizeRequiredError && !sizeSelected. No reserved empty space before the first miss.
Press Add to cart without a size. The hint appears after the miss, the sheet opens, and the size row gets focus.
Validation on submit beats a permanently disabled CTA. Tell people what went wrong when they try, not before they care.
Happy coding! Sander