AddressBook
A searchable, paged address book.
import { AddressBook } from "@evolve-storefront/commerce-ui/address-book";Renders inside AddressConfigProvider.
Design notes
For the case a picker cannot serve: a book with more addresses than a page. A radio list is right for the two or three a private shopper keeps and wrong for the sixty-six a company keeps — at that size the list is not a choice, it is a haystack, and the only usable control is a search box over a server query.
So searching and paging are the caller's round trips and this component filters nothing. That is not indirection: the set is too large to hold client-side, which is the entire reason this exists rather than the picker.
Rows are buttons rather than radios. A radio group's whole value is comparing the options at a glance, which is exactly what stops being possible here — and a picked address usually closes the surface this is in, so there is no group left to compare.
Preview
Usage
Search and paging wired to a stand-in query.
const { data, isPending } = useCompanyAddresses({ searchTerm, page });
<AddressBook addresses={data?.items ?? []} pagination={data?.pagination} searchTerm={searchTerm} onSearchTermChange={setSearchTerm} onPageChange={setPage} onSelect={pick} isPending={isPending}/>Props
| Prop | Type | Description |
|---|---|---|
addresses | readonly AddressBookEntry[] | The addresses on this page. The caller owns the query, so searching and paging are its round trips, not this component's filtering. |
onPageChange | (page: number) => void | |
onSearchTermChange | (searchTerm: string) => void | |
onSelect | (id: string) => void | An address was picked. |
pagination? | Pagination | null | Where this page sits in the full set. Omit while the first query is still in flight; the pager renders nothing when there is nowhere to go. |
searchTerm? | string | The term the caller is querying with. Controlled, because the query owns it. |
selectedId? | string | The picked one, where the caller knows which. Marks it, nothing more. |
isPending? | boolean | A query is in flight: the list dims and the rows stop responding. |
addAction? | ReactNode | An action beside the count — "Add address", the app's own. A slot rather than a prop because writing the address book is an account mutation, and this package cannot know whose. |
emptyState? | ReactNode | Shown instead of the list when the search matched nothing. |
searchThreshold? | number | Hide the search field while the whole book holds fewer addresses than this and no search is running: two addresses need no search. Omit to always show it. |
Any other props go to the root element, like on a plain HTML element.
Loading and empty states
Render these while the data loads or when there is nothing to show, so the page does not jump when it arrives.
| Loading | AddressBookSkeleton | Placeholder rows at the real card's height, so nothing reflows on the first page. |

