@vtex/faststore 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/dist/actions.json +181 -0
- package/dist/catalog.json +1673 -484
- package/dist/cli/UnreachableCaseError-Crd168Vu.js +10 -0
- package/dist/cli/UnreachableCaseError-Crd168Vu.js.map +1 -0
- package/dist/cli/cacheControl-CEojH_TM.js +158 -0
- package/dist/cli/cacheControl-CEojH_TM.js.map +1 -0
- package/dist/cli/cachePolicy-m2vASMRW.js +26 -0
- package/dist/cli/cachePolicy-m2vASMRW.js.map +1 -0
- package/dist/cli/computeCoreSchemaHash-DPJZj-qJ.js +10 -0
- package/dist/cli/computeCoreSchemaHash-DPJZj-qJ.js.map +1 -0
- package/dist/cli/default-BCQHcwbL.js +253 -0
- package/dist/cli/default-BCQHcwbL.js.map +1 -0
- package/dist/cli/disableSuggestions-yO9UqiWn.js +21 -0
- package/dist/cli/disableSuggestions-yO9UqiWn.js.map +1 -0
- package/dist/cli/dist-C1JhdHfo.js +2001 -0
- package/dist/cli/dist-C1JhdHfo.js.map +1 -0
- package/dist/cli/graphql-DG9thCDG.js +14589 -0
- package/dist/cli/graphql-DG9thCDG.js.map +1 -0
- package/dist/cli/index.d.ts +350 -0
- package/dist/cli/index.js +35047 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.min-BsIHDfFK.js +613 -0
- package/dist/cli/index.min-BsIHDfFK.js.map +1 -0
- package/dist/cli/inlineTrace-uLgOJ3TH.js +52 -0
- package/dist/cli/inlineTrace-uLgOJ3TH.js.map +1 -0
- package/dist/cli/internalPlugin-DnuwN4_4.js +11 -0
- package/dist/cli/internalPlugin-DnuwN4_4.js.map +1 -0
- package/dist/cli/packageVersion-DQAnIEil.js +6 -0
- package/dist/cli/packageVersion-DQAnIEil.js.map +1 -0
- package/dist/cli/rolldown-runtime-BMI-E3GI.js +44 -0
- package/dist/cli/schemaIsSubgraph-DoGh3OYj.js +17 -0
- package/dist/cli/schemaIsSubgraph-DoGh3OYj.js.map +1 -0
- package/dist/cli/schemaReporting-K-me-3-v.js +199 -0
- package/dist/cli/schemaReporting-K-me-3-v.js.map +1 -0
- package/dist/cli/server-runtime.js +49859 -0
- package/dist/cli/server-runtime.js.map +1 -0
- package/dist/cli/traceTreeBuilder-BIcV2U7b.js +9118 -0
- package/dist/cli/traceTreeBuilder-BIcV2U7b.js.map +1 -0
- package/dist/cli/usageReporting-Bpl8vSZX.js +10201 -0
- package/dist/cli/usageReporting-Bpl8vSZX.js.map +1 -0
- package/dist/cli/v4-CBhFvC49.js +42 -0
- package/dist/cli/v4-CBhFvC49.js.map +1 -0
- package/dist/client.d.ts +2 -1
- package/dist/client.js +2 -1
- package/dist/components.d.ts +32 -9
- package/dist/components.js +35 -14
- package/dist/content-types.json +93 -0
- package/dist/core/dist/define-component.d.ts +37 -0
- package/dist/core/dist/index.d.ts +2 -2
- package/dist/docs/access-code-sign-in.md +1 -1
- package/dist/docs/account-entry-point.md +1 -1
- package/dist/docs/account-menu-identity.md +160 -0
- package/dist/docs/account-menu.md +106 -23
- package/dist/docs/address-summary.md +24 -3
- package/dist/docs/alert-dialog.md +204 -0
- package/dist/docs/avatar.md +103 -0
- package/dist/docs/billing-address.md +284 -0
- package/dist/docs/card-entry.md +250 -0
- package/dist/docs/cardholder-document.md +142 -0
- package/dist/docs/client-preferences-fieldset.md +148 -0
- package/dist/docs/client-preferences.md +2 -1
- package/dist/docs/client-profile-fieldset.md +184 -0
- package/dist/docs/client-profile.md +1 -1
- package/dist/docs/document-field.md +58 -4
- package/dist/docs/field.md +317 -0
- package/dist/docs/form.md +307 -0
- package/dist/docs/identity-edit.md +6 -6
- package/dist/docs/identity-summary.md +5 -5
- package/dist/docs/installments.md +248 -0
- package/dist/docs/my-account-profile.md +2 -1
- package/dist/docs/order-placed-payment-summary.md +138 -0
- package/dist/docs/payment-method-badges.md +232 -0
- package/dist/docs/payment-methods.md +1 -0
- package/dist/docs/payment.md +218 -0
- package/dist/docs/phone-field.md +58 -4
- package/dist/docs/place-order.md +157 -0
- package/dist/docs/product-shelf.md +20 -13
- package/dist/docs/save-card.md +186 -0
- package/dist/docs/saved-cards.md +218 -0
- package/dist/docs/select.md +465 -0
- package/dist/docs/shipping-address.md +110 -258
- package/dist/index.d.ts +5 -2
- package/dist/internal/client.d.ts +3 -1
- package/dist/internal/client.js +4 -2
- package/dist/internal/content.d.ts +2 -2
- package/dist/internal/server.d.ts +4 -1
- package/dist/internal/server.js +4 -1
- package/dist/matter/access-code-sign-in/access-code-sign-in.js +9 -8
- package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
- package/dist/matter/account-access-gate/account-access-gate.js.map +1 -1
- package/dist/matter/account-entry-point/account-entry-point.js +1 -1
- package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
- package/dist/matter/account-menu/account-menu.d.ts +70 -0
- package/dist/matter/account-menu/account-menu.js +201 -9
- package/dist/matter/account-menu/account-menu.js.map +1 -1
- package/dist/matter/account-menu/sign-out-failure.js +50 -0
- package/dist/matter/account-menu/sign-out-failure.js.map +1 -0
- package/dist/matter/account-menu-identity/account-menu-identity.d.ts +21 -0
- package/dist/matter/account-menu-identity/account-menu-identity.js +88 -0
- package/dist/matter/account-menu-identity/account-menu-identity.js.map +1 -0
- package/dist/matter/billing-address/billing-address.d.ts +165 -0
- package/dist/matter/billing-address/billing-address.js +408 -0
- package/dist/matter/billing-address/billing-address.js.map +1 -0
- package/dist/matter/card-entry/card-capture.d.ts +25 -0
- package/dist/matter/card-entry/card-capture.js +25 -0
- package/dist/matter/card-entry/card-capture.js.map +1 -0
- package/dist/matter/card-entry/card-entry.d.ts +120 -0
- package/dist/matter/card-entry/card-entry.js +833 -0
- package/dist/matter/card-entry/card-entry.js.map +1 -0
- package/dist/matter/cardholder-document/cardholder-document.d.ts +45 -0
- package/dist/matter/cardholder-document/cardholder-document.js +70 -0
- package/dist/matter/cardholder-document/cardholder-document.js.map +1 -0
- package/dist/matter/cart/cart.js +1 -1
- package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +77 -0
- package/dist/matter/client-preferences/client-preferences-fieldset.js +299 -0
- package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -0
- package/dist/matter/client-preferences/client-preferences.d.ts +3 -5
- package/dist/matter/client-preferences/client-preferences.js +6 -6
- package/dist/matter/client-preferences/client-preferences.js.map +1 -1
- package/dist/matter/client-profile/client-profile.d.ts +4 -6
- package/dist/matter/client-profile/client-profile.js +9 -6
- package/dist/matter/client-profile/client-profile.js.map +1 -1
- package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -0
- package/dist/matter/client-profile-form/client-profile-fieldset.js +488 -0
- package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -0
- package/dist/matter/identity-edit/identity-edit.js +2 -2
- package/dist/matter/identity-edit/identity-edit.js.map +1 -1
- package/dist/matter/identity-summary/identity-summary.js +3 -2
- package/dist/matter/identity-summary/identity-summary.js.map +1 -1
- package/dist/matter/installments/installments-select.d.ts +42 -0
- package/dist/matter/installments/installments-select.js +167 -0
- package/dist/matter/installments/installments-select.js.map +1 -0
- package/dist/matter/installments/installments.d.ts +58 -0
- package/dist/matter/installments/installments.js +176 -0
- package/dist/matter/installments/installments.js.map +1 -0
- package/dist/matter/installments/use-installments-selection.d.ts +29 -0
- package/dist/matter/installments/use-installments-selection.js +95 -0
- package/dist/matter/installments/use-installments-selection.js.map +1 -0
- package/dist/matter/my-account-profile/my-account-profile.d.ts +3 -0
- package/dist/matter/my-account-profile/my-account-profile.js +6 -5
- package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +63 -0
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +305 -0
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -0
- package/dist/matter/payment/payment-card-capture.d.ts +19 -0
- package/dist/matter/payment/payment-card-capture.js +129 -0
- package/dist/matter/payment/payment-card-capture.js.map +1 -0
- package/dist/matter/payment/payment-controller.d.ts +24 -0
- package/dist/matter/payment/payment-controller.js +108 -0
- package/dist/matter/payment/payment-controller.js.map +1 -0
- package/dist/matter/payment/payment-method-badges.d.ts +57 -0
- package/dist/matter/payment/payment-method-badges.js +192 -0
- package/dist/matter/payment/payment-method-badges.js.map +1 -0
- package/dist/matter/payment/payment.d.ts +89 -0
- package/dist/matter/payment/payment.js +264 -0
- package/dist/matter/payment/payment.js.map +1 -0
- package/dist/matter/payment/use-payment-method-selection.d.ts +302 -0
- package/dist/matter/payment/use-payment-method-selection.js +458 -0
- package/dist/matter/payment/use-payment-method-selection.js.map +1 -0
- package/dist/matter/payment/use-payment-submit-gate.d.ts +111 -0
- package/dist/matter/payment/use-payment-submit-gate.js +144 -0
- package/dist/matter/payment/use-payment-submit-gate.js.map +1 -0
- package/dist/matter/place-order/place-order.d.ts +74 -0
- package/dist/matter/place-order/place-order.js +379 -0
- package/dist/matter/place-order/place-order.js.map +1 -0
- package/dist/matter/product-list/product-list.d.ts +1 -0
- package/dist/matter/product-list/product-list.js.map +1 -1
- package/dist/matter/product-shelf/product-shelf.d.ts +62 -31
- package/dist/matter/product-shelf/product-shelf.js +159 -57
- package/dist/matter/product-shelf/product-shelf.js.map +1 -1
- package/dist/matter/region/region.js +1 -1
- package/dist/matter/region/region.js.map +1 -1
- package/dist/matter/save-card/save-card.d.ts +49 -0
- package/dist/matter/save-card/save-card.js +188 -0
- package/dist/matter/save-card/save-card.js.map +1 -0
- package/dist/matter/saved-cards/saved-cards.d.ts +79 -0
- package/dist/matter/saved-cards/saved-cards.js +388 -0
- package/dist/matter/saved-cards/saved-cards.js.map +1 -0
- package/dist/matter/shipping-address/country-descriptors.js +20 -10
- package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
- package/dist/matter/shipping-address/shipping-address.d.ts +113 -174
- package/dist/matter/shipping-address/shipping-address.js +480 -791
- package/dist/matter/shipping-address/shipping-address.js.map +1 -1
- package/dist/matter/variant-selector/variant-selector.js +1 -1
- package/dist/particles/address-summary/address-summary.d.ts +24 -0
- package/dist/particles/address-summary/address-summary.js +83 -2
- package/dist/particles/address-summary/address-summary.js.map +1 -1
- package/dist/particles/alert-dialog/alert-dialog.d.ts +68 -0
- package/dist/particles/alert-dialog/alert-dialog.js +187 -0
- package/dist/particles/alert-dialog/alert-dialog.js.map +1 -0
- package/dist/particles/avatar/avatar.d.ts +17 -0
- package/dist/particles/avatar/avatar.js +65 -0
- package/dist/particles/avatar/avatar.js.map +1 -0
- package/dist/particles/checkbox/checkbox.d.ts +7 -3
- package/dist/particles/checkbox/checkbox.js +4 -1
- package/dist/particles/checkbox/checkbox.js.map +1 -1
- package/dist/particles/document-field/document-field.d.ts +48 -5
- package/dist/particles/document-field/document-field.js +189 -32
- package/dist/particles/document-field/document-field.js.map +1 -1
- package/dist/particles/field/bound-field-registry.js +52 -0
- package/dist/particles/field/bound-field-registry.js.map +1 -0
- package/dist/particles/field/field.d.ts +116 -0
- package/dist/particles/field/field.js +497 -6
- package/dist/particles/field/field.js.map +1 -1
- package/dist/particles/fieldset/fieldset.js +2 -2
- package/dist/particles/fieldset/fieldset.js.map +1 -1
- package/dist/particles/form/form.d.ts +104 -0
- package/dist/particles/form/form.js +485 -0
- package/dist/particles/form/form.js.map +1 -0
- package/dist/particles/phone-field/phone-field.d.ts +38 -10
- package/dist/particles/phone-field/phone-field.js +183 -39
- package/dist/particles/phone-field/phone-field.js.map +1 -1
- package/dist/particles/postal-code-field/postal-code-field.js +2 -2
- package/dist/particles/postal-code-field/postal-code-field.js.map +1 -1
- package/dist/particles/select/field-select.d.ts +43 -0
- package/dist/particles/select/field-select.js +150 -0
- package/dist/particles/select/field-select.js.map +1 -0
- package/dist/particles/select/select.d.ts +2 -0
- package/dist/particles/select/select.js.map +1 -1
- package/dist/particles/shared/compose-refs.js +21 -0
- package/dist/particles/shared/compose-refs.js.map +1 -0
- package/dist/schema.graphql +766 -28
- package/dist/sdk/actions/analytics-action-provider.d.ts +15 -0
- package/dist/sdk/actions/analytics-action-provider.js +19 -0
- package/dist/sdk/actions/analytics-action-provider.js.map +1 -0
- package/dist/sdk/actions/index.d.ts +3 -1
- package/dist/sdk/actions/index.js +3 -1
- package/dist/sdk/actions/payment-action-provider.d.ts +22 -0
- package/dist/sdk/actions/payment-action-provider.js +26 -0
- package/dist/sdk/actions/payment-action-provider.js.map +1 -0
- package/dist/sdk/actions/types.d.ts +6 -2
- package/dist/sdk/analytics/analytics-destination.d.ts +43 -0
- package/dist/sdk/analytics/analytics-destination.js +90 -0
- package/dist/sdk/analytics/analytics-destination.js.map +1 -0
- package/dist/sdk/analytics/use-analytics-actions.d.ts +57 -0
- package/dist/sdk/analytics/use-analytics-actions.js +109 -0
- package/dist/sdk/analytics/use-analytics-actions.js.map +1 -0
- package/dist/sdk/cart/use-cart-actions.js +10 -9
- package/dist/sdk/cart/use-cart-actions.js.map +1 -1
- package/dist/sdk/cart/use-cart-validate-on-open.js +2 -1
- package/dist/sdk/cart/use-cart-validate-on-open.js.map +1 -1
- package/dist/sdk/content/create-content-runtime.d.ts +22 -1
- package/dist/sdk/content/create-content-runtime.js +89 -1
- package/dist/sdk/content/create-content-runtime.js.map +1 -1
- package/dist/sdk/data/empty-content-value.js +16 -0
- package/dist/sdk/data/empty-content-value.js.map +1 -0
- package/dist/sdk/data/entity-resolution-context.js +31 -0
- package/dist/sdk/data/entity-resolution-context.js.map +1 -0
- package/dist/sdk/data/entity-subscriber.js +18 -8
- package/dist/sdk/data/entity-subscriber.js.map +1 -1
- package/dist/sdk/data/hot-data-provider.js +2 -1
- package/dist/sdk/data/hot-data-provider.js.map +1 -1
- package/dist/sdk/data/index.js +2 -1
- package/dist/sdk/data/page-reactive-data-root.d.ts +36 -0
- package/dist/sdk/data/page-reactive-data-root.js +4 -2
- package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
- package/dist/sdk/data/reactive-data-provider.js +7 -3
- package/dist/sdk/data/reactive-data-provider.js.map +1 -1
- package/dist/sdk/data/reactive-list-item-data-provider.js +12 -4
- package/dist/sdk/data/reactive-list-item-data-provider.js.map +1 -1
- package/dist/sdk/data/use-reactive-data-settled.js +39 -0
- package/dist/sdk/data/use-reactive-data-settled.js.map +1 -0
- package/dist/sdk/data/use-reactive-entity.js +5 -1
- package/dist/sdk/data/use-reactive-entity.js.map +1 -1
- package/dist/sdk/data/variables-from-content.d.ts +43 -0
- package/dist/sdk/data/variables-from-content.js +57 -0
- package/dist/sdk/data/variables-from-content.js.map +1 -0
- package/dist/sdk/generated/fragment-types.js +2 -0
- package/dist/sdk/generated/fragment-types.js.map +1 -1
- package/dist/sdk/generated/gql.js +2 -1
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.js +85 -1
- package/dist/sdk/generated/graphql.js.map +1 -1
- package/dist/sdk/i18n/messages/en-US.js +3 -0
- package/dist/sdk/i18n/messages/en-US.json +3 -0
- package/dist/sdk/i18n/messages/en-US.json.d.ts +3 -0
- package/dist/sdk/i18n/messages/es-ES.js +3 -0
- package/dist/sdk/i18n/messages/es-ES.json +3 -0
- package/dist/sdk/i18n/messages/pt-BR.js +3 -0
- package/dist/sdk/i18n/messages/pt-BR.json +3 -0
- package/dist/sdk/identity/use-identity-actions.js +8 -6
- package/dist/sdk/identity/use-identity-actions.js.map +1 -1
- package/dist/sdk/payment/gateway-origin.js +35 -0
- package/dist/sdk/payment/gateway-origin.js.map +1 -0
- package/dist/sdk/payment/gateway.d.ts +85 -0
- package/dist/sdk/payment/gateway.js +183 -0
- package/dist/sdk/payment/gateway.js.map +1 -0
- package/dist/sdk/payment/operations.d.ts +52 -0
- package/dist/sdk/payment/operations.js +223 -0
- package/dist/sdk/payment/operations.js.map +1 -0
- package/dist/sdk/payment/security-code-mask.js +71 -0
- package/dist/sdk/payment/security-code-mask.js.map +1 -0
- package/dist/sdk/payment/submission-registry.d.ts +33 -0
- package/dist/sdk/payment/submission-registry.js +58 -0
- package/dist/sdk/payment/submission-registry.js.map +1 -0
- package/dist/sdk/payment/use-payment-actions.d.ts +78 -0
- package/dist/sdk/payment/use-payment-actions.js +276 -0
- package/dist/sdk/payment/use-payment-actions.js.map +1 -0
- package/dist/sdk/payment/use-place-order.d.ts +65 -0
- package/dist/sdk/payment/use-place-order.js +640 -0
- package/dist/sdk/payment/use-place-order.js.map +1 -0
- package/dist/sdk/region/use-region-actions.js +2 -1
- package/dist/sdk/region/use-region-actions.js.map +1 -1
- package/dist/sdk/session/read-server-session.d.ts +21 -0
- package/dist/sdk/session/read-server-session.js +61 -0
- package/dist/sdk/session/read-server-session.js.map +1 -0
- package/dist/sdk/session/use-session-actions.js +5 -4
- package/dist/sdk/session/use-session-actions.js.map +1 -1
- package/dist/sdk/session/use-session-revalidation.js +2 -1
- package/dist/sdk/session/use-session-revalidation.js.map +1 -1
- package/dist/sdk/shipping/use-shipping-actions.js +4 -3
- package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
- package/dist/utils/loggable-error-name.js +49 -0
- package/dist/utils/loggable-error-name.js.map +1 -0
- package/dist/utils/resolve-authored-copy.js +18 -0
- package/dist/utils/resolve-authored-copy.js.map +1 -0
- package/dist/utils/safe-href.d.ts +11 -0
- package/dist/utils/substitute-template.js +33 -0
- package/dist/utils/substitute-template.js.map +1 -0
- package/package.json +14 -2
- package/src/styles/tailwind.css +34 -0
- package/dist/docs/client-profile-form.md +0 -192
- package/dist/matter/client-profile-form/client-profile-form.d.ts +0 -126
- package/dist/matter/client-profile-form/client-profile-form.js +0 -662
- package/dist/matter/client-profile-form/client-profile-form.js.map +0 -1
|
@@ -28,12 +28,14 @@ The image is the source of truth for layout.
|
|
|
28
28
|
|
|
29
29
|
## Composition
|
|
30
30
|
|
|
31
|
-
Two parts, and the split is the point. `AccountMenuRoot` is the provider and `AccountMenuList` is the landmark.
|
|
31
|
+
Two parts, and the split is the point. `AccountMenuRoot` is the provider and `AccountMenuList` is the landmark. A third, `AccountMenuIndexRedirect`, is the account root's only content and lives inside the slot. A fourth, `AccountMenuSignOut`, is the sidebar's way out and sits beside the list.
|
|
32
32
|
|
|
33
33
|
```text
|
|
34
34
|
AccountMenuRoot
|
|
35
35
|
├── AccountMenuList
|
|
36
|
+
├── AccountMenuSignOut ← beside the list, outside the landmark
|
|
36
37
|
└── Slot ← the section's own page
|
|
38
|
+
└── AccountMenuIndexRedirect ← on /pvt/account only
|
|
37
39
|
```
|
|
38
40
|
|
|
39
41
|
**The Root wraps the section's content; the landmark does not.** The Root's context has to reach consumers that live inside the slot — the account root's redirect, the sibling breadcrumb — and a context reaches only its descendants. A `<nav>` stretched that far would put every section's content inside a navigation region: a screen reader would announce the page as navigation and "skip to navigation" would skip nothing. So the Root wraps, and the `<nav>` stays around the items alone.
|
|
@@ -58,11 +60,11 @@ Content model (`account-menu`) fields, edited in the CMS:
|
|
|
58
60
|
| `items[].href` | string | yes | Its destination; `http(s)`, `mailto:`, `tel:`, or a site-relative path |
|
|
59
61
|
| `items[].external` | boolean | no | The entry leaves the account; it is never marked current |
|
|
60
62
|
|
|
61
|
-
**The list comes from three channels, in order: a published entry, the authored `items` prop, then the library's five.** The default is Profile, Orders, Address, Payments, and Security, at `/
|
|
63
|
+
**The list comes from three channels, in order: a published entry, the authored `items` prop, then the library's five.** The default is Profile, Orders, Address, Payments, and Security, at `/pvt/profile` and its siblings — the set the PRD names. Presence decides, not emptiness: a channel supplying an empty list resolves to empty rather than falling through, because a merchant who cleared the list cleared it and the defaults must not override a deliberate publication.
|
|
62
64
|
|
|
63
|
-
**The current section is derived, never authored.** The component reads the current path and matches each entry's destination on segment boundaries. At most one entry is current: among the matches, the one with the longest destination wins, which makes an exact match beat every ancestor without a second rule. `/
|
|
65
|
+
**The current section is derived, never authored.** The component reads the current path and matches each entry's destination on segment boundaries. At most one entry is current: among the matches, the one with the longest destination wins, which makes an exact match beat every ancestor without a second rule. `/pvt/order` is not a match for `/pvt/orders` — a prefix that does not land on a segment boundary is not a match at all.
|
|
64
66
|
|
|
65
|
-
**An exact match announces `aria-current="page"`; an ancestor match announces `aria-current="true"`.** Inside `/
|
|
67
|
+
**An exact match announces `aria-current="page"`; an ancestor match announces `aria-current="true"`.** Inside `/pvt/orders/123`, Orders is the current item of its set but not the current page. That claim belongs to the breadcrumb's deep entry, and two surfaces announcing "current page" for two different things is worse than the menu claiming only its set.
|
|
66
68
|
|
|
67
69
|
Two kinds of entry are excluded from the match entirely: one marked `external`, and one whose destination is not site-relative. A destination of `/` is excluded from ancestor matching alone — a root destination is an ancestor of every account path, so a merchant listing the storefront's home beside the sections would otherwise see it current on every page. It still matches the path `/` exactly.
|
|
68
70
|
|
|
@@ -80,6 +82,58 @@ It takes no children: one `<li>` per resolved section is what it renders. With n
|
|
|
80
82
|
|
|
81
83
|
A refused destination keeps its label and loses its anchor, rendering as text under `data-fs-account-menu-text`. A blank label drops the entry outright: an anchor with no accessible name is a WCAG failure.
|
|
82
84
|
|
|
85
|
+
### AccountMenuIndexRedirect
|
|
86
|
+
|
|
87
|
+
Exposed as `AccountMenu.IndexRedirect`. The account's root has no section of its own, and which section is first is the merchant's call, so the root is a page holding this part alone.
|
|
88
|
+
|
|
89
|
+
| Prop | Type | Default | Notes |
|
|
90
|
+
|------|------|---------|-------|
|
|
91
|
+
| `loadingLabel` | string | — | Announced while the first section opens. |
|
|
92
|
+
| `emptyMessage` | string | `'No account section is configured.'` | What the root says when there is no section to open. |
|
|
93
|
+
| `className` | string | — | Applied to whichever element renders. |
|
|
94
|
+
|
|
95
|
+
Content model (`account-menu-index-redirect`) fields, edited in the CMS, each winning over its prop when published; a blank field falls through:
|
|
96
|
+
|
|
97
|
+
| Field | Type | Required | Notes |
|
|
98
|
+
|-------|------|----------|-------|
|
|
99
|
+
| `loadingLabel` | string | no | The waiting announcement |
|
|
100
|
+
| `emptyMessage` | string | no | The no-section message |
|
|
101
|
+
|
|
102
|
+
**It replaces the current history entry with the first section that stays in the account.** It reads the Root's resolved list and skips, in order: an entry marked `external`, a destination the allowlist refused, a destination that is not site-relative even though the merchant did not flag it, and the root itself in any spelling that matches it. Replace, never push: back from the section leaves the account instead of bouncing through its root.
|
|
103
|
+
|
|
104
|
+
**While a destination exists it renders the access gate's loading look**, `AccountAccessGateLoading`, with `data-fs-account-menu-index-redirect` beside the part's own hook. The list itself never loads — the Root resolves it synchronously — so what the look covers is the navigation: the frame before the replace is issued and the time the section takes to land. In the `my-account` layout the gate's own wait for the session comes first, so the shopper sees one look throughout.
|
|
105
|
+
|
|
106
|
+
**With nothing to open, the root is terminal.** A published empty list, or one holding external entries only, navigates nowhere and renders the message instead, under `data-fs-account-menu-index-redirect-empty`. The shell and the sidebar stay. The library's five defaults do not come back: the Root's presence rule is what keeps a published empty list empty, and this part reads the Root's result rather than choosing a channel of its own.
|
|
107
|
+
|
|
108
|
+
It inherits the menu's V0 assumption that public paths carry no binding prefix. Where a store's public base path is its binding id, the root's own entry is not recognized as the current page and the replace targets an unprefixed destination.
|
|
109
|
+
|
|
110
|
+
### AccountMenuSignOut
|
|
111
|
+
|
|
112
|
+
Exposed as `AccountMenu.SignOut`. A button that ends the session and leaves the account for the home page. It reads nothing from the Root, so it works anywhere under the `my-account` layout's gate; the sidebar is where shoppers look for it.
|
|
113
|
+
|
|
114
|
+
| Prop | Type | Default | Notes |
|
|
115
|
+
|------|------|---------|-------|
|
|
116
|
+
| `label` | string | `'Sign out'` | The button's text. |
|
|
117
|
+
| `errorMessage` | string | `"We couldn't sign you out. Please try again."` | Shown when the sign-out did not happen. |
|
|
118
|
+
| `className` | string | — | Applied to the wrapper. |
|
|
119
|
+
|
|
120
|
+
Content model (`account-menu-sign-out`) fields, edited in the CMS, each winning over its prop when published; a blank field falls through:
|
|
121
|
+
|
|
122
|
+
| Field | Type | Required | Notes |
|
|
123
|
+
|-------|------|----------|-------|
|
|
124
|
+
| `label` | string | no | The button's text |
|
|
125
|
+
| `errorMessage` | string | no | The failure message |
|
|
126
|
+
|
|
127
|
+
The component declares `actions: { session: ['logout'] }` and writes only through `$actions.session.logout()`.
|
|
128
|
+
|
|
129
|
+
**It declares the sign-out intent before it awaits the logout.** The logout's payload flips the session to signed out in place, before any navigation can start. A gate that saw that session with no intent would read it as an expired session and send the shopper to sign in for the account they just left. With the intent declared first, the gate stands down — it renders nothing — from the click until the document is gone. The shopper sees the page empty while the request runs; that is the gate's look, not this part's.
|
|
130
|
+
|
|
131
|
+
**Success is a document load of `/`.** It uses `location.assign`, not the router, so no client cache keeps the account behind the back control. What the browser's back-forward cache restores is the gate's to revalidate: it withdraws the intent on a restored page and re-reads the session. This part adds no `pageshow` handling of its own.
|
|
132
|
+
|
|
133
|
+
**Failure keeps the shopper where they are.** When the logout reports any error, rejects, or has no handler to run, the part withdraws the intent, the gate brings the account back, and the message renders under `role="alert"`. A logout that reports an error is a sign-out that did not happen, so the shopper is never sent home still signed in. The failure is held outside the component, because the gate unmounts the part for the length of the attempt and mounts it anew on withdrawal. The next click clears it.
|
|
134
|
+
|
|
135
|
+
**One activation, one logout.** While an attempt runs, a second click neither declares again nor dispatches a second mutation. The button is also disabled and `aria-busy` while any sign-out intent stands, so a second sign-out control on the page stops too.
|
|
136
|
+
|
|
83
137
|
### useAccountMenu()
|
|
84
138
|
|
|
85
139
|
Returns `{ items, current }` — the resolved sections and the current one as `{ index, match }`. It throws outside an `AccountMenuRoot`. This is the contract the account root's redirect and the sibling breadcrumb read, so the two surfaces cannot disagree about which section is current.
|
|
@@ -92,26 +146,45 @@ Returns `{ items, current }` — the resolved sections and the current one as `{
|
|
|
92
146
|
{
|
|
93
147
|
"account-menu": {
|
|
94
148
|
"type": "AccountMenuRoot",
|
|
95
|
-
"children": ["account-menu-list", "account-slot"]
|
|
96
|
-
"style": ["$account-menu"]
|
|
149
|
+
"children": ["account-menu-list", "account-menu-sign-out", "account-slot"]
|
|
97
150
|
},
|
|
98
151
|
"account-menu-list": {
|
|
99
152
|
"type": "AccountMenuList",
|
|
100
|
-
"props": { "label": "Minha conta" }
|
|
101
|
-
|
|
153
|
+
"props": { "label": "Minha conta" }
|
|
154
|
+
},
|
|
155
|
+
"account-menu-sign-out": {
|
|
156
|
+
"type": "AccountMenuSignOut",
|
|
157
|
+
"props": { "label": "Sair", "errorMessage": "Não conseguimos encerrar sua sessão. Tente novamente." }
|
|
102
158
|
}
|
|
103
159
|
}
|
|
104
160
|
```
|
|
105
161
|
|
|
106
162
|
Bound to a CMS entry, the Root authors no `items` at all — the entry supplies the whole list.
|
|
107
163
|
|
|
164
|
+
No part carries a `style` reference: each takes its type's `base` swatch from `global.json → styles` on its own. Reference a named swatch only when the store defines one, since a `$name` the store does not define expands to nothing, without an error.
|
|
165
|
+
|
|
166
|
+
The account root's page, whose only content is the redirect:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"account-index-redirect": {
|
|
171
|
+
"type": "AccountMenuIndexRedirect",
|
|
172
|
+
"props": { "loadingLabel": "Abrindo sua conta…", "emptyMessage": "Nenhuma seção configurada." }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
108
177
|
## Common mistakes
|
|
109
178
|
|
|
110
179
|
- **Placing the Root beside the slot instead of around it.** The layout's own consumers would be satisfied and the page's would not: a context reaches only descendants. Context-constraint validation reports it as a build error rather than as an empty menu at runtime.
|
|
111
180
|
- **Putting the `<nav>` around the section's content.** That is what the two-part split exists to prevent; do not wrap the slot in `AccountMenuList`.
|
|
112
181
|
- **Leaving `label` unauthored.** The default is `Account`; a store with its own wording should say so, because a landmark's name is how a screen-reader user tells it from every other one.
|
|
113
182
|
- **Styling the current item and nothing else.** The hook exists beside `aria-current`, never instead of it. Removing the programmatic signal leaves position conveyed by appearance alone.
|
|
114
|
-
- **Publishing an empty list and expecting the defaults.** Empty is a configuration, not an absence. The account's root then has no section to open.
|
|
183
|
+
- **Publishing an empty list and expecting the defaults.** Empty is a configuration, not an absence. The account's root then has no section to open, and says so.
|
|
184
|
+
- **Placing `AccountMenuIndexRedirect` on a section's page.** It navigates away from whatever page hosts it; it belongs on `/pvt/account` alone.
|
|
185
|
+
- **Putting an external entry first and expecting the root to follow it.** It is skipped, as is an absolute destination left unflagged; the root opens the first section that stays in the account.
|
|
186
|
+
- **Placing `AccountMenuSignOut` outside the gate.** Nothing stands down while the logout runs, so the page shows the signed-out session for the moment before it leaves. Compose it under the `my-account` layout's gate.
|
|
187
|
+
- **Signing out with the router, or adding `pageshow` handling to the control.** The document load is what keeps the account off the back control, and the gate owns the back-forward cache.
|
|
115
188
|
- **Authoring `$content` in the schema.** `$content` is compiler-injected from the page's or layout's content entry; naming it in `props` fails the build.
|
|
116
189
|
- **Expecting the default five to resolve.** Their routes exist only in a store that authored the account's route family; until then the default is correct in the example store alone.
|
|
117
190
|
|
|
@@ -128,37 +201,47 @@ Bound to a CMS entry, the Root authors no `items` at all — the entry supplies
|
|
|
128
201
|
| Current item | `data-fs-account-menu-item-current` marks the current row | `font-semibold` |
|
|
129
202
|
| Link | `data-fs-account-menu-link` is the anchor | `block rounded-md px-3 py-2 text-sm` |
|
|
130
203
|
| Refused text | `data-fs-account-menu-text` replaces the anchor for a refused destination | `block px-3 py-2 text-gray-400` |
|
|
204
|
+
| `AccountMenuIndexRedirect` | `data-fs-account-menu-index-redirect` is on both of its looks; the wait also carries the gate's `data-fs-account-access-gate-loading` | `text-sm text-gray-600` |
|
|
205
|
+
| No-section message | `data-fs-account-menu-index-redirect-empty` marks the terminal state | `flex-1 p-6` |
|
|
206
|
+
| `AccountMenuSignOut` | `data-fs-account-menu-sign-out` is the wrapper; `data-fs-account-menu-sign-out-pending` is on it while a sign-out runs | `flex flex-col gap-2 px-3` |
|
|
207
|
+
| Sign-out button | `data-fs-account-menu-sign-out-button` is the `<button>`; style `:disabled` for the wait | `text-left text-sm underline` |
|
|
208
|
+
| Sign-out failure | `data-fs-account-menu-sign-out-error` is the alert | `text-sm text-red-600` |
|
|
131
209
|
|
|
132
|
-
The vertical-to-horizontal switch and the scroll affordance are one DOM styled two ways,
|
|
210
|
+
The vertical-to-horizontal switch and the scroll affordance are one DOM styled two ways, in CSS alone. A store authors them as `AccountMenuList.base` in `global.json → styles`, abridged here:
|
|
133
211
|
|
|
134
212
|
```json
|
|
135
213
|
{
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"flex",
|
|
139
|
-
"flex-col",
|
|
140
|
-
"gap-6",
|
|
141
|
-
"md:flex-row",
|
|
142
|
-
"md:gap-8",
|
|
214
|
+
"AccountMenuList": {
|
|
215
|
+
"base": [
|
|
143
216
|
"[&_[data-fs-account-menu-items]]:flex",
|
|
144
|
-
"[&_[data-fs-account-menu-items]]:gap-2",
|
|
145
|
-
"[&_[data-fs-account-menu-items]]:overflow-x-auto",
|
|
146
217
|
"md:[&_[data-fs-account-menu-items]]:flex-col",
|
|
147
|
-
"md:[&_[data-fs-account-menu-items]]:overflow-
|
|
148
|
-
"[&_[data-fs-account-menu-
|
|
149
|
-
"[&_[data-fs-account-menu-
|
|
218
|
+
"max-md:[&_[data-fs-account-menu-items]]:overflow-x-auto",
|
|
219
|
+
"max-md:[&_[data-fs-account-menu-items]]:scroll-pe-[32px]",
|
|
220
|
+
"max-md:[&_[data-fs-account-menu-items]]:mask-[linear-gradient(to_right,#000_calc(100%-32px),transparent)]",
|
|
221
|
+
"max-md:[&_[data-fs-account-menu-item]:last-child]:pe-[32px]",
|
|
222
|
+
"[&_[data-fs-account-menu-item]]:shrink-0",
|
|
223
|
+
"[&_[data-fs-account-menu-link]]:whitespace-nowrap",
|
|
224
|
+
"[&_[data-fs-account-menu-link]]:border-transparent",
|
|
225
|
+
"max-md:[&_[data-fs-account-menu-link]]:border-b-2",
|
|
226
|
+
"md:[&_[data-fs-account-menu-link]]:border-l-2",
|
|
227
|
+
"[&_[data-fs-account-menu-item-current]_[data-fs-account-menu-link]]:border-gray-900"
|
|
150
228
|
]
|
|
151
229
|
}
|
|
152
230
|
}
|
|
153
231
|
```
|
|
154
232
|
|
|
155
|
-
The
|
|
233
|
+
- **The masked edge needs space as wide as its fade.** Give the last item a trailing padding and the `<ul>` a `scroll-padding-inline-end` equal to the fade width. Without the padding, a row scrolled to its end leaves the last label under the fade. Without the scroll padding, bringing a current last item into view parks it there.
|
|
234
|
+
- **Reserve the current rule on every link in `transparent`.** Becoming current then changes a color, never a width, so the row does not shift on a route change.
|
|
235
|
+
- **The current-item look reaches the anchor through the row**, since the hook is on the `<li>` and the anchor is its child.
|
|
236
|
+
- **Keep the list's rules off the Root.** The Root wraps the section's content, so a descendant rule there reaches into every page. The Root's own classes and the layout's wrappers place the sidebar beside the section.
|
|
156
237
|
|
|
157
238
|
---
|
|
158
239
|
|
|
159
240
|
## Related
|
|
160
241
|
|
|
161
242
|
- [[account-entry-point]] — the header control that links into the account.
|
|
243
|
+
- [[account-access-gate]] — the loading look the root's redirect reuses, and the gate it runs under.
|
|
244
|
+
- [[account-menu-identity]] — the shopper's name and avatar, composed beside the list inside the Root.
|
|
162
245
|
- [[navigation-link]] — the client-side link each item composes.
|
|
163
246
|
- [[navigation-link-list]] — the general-purpose CMS-driven list this one is patterned on.
|
|
164
247
|
- `BreadcrumbRoot` — the sibling trail that keeps the "current page" claim for the deep page.
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
|-----------|-------|-------|
|
|
18
18
|
| `AddressSummaryRoot` | `address: AddressSummaryFields` (required), `children?: ReactNode` | Provides the address to descendant components via context (no business coupling). Must wrap `AddressSummary` or another presentation component. |
|
|
19
19
|
| `AddressSummary` | `className?: string`, `children?: ReactNode` | Read-only formatted display: recipient name, street/number/complement, neighborhood/city/state/postal code. Lines with no content are omitted. Composed `children` render inside the container in place of the default lines. Must be a descendant of `AddressSummaryRoot`. |
|
|
20
|
+
| `AddressSummaryName` | `className?: string` | The shopper's own label for the address, or nothing when there is none. Not part of the default composition. Must be a descendant of `AddressSummaryRoot`. |
|
|
21
|
+
| `AddressSummaryCountry` | `className?: string` | The address's country, shown exactly as provided, or nothing when there is none. Not part of the default composition. Must be a descendant of `AddressSummaryRoot`. |
|
|
22
|
+
| `AddressSummaryField` | `field: AddressSummaryFieldKey` (required), `className?: string` | One address field, rendered inline (`<span>`), or nothing when it is empty. `field` is one of `recipientName`, `name`, `street`, `number`, `complement`, `neighborhood`, `city`, `state`, `postalCode`, `country`, `reference`. Compose several to build a line in a country's own order, e.g. number before street. Not part of the default composition. Must be a descendant of `AddressSummaryRoot`. |
|
|
20
23
|
|
|
21
24
|
---
|
|
22
25
|
|
|
@@ -32,6 +35,21 @@ or only one of them, composes the leaves instead:
|
|
|
32
35
|
| `AddressSummaryStreet` | street, number, complement | all three absent |
|
|
33
36
|
| `AddressSummaryLocality` | neighborhood, city, state, postal code | all absent |
|
|
34
37
|
|
|
38
|
+
Three more parts compose beside these, none of which join the default: `AddressSummaryName` and
|
|
39
|
+
`AddressSummaryCountry` are whole lines like the leaves above, and `AddressSummaryField` renders a single
|
|
40
|
+
field inline so a consumer can assemble a line in another order — a United States address writes its number
|
|
41
|
+
before its street, which no whole-line part can produce.
|
|
42
|
+
|
|
43
|
+
| Part | Renders | Nothing when |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `AddressSummaryName` | the shopper's own label for the address | no name |
|
|
46
|
+
| `AddressSummaryCountry` | the country, exactly as provided | no country |
|
|
47
|
+
| `AddressSummaryField` | one field, inline (`<span data-fs-address-summary-field="<key>">`) | that field is absent |
|
|
48
|
+
|
|
49
|
+
`AddressSummaryCountry` shows whatever value it is given. The checkout's address stores an ISO alpha-3 code
|
|
50
|
+
(e.g. `BRA`), and `Intl.DisplayNames` rejects alpha-3 codes, so a consumer that wants a country name rather
|
|
51
|
+
than a code converts it before providing the address — this particle has no locale dependency of its own.
|
|
52
|
+
|
|
35
53
|
## Known gaps
|
|
36
54
|
|
|
37
55
|
Found by review and deliberately left for the dedicated revision of these components.
|
|
@@ -41,9 +59,12 @@ Found by review and deliberately left for the dedicated revision of these compon
|
|
|
41
59
|
outside an `AddressSummaryRoot` renders an empty styled block instead of failing loudly, while the
|
|
42
60
|
definition still declares `requiresContext: 'address-summary'` — the declared contract and the runtime
|
|
43
61
|
check no longer agree.
|
|
44
|
-
- **`AddressSummaryRecipient`, `AddressSummaryStreet
|
|
45
|
-
|
|
46
|
-
`
|
|
62
|
+
- **`AddressSummaryRecipient`, `AddressSummaryStreet`, `AddressSummaryLocality`, `AddressSummaryName`,
|
|
63
|
+
`AddressSummaryCountry` and `AddressSummaryField` have no story of their own.** Each is registered in the
|
|
64
|
+
catalog and covered by `address-summary.test.tsx` (the first three also indirectly through
|
|
65
|
+
`shipping-address.test.tsx`), and the three new ones also appear inside `NamedWithCountry` and
|
|
66
|
+
`UsFieldOrder`, but none has the isolated, one-component-per-story coverage the `create-base-component`
|
|
67
|
+
contract asks for.
|
|
47
68
|
|
|
48
69
|
## Extensibility
|
|
49
70
|
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# AlertDialog
|
|
2
|
+
|
|
3
|
+
**Category:** layout
|
|
4
|
+
**Purpose:** Confirmation prompt for an irreversible action. Wraps Base UI's Alert Dialog to give an overlay with the `alertdialog` role that is always modal and never closes on an outside click, so a stray click cannot answer the question. Composed like `Dialog`; the confirm control is a separate `Button`.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Visual cues (how to identify in an image)
|
|
9
|
+
|
|
10
|
+
An AlertDialog is present only when the image shows a **prompt that is already open**: the page behind it is **dimmed**, and a **small centered card** sits over it holding a **question as its heading** (for example "Delete this address?"), **one sentence of consequence**, and **two buttons** side by side, a plain **Cancel** and a **destructive confirm** that is often red.
|
|
11
|
+
|
|
12
|
+
It is an overlay that appears after a click, not a region of the page. A static screenshot of a page rarely contains one, so do not add it "just in case". Compose it only when the image shows the open prompt, or when a design note names a confirmation step.
|
|
13
|
+
|
|
14
|
+
Tell it apart from a `Dialog` by the question: an AlertDialog asks for an answer about something that cannot be undone, and offers no close icon in the corner and no way out except its own buttons. The image is the source of truth for layout.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## When to use
|
|
19
|
+
|
|
20
|
+
- Confirming an **irreversible or destructive** action: deleting a saved address, removing a saved payment method, cancelling an order.
|
|
21
|
+
- Any prompt where **accidentally dismissing it must not count as an answer**: the shopper has to choose Cancel or Confirm, or press Escape on purpose.
|
|
22
|
+
|
|
23
|
+
## When NOT to use
|
|
24
|
+
|
|
25
|
+
- **An informational overlay, a form, or a prompt that a click outside may safely close** — use `Dialog`.
|
|
26
|
+
- **A side panel such as the mini-cart or the mobile menu** — use `Drawer`.
|
|
27
|
+
- **A reversible action** — apply it and offer undo; a confirmation for something that can be undone is friction.
|
|
28
|
+
- **A non-blocking tip or a small anchored panel** — use `Popover` or a non-modal `Dialog`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Composition
|
|
33
|
+
|
|
34
|
+
`AlertDialogRoot` provides the open state to its descendants. The trigger and the portal are its two children; everything visible lives under the portal.
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
AlertDialogRoot
|
|
38
|
+
├── AlertDialogTrigger (sibling of the portal, not inside it)
|
|
39
|
+
└── AlertDialogPortal (teleports its children to <body>)
|
|
40
|
+
├── AlertDialogBackdrop (before the viewport)
|
|
41
|
+
└── AlertDialogViewport (positions the popup)
|
|
42
|
+
└── AlertDialogPopup (the visible prompt, role alertdialog)
|
|
43
|
+
├── AlertDialogTitle (required)
|
|
44
|
+
├── AlertDialogDescription (the consequence)
|
|
45
|
+
├── AlertDialogClose (Cancel)
|
|
46
|
+
└── Button (the confirm control)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Composition rules:**
|
|
50
|
+
|
|
51
|
+
- `AlertDialogBackdrop` comes before `AlertDialogViewport`, both as direct children of the portal.
|
|
52
|
+
- `AlertDialogTitle` is required: it is the prompt's accessible name.
|
|
53
|
+
- **Focus starts on the first focusable element in the popup, except on touch.** Put the Cancel control first among the popup's children so the safe action is the default for a mouse or the keyboard. When the prompt is opened by touch, Base UI focuses the popup itself instead, which keeps the virtual keyboard from opening on Android. Cancel is not focused there, and neither is a destructive control. A schema cannot change that: only code can pass `initialFocus`, which gives Cancel the focus for every kind of interaction. Focus order follows the children order; the layout classes decide where each button appears.
|
|
54
|
+
- The confirm control is a plain `Button`. The particle has no confirm part and runs no action: whatever the confirmation does is wired by the component that owns the prompt, not by the schema.
|
|
55
|
+
- Child order reflects visual order, apart from the focus rule above.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Components
|
|
60
|
+
|
|
61
|
+
### AlertDialogRoot
|
|
62
|
+
|
|
63
|
+
Provides the open state. Context-only: it renders no element of its own and takes no `className`, so it has no styling surface.
|
|
64
|
+
|
|
65
|
+
No schema props. Components that open the prompt from code can control it with `open`, `defaultOpen`, and `onOpenChange` (the same signature as `Dialog`). There is **no `modal` prop**: an alert dialog is always modal.
|
|
66
|
+
|
|
67
|
+
### AlertDialogTrigger
|
|
68
|
+
|
|
69
|
+
The button that opens the prompt. Direct child of `AlertDialogRoot`. Accepts any children.
|
|
70
|
+
|
|
71
|
+
No props.
|
|
72
|
+
|
|
73
|
+
### AlertDialogPortal
|
|
74
|
+
|
|
75
|
+
Teleports its children to `<body>`. Context-only: no element of its own and no `className`.
|
|
76
|
+
|
|
77
|
+
No props.
|
|
78
|
+
|
|
79
|
+
### AlertDialogBackdrop
|
|
80
|
+
|
|
81
|
+
The dimmed layer behind the popup. Clicking it does **not** close the prompt.
|
|
82
|
+
|
|
83
|
+
No props.
|
|
84
|
+
|
|
85
|
+
### AlertDialogViewport
|
|
86
|
+
|
|
87
|
+
A positioning container for the popup. Where the fixed positioning and centering go.
|
|
88
|
+
|
|
89
|
+
No props.
|
|
90
|
+
|
|
91
|
+
### AlertDialogPopup
|
|
92
|
+
|
|
93
|
+
The visible prompt, with `role="alertdialog"`. Holds the title, the description, the cancel control, and the confirm control.
|
|
94
|
+
|
|
95
|
+
No schema props. Code can pass `initialFocus` and `finalFocus` (a ref, a boolean, or a function) to choose where focus lands on open and on close. `initialFocus` is the only way to put focus on Cancel when the prompt is opened by touch, since the default there is the popup itself. Both take a ref, so a schema cannot express them: put Cancel first among the children, which covers a mouse and the keyboard.
|
|
96
|
+
|
|
97
|
+
### AlertDialogTitle
|
|
98
|
+
|
|
99
|
+
The prompt's heading, an `<h2>`. Required for the accessible name. State the question.
|
|
100
|
+
|
|
101
|
+
No props.
|
|
102
|
+
|
|
103
|
+
### AlertDialogDescription
|
|
104
|
+
|
|
105
|
+
A paragraph read out with the prompt. State the consequence of confirming.
|
|
106
|
+
|
|
107
|
+
No props.
|
|
108
|
+
|
|
109
|
+
### AlertDialogClose
|
|
110
|
+
|
|
111
|
+
Closes the prompt. Use it for the Cancel control. Several can appear.
|
|
112
|
+
|
|
113
|
+
No props.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Canonical schema example
|
|
118
|
+
|
|
119
|
+
A delete-address confirmation. The confirm `Button` is inert here: in a store, the matter that owns the destructive action wires it.
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"delete-prompt": { "type": "AlertDialogRoot", "children": ["delete-trigger", "delete-portal"] },
|
|
124
|
+
"delete-trigger": {
|
|
125
|
+
"type": "AlertDialogTrigger",
|
|
126
|
+
"props": { "children": "Delete address" },
|
|
127
|
+
"style": ["px-[16px]", "py-[8px]", "text-[14px]", "font-medium", "text-[#B42318]", "border", "border-[#FDA29B]", "rounded-[6px]"]
|
|
128
|
+
},
|
|
129
|
+
"delete-portal": { "type": "AlertDialogPortal", "children": ["delete-backdrop", "delete-viewport"] },
|
|
130
|
+
"delete-backdrop": { "type": "AlertDialogBackdrop", "style": ["fixed", "inset-0", "bg-black/40"] },
|
|
131
|
+
"delete-viewport": {
|
|
132
|
+
"type": "AlertDialogViewport",
|
|
133
|
+
"style": ["fixed", "inset-0", "flex", "items-center", "justify-center", "p-[16px]"],
|
|
134
|
+
"children": ["delete-popup"]
|
|
135
|
+
},
|
|
136
|
+
"delete-popup": {
|
|
137
|
+
"type": "AlertDialogPopup",
|
|
138
|
+
"style": ["flex", "flex-col", "gap-[8px]", "w-full", "max-w-[448px]", "p-[24px]", "bg-white", "rounded-[12px]", "shadow-xl"],
|
|
139
|
+
"children": ["delete-title", "delete-description", "delete-actions"]
|
|
140
|
+
},
|
|
141
|
+
"delete-title": {
|
|
142
|
+
"type": "AlertDialogTitle",
|
|
143
|
+
"props": { "children": "Delete this address?" },
|
|
144
|
+
"style": ["text-[18px]", "font-semibold", "text-[#101828]"]
|
|
145
|
+
},
|
|
146
|
+
"delete-description": {
|
|
147
|
+
"type": "AlertDialogDescription",
|
|
148
|
+
"props": { "children": "It stops being offered at checkout. This cannot be undone." },
|
|
149
|
+
"style": ["text-[14px]", "text-[#667085]"]
|
|
150
|
+
},
|
|
151
|
+
"delete-actions": {
|
|
152
|
+
"type": "Container",
|
|
153
|
+
"style": ["flex", "justify-end", "gap-[12px]", "mt-[16px]"],
|
|
154
|
+
"children": ["delete-cancel", "delete-confirm"]
|
|
155
|
+
},
|
|
156
|
+
"delete-cancel": {
|
|
157
|
+
"type": "AlertDialogClose",
|
|
158
|
+
"props": { "children": "Cancel" },
|
|
159
|
+
"style": ["px-[16px]", "py-[8px]", "text-[14px]", "font-medium", "text-[#344054]", "border", "border-[#D0D5DD]", "rounded-[6px]"]
|
|
160
|
+
},
|
|
161
|
+
"delete-confirm": {
|
|
162
|
+
"type": "Button",
|
|
163
|
+
"props": { "children": "Delete" },
|
|
164
|
+
"style": ["px-[16px]", "py-[8px]", "text-[14px]", "font-medium", "text-white", "bg-[#D92D20]", "rounded-[6px]"]
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Common mistakes
|
|
172
|
+
|
|
173
|
+
- **`AlertDialogContent`, `AlertDialogHeader`, `AlertDialogFooter`, `AlertDialogAction`, or `AlertDialogCancel`.** None exist. The prompt is `AlertDialogPopup`, Cancel is `AlertDialogClose`, and the confirm control is a plain `Button`.
|
|
174
|
+
- **Looking for a `modal` prop, or a way to close on a backdrop click.** An alert dialog is always modal and ignores outside clicks. Use `Dialog` if the overlay should close on one.
|
|
175
|
+
- **Leaving out `AlertDialogTitle`.** The prompt then has no accessible name.
|
|
176
|
+
- **Putting the confirm `Button` first.** With a mouse or the keyboard, focus starts on the first focusable element, so a destructive control first makes Delete the default. Put Cancel first. On touch, focus starts on the popup itself either way.
|
|
177
|
+
- **Putting `AlertDialogTrigger` inside `AlertDialogPortal`.** The trigger is a child of the root, beside the portal.
|
|
178
|
+
- **Styling `AlertDialogRoot` or `AlertDialogPortal`.** They render no element and take no `style`. Style the backdrop, the viewport, and the popup.
|
|
179
|
+
- **Expecting the schema to run the deletion.** A `Button` in a schema is inert; the owning component wires the confirm action.
|
|
180
|
+
- **Using it for anything reversible or merely informational.** That is a `Dialog`.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Styling
|
|
185
|
+
|
|
186
|
+
| Component | What you style | Plausible classes |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| `AlertDialogTrigger` | The button that opens the prompt | `px-[16px] py-[8px] text-[14px] font-medium text-[#B42318] border border-[#FDA29B] rounded-[6px]` |
|
|
189
|
+
| `AlertDialogBackdrop` | The dimmed layer over the page | `fixed inset-0 bg-black/40` |
|
|
190
|
+
| `AlertDialogViewport` | Fixed positioning and centering of the popup | `fixed inset-0 flex items-center justify-center p-[16px]` |
|
|
191
|
+
| `AlertDialogPopup` | The card: layout, background, radius, shadow, and its enter and exit | `flex flex-col gap-[8px] w-full max-w-[448px] p-[24px] bg-white rounded-[12px] shadow-xl data-[starting-style]:opacity-0 data-[ending-style]:opacity-0` |
|
|
192
|
+
| `AlertDialogTitle` | The question | `text-[18px] font-semibold text-[#101828]` |
|
|
193
|
+
| `AlertDialogDescription` | The consequence line | `text-[14px] text-[#667085]` |
|
|
194
|
+
| `AlertDialogClose` | The Cancel control | `px-[16px] py-[8px] text-[14px] font-medium text-[#344054] border border-[#D0D5DD] rounded-[6px]` |
|
|
195
|
+
|
|
196
|
+
`AlertDialogRoot` and `AlertDialogPortal` have no styling surface. Base UI sets `data-open`, `data-closed`, `data-starting-style`, and `data-ending-style` on the popup and the backdrop, so enter and exit animations key on those attributes.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Related
|
|
201
|
+
|
|
202
|
+
- `Dialog` — the general overlay, which a click outside may close. Use it for forms and information; use AlertDialog when the answer matters.
|
|
203
|
+
- `Drawer` — a side panel for the mini-cart and the mobile menu, not a confirmation.
|
|
204
|
+
- `Button` — the confirm control inside the popup.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Avatar
|
|
2
|
+
|
|
3
|
+
**Category:** content
|
|
4
|
+
**Purpose:** A person or account marker: an image with an initials fallback derived from a name. It carries no account data of its own.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Visual cues (how to identify in an image)
|
|
9
|
+
|
|
10
|
+
- A small circle, usually 32–48px, holding one or two capital letters — `JD`, `A` — on a flat tinted background.
|
|
11
|
+
- Or the same circle holding a round photo of a person.
|
|
12
|
+
- It sits beside a person's name, in a comment, a profile header, or an account sidebar.
|
|
13
|
+
|
|
14
|
+
The image is the source of truth for layout.
|
|
15
|
+
|
|
16
|
+
## When to use
|
|
17
|
+
|
|
18
|
+
- Wherever a person or account needs a compact visual marker beside their name.
|
|
19
|
+
- When there may be no photo: the initials are the fallback, not a separate component.
|
|
20
|
+
|
|
21
|
+
## When NOT to use
|
|
22
|
+
|
|
23
|
+
- For a product or content image → use `Image`.
|
|
24
|
+
- For a status or count label → use `Badge`.
|
|
25
|
+
- For a logo → use `Logo`.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Composition
|
|
30
|
+
|
|
31
|
+
`Avatar` is a leaf. It renders one `<span>` holding the image, when there is one, and the initials fallback. It has no children and requires no ancestor.
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Container
|
|
35
|
+
└── Avatar
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Components
|
|
41
|
+
|
|
42
|
+
### Avatar
|
|
43
|
+
|
|
44
|
+
| Prop | Type | Default | Notes |
|
|
45
|
+
|------|------|---------|-------|
|
|
46
|
+
| `name` | string | — | Whose avatar this is. The initials derive from it: the first letters of the first and last words, or one letter for a single word. |
|
|
47
|
+
| `src` | string | — | Image URL. Absent or empty, the initials show. |
|
|
48
|
+
| `alt` | string | — | Accessible name. Without it the avatar is decorative and hidden from assistive technology. |
|
|
49
|
+
|
|
50
|
+
The fallback shows whenever there is no image, the image is still loading, or it failed to load. The image replaces it only once it has loaded.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Canonical schema example
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"shopper-avatar": {
|
|
59
|
+
"type": "Avatar",
|
|
60
|
+
"props": { "name": "Jane Doe", "alt": "Jane Doe" },
|
|
61
|
+
"style": ["inline-flex", "size-10", "items-center", "justify-center", "rounded-full", "bg-gray-200", "text-sm", "font-medium"]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Common mistakes
|
|
67
|
+
|
|
68
|
+
- **Leaving `alt` off a standalone avatar.** Without `alt` it is hidden from assistive technology, which is right beside text that already names the person and wrong anywhere else. Give it an `alt`.
|
|
69
|
+
- **Giving it an `alt` beside the person's name.** The name is then announced twice.
|
|
70
|
+
- **Expecting a photo from `name` alone.** `name` only derives initials; a photo needs `src`.
|
|
71
|
+
- **Inventing `ProfilePicture` or `UserIcon`.** The component is `Avatar`.
|
|
72
|
+
- **Styling without a size and shape.** The particle ships no look: give it a size, `rounded-full`, and overflow hidden, or the image and initials render unconstrained.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Styling
|
|
77
|
+
|
|
78
|
+
| Component | What you style | Plausible classes |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `Avatar` | `data-fs-avatar` is the circle: size, shape, background, and the initials' type | `inline-flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-full bg-[#E5E7EB] text-[14px] font-medium` |
|
|
81
|
+
| Image | `data-fs-avatar-image` is the `<img>` once loaded | `size-full object-cover` |
|
|
82
|
+
| Initials | `data-fs-avatar-fallback` is the initials span | `uppercase` |
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"shopper-avatar": {
|
|
87
|
+
"type": "Avatar",
|
|
88
|
+
"props": { "name": "Jane Doe", "alt": "Jane Doe" },
|
|
89
|
+
"style": [
|
|
90
|
+
"inline-flex", "size-10", "shrink-0", "items-center", "justify-center", "overflow-hidden",
|
|
91
|
+
"rounded-full", "bg-[#E5E7EB]", "text-[14px]", "font-medium", "[&_img]:size-full", "[&_img]:object-cover"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Related
|
|
100
|
+
|
|
101
|
+
- [[badge]] — a status or count label; distinct from a person marker.
|
|
102
|
+
- `Image` — a content image with no fallback or initials.
|
|
103
|
+
- [[account-menu-identity]] — the account sidebar's name-and-avatar block, which composes `Avatar`.
|