Skip to main content

Product Purchase

This family builds reactive product presentation and cart interaction UI. ProductProvider is the optional structural container for shared product, variation, and active-media state. Product Image, Product Media, Price, SKU, Availability, and Description consume that state without mutating the selected variation. AddToCartForm owns a local purchase draft and the Add action; ProductCartQuantity is a separate Provider-scoped control for the quantity already confirmed in the cart.

When To Use This Family

Use this family anywhere a customer can buy a product: product archive cards, single product templates, featured product sections, or buy-now product panels.

Quick Start

Variable product purchase form
<OmeWooProductProvider product="{this.omewoo}">
{#slot default}
<OmeWooProductImage media_id="{this.omewoo.media.image.id}" />
<OmeWooProductMedia media="{this.omewoo.media.gallery}">
{#slot default}
<OmeWooProductImage media_id="{media.id}" maximum_size="woocommerce_gallery_thumbnail" />
{/slot}
</OmeWooProductMedia>

<OmeWooProductPrice content="{this.omewoo.price.html}" />
<OmeWooProductSku content="{this.omewoo.product.sku}" />
<OmeWooProductAvailability content="{this.omewoo.purchase.availabilityHtml}" />
<OmeWooProductDescription content="{this.omewoo.description.shortHtml}" />

<OmeWooProductCartQuantity />

<OmeWooAddToCartForm product='{{"product_id":"{this.id}","product_type":"{this.omewoo.product.type}","variants":{this.omewoo.variants}}}'>
{#slot default}
{#loop this.omewoo.attributes as attribute}
<OmeWooAttributeSelector target='{{"attribute":{attribute}}}' />
{/loop}
<OmeWooVariationResetButton content='{{"label":"Clear selections"}}' />
<OmeWooAddToCartButton behavior='{{"mode":"counter","counter_presentation":"stepper","trigger":"form_submit"}}' />
<OmeWooBuyNowButton content='{{"label":"Buy now"}}' />
{/slot}
</OmeWooAddToCartForm>
{/slot}
</OmeWooProductProvider>

Use {item.*} instead of {this.*} when this form is inside a product loop.

Components

Component keyRole
OmeWooProductProviderOptional structural container that owns the base product and shared derived variation-selection state.
OmeWooProductImageEtch Dynamic Image atom that can follow the Provider's active image or its Product Media row.
OmeWooProductMediaAccessible selectable media collection that changes the Provider's active image without changing the selected variation.
OmeWooProductPriceDisplays server-formatted Woo price HTML and can follow the selected variation.
OmeWooProductSkuDisplays the base or selected-variation SKU.
OmeWooProductAvailabilityDisplays Woo availability HTML in a polite live region.
OmeWooProductDescriptionDisplays a full or short base description and follows variation descriptions.
OmeWooProductCartQuantityReads and mutates the confirmed cart quantity for the Provider's simple product or fully resolved variation.
OmeWooAddToCartFormOwns the product ID, product type, variation ID, stock/availability flags, and submitted form state.
OmeWooAttributeSelectorSelects one variation attribute object from omewoo.attributes.
OmeWooVariationResetButtonClears all AttributeSelector selections in the nearest AddToCartForm.
OmeWooAddToCartButtonAdds a product by itself in standalone mode, or submits the parent form in form-submit mode.
OmeWooBuyNowButtonUses the parent form payload, adds the item, then redirects to checkout.

Authoring Structure

ProductProvider (optional structural shared-state container)
ProductImage (active hero image)
ProductMedia (selectable media collection)
ProductImage (authored row content)
ProductPrice, ProductSku, ProductAvailability, ProductDescription (read-only atoms)
ProductCartQuantity (confirmed cart quantity for the current purchasable identity)
AddToCartForm (purchase mutation boundary)
AttributeSelector loop over product attributes
VariationResetButton
AddToCartButton with trigger=form_submit
BuyNowButton

Use AddToCartButton as a standalone button only when it is outside an AddToCartForm.

ProductProvider Contract

Set OmeWooProductProvider.product to the complete Woo product object, not to selected fields:

ContextProduct expression
Single product template{this.omewoo}
Product loop or archive card{item.omewoo}

The Provider renders a real DOM container and participates in layout. structure.tag chooses its HTML tag and defaults to div; styling.class adds authored classes for layout and visual styling. The stable ome-woo-product-provider class and data-ome-woo-product-provider marker remain on the root.

The Provider supports simple and variable products. Simple products stay in base and do not emit variation-selection changes. Variable products move through exactly four selection phases:

PhaseMeaning
baseNo active attribute selection; the current product is the base product.
partialSome, but not all, required attributes are selected.
resolvedThe complete selection matches a variation; current_product is that variation.
invalidThe complete selection does not match a variation.

Availability is separate from phase. A valid out-of-stock or otherwise unavailable variation is still resolved; read its availability from the selected variation object.

The nearest Provider owns the controller for an AddToCartForm. Nested Providers are isolated, and missing or malformed Provider data fails safely without falling through to an outer Provider. A form without a Provider uses the same selection controller through a compatibility adapter and keeps its released datasets, submitted payload, and purchase behavior.

The Provider exposes only scalar public datasets:

DatasetMeaning
data-ome-woo-product-providerProvider root marker.
data-ome-product-idBase Woo product ID.
data-ome-product-typesimple or variable.
data-ome-selection-phasebase, partial, resolved, or invalid.
data-ome-selected-variation-idPresent only for a resolved variation.
data-ome-active-media-idCurrent image ID from the effective base or resolved-variation media collection, including a media item selected by the customer. Omitted when no image is available.

Complete product and variation objects are never copied into data-* attributes. Hidden unnamed payload carriers are internal transport details, not form fields or public styling hooks.

Reset returns Provider state to the base product and does not re-run behavior.select_first_option. Server-rendered markup remains useful before JavaScript; Etch editor preview intentionally shows the base product state only.

ProductProvider does not expose authored mutation setters. Attribute selection and reset still happen through controls inside AddToCartForm. Purchase-draft quantity belongs to AddToCartButton; confirmed-cart quantity belongs to ProductCartQuantity. Product Media may set the Provider's active image, but this does not change the selected variation and does not dispatch ome-woo:variation-selection-changed. See ome-woo:variation-selection-changed for the Provider-only event contract.

Reactive Product Media

Use OmeWooProductImage for a hero image, a Product Media thumbnail, or another image that must follow the nearest product context. It delegates attachment rendering to Etch Dynamic Image, so the WordPress media ID remains the source for registered image sizes, responsive image data, and media-library alt text.

Product Image propMeaning
media_idBase WordPress attachment ID for server rendering, editor preview, no-JavaScript output, and reset. Bind omewoo.media.image.id for a hero image or media.id inside Product Media.
altOptional authored override. Leave empty to let Etch use the attachment's media-library alt text.
maximum_sizeLargest registered size Etch may render. Defaults to woocommerce_single; Woo thumbnail and WordPress core sizes are also available. Active-media changes rebuild srcset and sizes with candidates no wider than this size.
styling.classClasses applied to the rendered image. The default preset keeps it responsive.

When Product Image is a descendant of the nearest valid Product Provider, it follows that Provider's active media. When it is inside a direct Product Media item, the row's media wins so every thumbnail keeps its own image while a separate hero follows the active selection. Nested Providers remain isolation boundaries.

If Product Image has no valid Product Provider or Product Media row, its authored server-rendered image remains unchanged. Development builds emit one calm, deduplicated warning that synchronization requires placing the atom in the Provider's default slot. Production never throws or clears the image. If the synchronized collection is empty, the atom uses WooCommerce's official product placeholder.

Use OmeWooProductMedia as an authored-row collection:

Product Media propMeaning
mediaOrdered base media array. Bind omewoo.media.gallery; runtime switches to the resolved variation's effective gallery and restores the base gallery on reset.
styling.root_classClasses on the real structural collection root. Product Media does not impose a grid, row, or column layout.
styling.item_classClasses on every interactive media-item button. The default preset supplies selected and focus affordances.

The default slot is the content of one media item, not a second collection wrapper. Author a Product Image in that slot with media_id="{media.id}"; Product Media reuses server-rendered rows, clones only its inert direct-child row template when the effective gallery grows, and preserves the authored template. Empty and malformed collections hide safely. A product without a featured image promotes its first valid gallery attachment to the primary image.

Product Media exposes a radiogroup containing radio buttons with roving tabindex. Click, Enter, Space, Arrow keys, Home, and End select media; Arrow, Home, and End also move focus. Alt text becomes the item label, with a localized positional label fallback. Selection is not communicated by color alone because checked state is exposed through aria-checked and datasets.

Product Media Styling Hooks

ElementStable hooks
Product Image.ome-woo-product-image, [data-ome-woo-product-image], [data-ome-media-id]
Product Media root.ome-woo-product-media, [data-ome-woo-product-media], [data-ome-state="has-media"], [data-ome-state="empty"]
Product Media item.ome-woo-product-media__item, [data-ome-woo-product-media-item], [data-ome-state="active"], [data-ome-state="inactive"], [data-ome-selected="true"], [data-ome-selected="false"], [data-ome-media-id], [data-ome-media-index]

Prefer the component class props for authored styling. The data hooks describe current runtime state and are useful for state-dependent styling; do not target the inert item template or internal Provider payload carriers.

Reactive Product Readouts

The four readouts take authored base content so server rendering, editor preview, and no-JavaScript output remain useful. Place them in the nearest ProductProvider default slot to make them follow a variable-product selection. They never select a variation, change quantity, or mutate the cart.

ComponentContent bindingAdditional props
OmeWooProductPrice{this.omewoo.price.html}price_display: formatted (default), current, regular, or sale.
OmeWooProductSku{this.omewoo.product.sku}No display selector. The atom renders the SKU value only.
OmeWooProductAvailability{this.omewoo.purchase.availabilityHtml}invalid_content: plain text used for an invalid complete selection.
OmeWooProductDescription{this.omewoo.description.html} or {this.omewoo.description.shortHtml}The authored binding chooses the full or short base description; a resolved variation uses its variation description.

Every readout also exposes styling.class for its root and styling.value_class for its value element. Use {item.omewoo...} instead of {this.omewoo...} in product loops.

Selection And Fallback Rules

Provider statePriceSKUAvailabilityDescription
Base or partial selectionAuthored base content.Authored base SKU.Authored base content.Authored full or short base content.
Resolved variation, including an unavailable variationSelected price representation.Variation SKU, falling back to the base SKU when empty.Variation Woo availability HTML.Variation description, falling back to the authored base description when empty.
Invalid complete selectionAuthored base content.Authored base SKU.Plain-text invalid_content.Authored base content.
ResetAuthored base content.Authored base SKU.Authored base content.Authored base content.

An empty effective value hides the atom with the native hidden attribute. In sale price display, a variation without a sale price hides the readout instead of inventing a price. Availability remains valid derived presentation for a resolved but out-of-stock variation; an out-of-stock variation does not become an invalid selection.

Woo and WordPress format price, availability, and description HTML on the server. The resulting markup is filtered through the post-content sanitization policy before it reaches these atoms. SKU and invalid_content are always written as text. The browser does not rebuild currency, tax, stock, or description markup.

Outside a Provider, authored output stays unchanged. Development builds log one deduplicated warning per readout type explaining that a Provider is required only for variation synchronization. Production does not throw, clear, or warn.

Stable Styling Hooks

AtomRootValue
Price[data-ome-woo-product-price][data-ome-woo-product-price-value]
SKU[data-ome-woo-product-sku][data-ome-woo-product-sku-value]
Availability[data-ome-woo-product-availability][data-ome-woo-product-availability-value]
Description[data-ome-woo-product-description][data-ome-woo-product-description-value]

[data-ome-woo-product-readout] and [data-ome-woo-product-readout-value] are shared runtime hooks. Do not style internal Provider payload carriers.

Simple product readouts
<OmeWooProductProvider product="{this.omewoo}" styling='{{"class":"product-summary"}}'>
{#slot default}
<OmeWooProductPrice content="{this.omewoo.price.html}" />
<OmeWooProductSku content="{this.omewoo.product.sku}" />
<OmeWooProductAvailability content="{this.omewoo.purchase.availabilityHtml}" />
<OmeWooProductDescription content="{this.omewoo.description.html}" />
{/slot}
</OmeWooProductProvider>

For a variable product, use the same readouts next to the form shown in Quick Start. Attribute selection updates all four atoms before ome-woo:variation-selection-changed is dispatched, so event listeners observe the committed DOM.

Product Cart Quantity

OmeWooProductCartQuantity shows and changes the confirmed quantity already in the cart for the nearest Product Provider's current purchasable identity. It has no product ID or variation ID prop: the Provider is the only target source.

Choose the quantity component by ownership:

ComponentQuantity it ownsWhen the cart changes
OmeWooAddToCartButton in counter modeA local purchase draft for the next Add action.Only when Add to cart is activated. Stepper and + do not mutate the cart.
OmeWooProductCartQuantityThe confirmed cart quantity for the Provider's current simple product or resolved variation.Each valid committed change adds, updates, or removes through the shared Cart Store coordinator.
OmeWooCartItemQuantityOne exact existing cart line owned by a CartItems row.Each valid committed change updates or removes that exact line.

For a simple product, Product Cart Quantity targets the base purchasable ID. For a variable product, it stays unresolved until all required attributes resolve one exact variation; then it targets that variation ID and rebinds when the selection changes. Resetting or partially selecting attributes returns it to unresolved. Nested Providers remain isolated.

Cart matching is intentionally conservative:

  • zero matching lines means confirmed quantity 0; the first valid increase adds the current product or variation;
  • exactly one matching line enables updates to that exact cart item key;
  • multiple matching lines means ambiguous; mutation is disabled and the component never guesses, combines, or distributes quantity across lines.

Use OmeWooCartItemQuantity when extensions intentionally create duplicate or otherwise non-standard cart lines. Matching plugin-defined bundle, composite, add-on, or custom line identity is outside the Product Cart Quantity contract.

Add, Update, And Remove Rules

The default stepper uses Woo's current minimum, maximum, step, managed-stock limit, and sold-individually rule. From zero, increase adds the smallest valid Woo quantity. Above zero, increase and decrease update the exact single line. Decreasing from the minimum valid in-cart quantity removes that line.

The optional input presentation commits on change. An explicit valid committed 0 removes the line. Empty, non-numeric, out-of-range, or off-step input is restored to the confirmed value and never removes anything. Decimal quantities use the same decimal-safe arithmetic as the other Woo quantity controls.

An unavailable or out-of-stock resolved product cannot be increased or newly added. If its line already exists, decrease and removal remain enabled so the customer is not trapped with an uneditable item. When Woo marks that line's quantity as non-editable, decrement removes the line directly instead of attempting an invalid intermediate update.

All mutations reuse the shared Cart Store coordinator, notices, recovery behavior, and semantic cart events. The component does not create a separate scheduler.

Props

PropMeaning
configuration.counter_presentationstepper (default) renders decrease, read-only value, and increase controls. input renders a directly editable number field.
preview.quantityNon-mutating quantity shown only in the Etch editor. Defaults to 1.
content.decrease_label, content.increase_labelVisible stepper button content.
accessibility.decrease_aria_label, increase_aria_label, value_aria_labelAccessible names for both buttons and the quantity value/input.
styling.wrapper_class, input_classClass props for the root control and input presentation.
styling.decrease_button_class, value_class, increase_button_classClass props for individual stepper parts.

The component deliberately exposes no authored target ID and no authored quantity limits. Server-rendered frontend markup starts in a disabled loading state until Provider and Cart Store state are confirmed. Outside a valid Provider it remains disabled and development builds emit one deduplicated guidance warning; production does not throw.

State And Styling Hooks

HookMeaning
[data-ome-woo-product-cart-quantity]Component root.
data-ome-stateloading, unresolved, ready, or ambiguous.
data-ome-selection-phaseProvider selection phase projected independently from cart lifecycle.
data-ome-woo-availableWhether increases/adds are currently allowed.
data-ome-woo-confirmed-quantityLast confirmed cart quantity.
data-ome-woo-mutation-phaseShared coordinator mutation phase, separate from selection and availability.
data-ome-woo-purchasable-idCurrent simple product or resolved variation identity, when available.
data-ome-woo-cart-item-keyExact matching line key, present only when one line matches.
data-ome-woo-quantity-presentationstepper or input.
[data-ome-woo-quantity-decrease], [data-ome-woo-quantity-value], [data-ome-woo-quantity-increase]Shared stepper-part hooks.
input[data-ome-woo-product-cart-quantity-input]Direct input presentation.

Prefer class props for authored visuals and datasets for state-dependent styling. The stepper uses native buttons, a polite live output, boundary disabled states, and visible focus defaults.

AddToCartForm Props

PropMeaning
product.product_idProduct ID. Use {item.id} in product loops and {this.id} on single product templates.
product.product_typeProduct type, such as simple or variable. Use omewoo.product.type from product dynamic data.
product.variation_idOptional fixed variation ID. Usually empty when selectors provide variation state.
availability.unavailableDisables the form when authored or dynamic product availability says the product cannot be bought.
availability.availablePositive availability flag from dynamic data.
availability.stock_statusStock status used by form sync and disabled state.

Runtime blocks submit if the product is unavailable or if a required variable product option has not been selected.

AddToCartButton Props

PropMeaning
behavior.modefixed renders a normal button; counter renders a quantity control plus button.
behavior.counter_presentationinput keeps the released number field. stepper renders decrement, read-only value, and increment parts. Defaults to input and applies only in counter mode.
behavior.triggerstandalone sends its own Store API add request; form_submit submits the parent purchase form.
behavior.product_idRequired for standalone buttons. Ignored by form-submit buttons.
quantity.default, min, max, stepInitial purchase draft and authored limits. An empty maximum is unbounded. In stepper Provider context these values may tighten, but never loosen, Woo limits.
content.labelButton text.
content.successMsgTemporary text after a successful add.
content.decrement_content, increment_contentVisible decrement and increment content in stepper presentation.
accessibility.aria_labelButton accessible label.
accessibility.input_aria_labelAccessible label for the input, or base label for the stepper's read-only value.
accessibility.decrement_aria_label, increment_aria_labelAccessible names for the stepper buttons.
styling.wrapper_class, input_class, button_classCounter wrapper, serialized quantity input, and Add button class props.
styling.decrement_button_class, value_class, increment_button_classStepper part class props.

Purchase Draft Quantity

Counter mode edits a purchase draft. The draft becomes a cart mutation only when the customer activates Add to cart. In stepper presentation, decrement and increment never send Store API requests and never change the cart by themselves. They update the read-only value and the hidden serialized quantity source used by the existing Add action.

Purchase draft stepper
<OmeWooAddToCartButton
behavior='{{"mode":"counter","counter_presentation":"stepper","trigger":"form_submit"}}'
quantity='{{"default":"1","min":"1","max":"","step":"1"}}'
content='{{"decrement_content":"−","increment_content":"+"}}'
accessibility='{{"input_aria_label":"Quantity","decrement_aria_label":"Decrease quantity","increment_aria_label":"Increase quantity"}}'
/>

Use the stepper inside AddToCartForm and the nearest ProductProvider for variable products. The Provider supplies the currently resolved variation's Woo quantity rules. Before all required attributes resolve, customers may edit the base-product draft, but Add remains disabled. Resolving or changing a variation preserves the draft where possible and normalizes it to the selected variation instead of resetting it.

Woo remains authoritative:

  • minimum, maximum, and step come from the current product or variation;
  • finite managed stock limits the maximum when backorders are unavailable;
  • sold-individually products are fixed at 1;
  • authored props may make the range stricter, but cannot permit a quantity Woo rejects;
  • compatible authored and Woo decimal steps combine into values valid on both step grids;
  • unavailable products, incompatible step grids, and contradictory ranges disable the stepper and Add action.

The decrement and increment controls are native button type="button" elements with disabled boundary states and keyboard behavior. The read-only value is a polite live output, so assistive technology can announce changes; the hidden number input remains the canonical serialized quantity. Use these stable hooks for runtime-aware styling or inspection:

PartSelector
Stepper control[data-ome-woo-quantity-control][data-ome-woo-quantity-presentation="stepper"]
Decrement[data-ome-woo-quantity-decrease]
Read-only value[data-ome-woo-quantity-value]
Increment[data-ome-woo-quantity-increase]
Serialized quantityinput[data-ome-woo-product-quantity]

The default stepper parts have approximately 2.75rem touch targets, visible keyboard focus, boundary disabled states, and separate class props. Existing counter components need no migration: a missing or input counter_presentation continues to render the released number input exactly as before.

Successful add-to-cart dispatches ome-woo:item-added, followed by ome-woo:cart-updated; failed add-to-cart dispatches ome-woo:add-to-cart-error. Use Woo Custom Events for post-add integrations such as analytics or mini-cart drawers. data-ome-state="success" is only the control's visible feedback state.

AttributeSelector Props

PropMeaning
target.attributeA full attribute object from omewoo.attributes. It contains key, label, required flag, and options.
behavior.select_first_optionSelects the first available option when nothing is selected.
behavior.unavailable_optionsdisabled keeps unavailable options visible but inactive. hidden removes them from layout, keyboard order, and the accessibility tree. Defaults to disabled.
behavior.show_swatch_labelAdds a supplementary visible label in color/image swatch modes. Defaults to false; the option still has an accessible name.
ui.modeselect, radio, button-radio, color-swatch, or image-swatch. select remains the default.
ui.aria_labelAccessible selector name.
ui.default_labelSelect trigger label before selection.

Each option carries value, label, variation ID, availability, and stock status. Unavailable options are marked disabled and cannot be selected.

Color And Image Swatches

Both swatch modes keep the same UIChoice radiogroup behavior as radio and button-radio: click, Enter, Space, Arrow keys, Home, End, roving tabindex, reset, and variation-form synchronization. Selected options show an outer ring and check badge; unavailable options also use opacity and a strike, so state is not communicated by color alone.

Public state hooks stay on the option item:

StateSelector
Selected[data-ome-ui-choice-item][data-ome-selected="true"]
Disabled[data-ome-ui-choice-item][data-ome-disabled="true"]
Hidden[data-ome-ui-choice-item][hidden]
Keyboard focus[data-ome-ui-choice-item]:focus-visible

Scope these hooks below [data-ome-woo-attribute-selector] when overriding the default ring, strike, hidden state, or focus outline.

data-ome-value is the canonical public mapping hook. Scope storefront CSS to the Woo Attribute Selector so the same option slug in a facet or another UIChoice control is not affected.

Custom color swatch mappings
[data-ome-woo-attribute-selector][data-ome-ui-choice-mode="color-swatch"]
[data-ome-value="forest"] {
--ome-woo-swatch-color: #234f32;
--ome-woo-swatch-fallback-display: none;
}

[data-ome-woo-attribute-selector][data-ome-ui-choice-mode="color-swatch"]
[data-ome-value="warm-white"] {
--ome-woo-swatch-color: #fffdf5;
--ome-woo-swatch-fallback-display: none;
}

[data-ome-woo-attribute-selector][data-ome-ui-choice-mode="color-swatch"]
[data-ome-value="warm-white"] [data-ome-woo-swatch-visual] {
border-color: #777;
}

Always quote the exact slug in the attribute selector, including unusual values such as [data-ome-value="50-50"]. Do not target the translated label or infer a color from a substring. Built-in exact-slug defaults are provided for black, white, gray, grey, red, orange, yellow, green, blue, navy, purple, pink, brown, beige, teal, cyan, magenta, gold, and silver.

Custom image swatch mapping
[data-ome-woo-attribute-selector][data-ome-ui-choice-mode="image-swatch"]
[data-ome-value="suede"] {
--ome-woo-swatch-image: url("/wp-content/uploads/suede-swatch.webp");
--ome-woo-swatch-fallback-display: none;
}

The runtime never reads computed CSS to guess whether a custom mapping resolved. Set --ome-woo-swatch-fallback-display: none only alongside a valid custom color or image. If the mapping is missing, misspelled, or intentionally omitted, leave the variable alone and the honest option text remains visible.

In image-swatch mode, Woo can supply an image automatically only when every variation matching that option owns the same non-zero image. A missing image, different images, or parent-product-only fallback keeps the text fallback visible. The option image is calculated from the complete variation set, so changing another attribute does not make the swatch change unexpectedly.

With behavior.show_swatch_label=false, a resolved swatch has no supplementary label node, but the option label remains its accessible name. Set it to true when visible text below every resolved swatch improves recognition. Fallback text is separate: it remains visible for unresolved swatches regardless of this prop.

Meaningful class props are available for the option, swatch visual, supplementary label, text fallback, and selected indicator. Use those class props for visual presets; keep runtime targeting on data-ome-* attributes.

Existing select, radio, and button-radio authoring remains compatible. The new modes and props are additive, and existing option data paths are retained.

VariationResetButton Props

PropMeaning
content.labelButton text. Defaults to Clear selections.
accessibility.aria_labelOptional accessible label. Defaults to the visible label.
styling.classAdditional class list for the button root.

VariationResetButton must be inside an AddToCartForm. Runtime clears every AttributeSelector in that nearest form, removes selected variation state, and lets the form become invalid naturally. It does not reapply behavior.select_first_option after reset.

BuyNowButton Props

PropMeaning
content.labelButton text.
accessibility.aria_labelOptional accessible label.
checkout.urlAuthored redirect target. If empty, runtime uses the localized Woo checkout URL.

BuyNowButton must be inside an AddToCartForm because it serializes the form payload before redirecting.