镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Leave out attribute values no active SKU has on the product page - #1521

Draft
sbolinger-godaddy wants to merge 1 commit into
mainfrom
fix/storefront-hide-unpurchasable-attribute-values
Draft

sbolinger-godaddy wants to merge 1 commit into
mainfrom
fix/storefront-hide-unpurchasable-attribute-values

Conversation

@sbolinger-godaddy

Copy link
Copy Markdown
Collaborator

Summary

Problem. ProductDetails builds each option control from every value on the attribute, whether or not an active SKU has that value. A merchant may define more values than they stock. For example, a product might define sizes XS to XL but have active SKUs only in XS. Shoppers then see every size. Choosing one with no SKU shows "This combination is unavailable. Choose different options." and disables Add to cart, even though the page offered that choice. We saw this on a live store: 5 of its 8 products offered sizes they couldn't sell.

Change. The product response already includes every active SKU with its attribute value names (gd-commerce-server 0.4.0+, up to 50 SKUs). When it does, the page keeps only the values that some SKU has:

  • getOfferedAttributes() filters each attribute's values to those found on an active SKU. It uses the same completeness check as sold-out marking: no hasNextPage, totalCount equal to the loaded SKUs, and every SKU carrying attributeValues. That check now lives in a shared getSkuAttributeValues() helper, so the two can't drift apart.
  • A URL selection that names a value outside the offered values counts as not chosen. For example, an old link with ?option.size=s asks the shopper to pick a size instead of showing "unavailable."
  • These cases keep every value, as before:
    • the SKU list is truncated
    • the server is older and returns no SKU attributeValues
    • no SKU has a value for the attribute, so the control still renders
  • Sold-out marking doesn't change. A value whose SKUs are all sold out is still shown, crossed out.

useProductDetailsOption() and ProductDetailsOption read the filtered values, so custom option controls get the same behavior.

Changeset

  • Changeset added: @godaddy/gd-commerce-storefront minor. The README and docs/server-api.md are updated to match.

Test Plan

New tests in default-design.test.tsx use a fixture product with five sizes and SKUs in only two:

  • offers only the values some active SKU has, so every choice can be bought: only xs and l render. Choosing L enables "Add to cart, $25.00", and "unavailable" never appears.
  • treats a shared link to a value with no active SKU as not yet chosen: ?option.size=s renders no checked size and a "Select size" button, with no "unavailable" message.
  • keeps every value when the SKU list is incomplete: with hasNextPage: true, all five sizes render.

The first two tests fail against main's product-details-context.tsx (2 failed, 13 passed). They pass with this change. The third passes on both, as expected, because it covers unchanged behavior.

pnpm --filter @godaddy/gd-commerce-storefront build, lint, typecheck, and test (9 files, 133 tests) all pass.

🤖 Generated with Claude Code

ProductDetails built each option control from every value on the
attribute. A product with five sizes but SKUs in only two offered all
five, and choosing one of the other three showed "This combination is
unavailable. Choose different options."

When the product response includes every SKU with its attribute values,
keep only values some SKU has. A URL selection outside the offered
values counts as not chosen. A truncated SKU list, an older server, or
an attribute no SKU uses keeps every value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fc6df60

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@godaddy/gd-commerce-storefront Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant