feat(accounts): add initial Account Provider, Gate and Field components - #579
Conversation
|
Updated Since Gate only controls whether children render and does not render its own UI, it now returns children directly instead of introducing a DOM wrapper. This avoids layout/HTML composition issues when Gate is nested inside other components. As a result, the Gate instance itself is no longer styleable in Studio. This is intentional — Gate is treated as a control-flow primitive rather than a visual component, so styling should be applied to the rendered children instead. Also updated the component registration metadata with Additionally, updated invalid Left broader cleanup items ( |
field123
left a comment
There was a problem hiding this comment.
The names in $ctx.account match the session data on master. Some changes must happen before merge, because of ADR-0004 ("registered surfaces are append-only"). This package is published as a hostless bundle. The publish-hostless step rejects a release that removes or renames a registered component, prop, option or $ctx key. After we publish this PR, we can add to that surface, but we cannot change or remove what is there.
Must fix
- The Provider must read the real session. Outside Studio,
resolveAccountContextalways returns anonymous (EPAccountProvider.tsx:46-48). On a published page, ananonymousGate shows the login prompt to a signed-in member. TheauthenticatedandselectedGates never render. The session data is already on master (#534, #568, anduseEpIdentity().getSession()from #569), so this slice can use it. - "authenticated" has two meanings.
state: "authenticated"means a member with no selected account.when="authenticated"means any member (EPAccountGate.tsx:72). Give the state a different name, for examplememberOnly. AccountRef.namemust be optional. The session types on master havename?(EpAccountSummary,envelope.ts).
accountRoster
The key belongs in the Provider, because #563 asks for roster state before the switcher. But the roster is not in the session. It comes from /ep/account/roster as { accounts, total }. It is paged, so total is not the length of accounts. A plain array cannot hold total or a loading state, and ADR-0004 does not let us change the shape later. Use the { accounts, total } shape, or remove the key until the switcher slice. A new key is an addition, so you can add it later at no cost.
Smaller items
- When
previewStateisauto, Checkout shows live data and uses a mock only when no data exists. Hereautoalways shows theselectedmock (EPAccountProvider.tsx:49-50). Match Checkout. - With no Provider, the Gate and Field render nothing in Studio.
EPCartFieldshows mock data in the editor. Do the same. - Under
auto, awhen="anonymous"Gate is hidden in the canvas, so nobody can edit its content. - Remove the unused
classNameprop on the Gate. - Remove the comments and Studio descriptions that describe future work. They will become incorrect.
- Remove the "published contract" test that runs regexes over constant mock data. It cannot fail.
- The Field
stateoption shows the raw value (for exampleselected) as page text. - Move the CHANGELOG entry. Master released the old "Unreleased" section as 0.7.0.
Drafted with AI assistance. Verified before posting.
|
I've updated the slice based on the feedback and verified the flows locally. Verified behaviour:
The contract updates are also in place:
|
…mponents-foundation
…client and hold Gates while loading The Provider fetched a hardcoded /api/ep, so a store that mounts the auth handler elsewhere read every shopper as anonymous. It now uses useEpIdentity(), which takes basePath from ShopperContext, and discards a read made with a previous basePath. $ctx.account was anonymous until the session read settled, so an anonymous Gate showed signed-out content to a signed-in member on first render. isLoading is now published, and Gates render nothing while it is true. The CHANGELOG entry moves out of the section master released as 0.7.0.
Overview
This PR implements the first thin vertical slice of the Accounts component work defined in #563.
The goal of this slice is to establish the foundational Accounts component architecture using the same composable/headless approach as Checkout.
Instead of introducing a single Account Dashboard component, this adds the core building blocks that future Account experiences will compose around:
What this adds
EP Account Provider
Introduces the
$ctx.accountboundary for Account components.Current context shape:
The Provider owns the mapping boundary so future identity/session changes can be absorbed without requiring consuming components to change.
EP Account Gate
Adds conditional rendering based on account state:
EP Account Field
Adds composable access to Account context values.
Currently exposes stable account values:
Member profile fields are intentionally not included until there is a supported runtime source for them.
Studio / Design-time support
Adds
previewStatesupport following the Checkout Provider pattern.Preview states allow Studio users to compose and validate Account experiences without requiring a real authenticated session.
Runtime pages continue to rely on the real account/session integration once connected.
What is intentionally not included
This PR does not implement:
Those will be implemented as follow-up slices on top of this foundation.
Documentation
Added:
Testing
Added tests covering:
Test results: