Skip to content

Update storefront component design using Opus - #1515

Merged
sbolinger-godaddy merged 4 commits into
mainfrom
feat/storefront-default-design
Oct 21, 2026
Merged

sbolinger-godaddy merged 4 commits into
mainfrom
feat/storefront-default-design

Conversation

@sbolinger-godaddy

@sbolinger-godaddy sbolinger-godaddy commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Gives the packaged storefront components a cleaner default look that reads well on light and dark host pages without configuration. The design is pretty similar, but it adds a few features and cleans it up.

Screenshot 2026-10-21 at 11 24 00 AM Screenshot 2026-10-21 at 11 24 16 AM
  • Catalog: borderless cards with square images, a Sale badge and the struck-through compare-at price. The grid is two columns on phones. Pagination is centered and hidden when there is only one page.
  • Product page: square gallery with the Sale badge. Options are buttons (radios), or a select when there are more than eight values. Values whose SKUs are all sold out, given the other selections, are crossed out but stay selectable. Quantity is a stepper capped at stock. The add button shows the total ("Add to cart · $64.00"). Until every option is chosen, it names the next one ("Select size"), and pressing it shows errors and focuses the first missing option.
  • Cart: the drawer title shows the count. Options share one line, the checkout note is a summary row, and there's a new CartContinueShopping part and a new empty state. CartButton is now a bag icon with a count badge.
  • Optional features, off by default: swatches through a new getSwatch provider prop, and a new RelatedProducts component.
  • Theme: new --commerce-sale / --commerce-on-sale theme properties. Muted text, lines and outlined or disabled controls derive from the inherited text color, so they work on dark pages.
  • Server: the product details route in gd-commerce-server returns each SKU's attribute value names, which sold-out marking uses. It's a separate commit. The storefront treats the field as optional: without it, or when the SKU list is truncated, no value is marked.

Review fixes: choosing an option no longer resets a quantity the shopper already set, and the Sale badge and struck-through compare-at price now compare each SKU's price with its own compare-at price.

Changeset

  • Changeset added: storefront-default-design.md (gd-commerce-storefront minor) and sku-attribute-values.md (gd-commerce-server minor)

Test Plan

  • pnpm --filter @godaddy/gd-commerce-storefront build, test (123 passing, including a new default-design.test.tsx), lint and typecheck
  • pnpm --filter @godaddy/gd-commerce-server test (256 passing) and lint
  • Packed tarball checked in the component test app against its mock API. Its Playwright scripts pass: smoke (19 checks), parts (13), walkthrough (5), boutique (4) and contract. They cover the connected store, the no-store sample catalog and cart, switching between them without a reload, sold-out values, impossible combinations, swatches, related products and phone widths.

sbolinger-godaddy and others added 2 commits October 21, 2026 10:50
Catalog cards get square images, a Sale badge and compare-at price, and no
description. The product page uses option buttons (a select above eight
values), crosses out sold-out values, caps a quantity stepper at stock, and
labels add with the total or the next missing option. The cart drawer shows
the count, one-line options, a checkout-note row and Continue shopping, and
CartButton becomes an icon with a count badge.

Swatches are supported through a getSwatch provider prop, off by default.
RelatedProducts is a new optional component. Sold-out marking uses SKU attribute value names when the server returns them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each SKU in the product details response now carries its attribute value
names, so a client can tell which option values are sold out given the
other selections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sbolinger-godaddy
sbolinger-godaddy requested a review from a team as a code owner October 21, 2026 17:57
@changeset-bot

changeset-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e55a25c

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

This PR includes changesets to release 2 packages
Name Type
@godaddy/gd-commerce-server Minor
@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

@sbolinger-godaddy sbolinger-godaddy changed the title Apply the proposed default design to the storefront components Update storefront component design using Opus Oct 21, 2026
…r SKU

The stepper now works before options are chosen, so resetting the quantity
on every selection change silently dropped a quantity the shopper set. It
is kept; a quantity above the new SKU's stock shows the quantity error.

A struck-through compare-at price could pair the cheapest SKU's price with
another SKU's compare-at price. The product page now strikes through a
starting compare-at price only when the cheapest SKUs share it, and cards
only for a single price. The Sale badge is unchanged.

The changeset notes the quantity and status changes for custom layouts, and
card swatch text keeps acronyms in attribute labels.

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

@wesleycole wesleycole left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving with one non-blocking follow-up: isProductOnSale() in packages/commerce-storefront/src/product-card.tsx:243–245 compares product-wide minimum price and minimum compare-at price, which may belong to different SKUs. For example, a $10 SKU without a compare-at price plus a $20 SKU with a $20 compare-at price incorrectly receives a Sale badge. The reverse can hide a real discount when the cheapest SKU has an equal compare-at price. This affects catalog/related-product cards and the product page before selection. Please consider determining sale status from paired prices on individual SKUs, with a conservative fallback for incomplete data. Two targeted regression tests reproduced both cases.

Validation: storefront build, all 121 existing storefront tests, storefront typecheck, and all 256 server tests passed.

The badge compared the product's lowest price with its lowest compare-at
price, which can belong to different SKUs: a $10 SKU without a compare-at
price beside a $20 SKU at a $20 compare-at price was badged, and a real
markdown on a pricier SKU was missed when the cheapest SKU's compare-at
price equaled its price.

With every SKU's price loaded, as on the product page, the badge shows when
some SKU's compare-at price is above that SKU's price. Without them, as in
the catalog list, it shows only when the lowest compare-at price is above
the highest price, which guarantees a marked-down SKU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sbolinger-godaddy
sbolinger-godaddy merged commit 7e94726 into main Oct 21, 2026
3 checks passed
@sbolinger-godaddy
sbolinger-godaddy deleted the feat/storefront-default-design branch October 21, 2026 20:22
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.

2 participants