Skip to content

AccountShell

Optional, thin account layout: a permission-gated section menu + logout beside the section content. Overridable — the app can supply its own layout instead and just render the feature views. Business mode gates items on the buyer's permissions (never role names). From md the menu sticks --account-shell-nav-top (default 1rem) below the top of the viewport, set to clear a pinned header, and scrolls on its own when it is taller than the room.

import { AccountShell } from "@evolve-storefront/feature-account/account-shell";

Renders inside AccountProvider.

Preview

ConsumerOpen in Storybook ↗

Usage

Consumer: permission-gated items are hidden (no permissions held).

const items: AccountNavItem[] = [
{ key: "profile", label: t("profile"), href: "/account" },
{ key: "addresses", label: t("addresses"), href: "/account/addresses" },
];
<AccountShell items={items} activeKey="profile" onLogout={() => logout.mutate()}>
<AccountProfile customer={customer} />
</AccountShell>;

Props

PropTypeDescription
itemsAccountNavItem[]
childrenReactNode

The section content (each feature's view).

groups?AccountNavGroup[]

The menu's groups, in order. Items without a group come first; a group with no item the buyer may see is left out. Omit for a flat menu.

activeKey?string

The active section key — sets aria-current on the matching item.

onLogout?(() => void)

Wire the app's logout. Omit to hide the logout control.

renderLink?((item: AccountNavItem, props: LinkRenderProps) => ReactNode)

Render a nav link with the app's router (e.g. Next Link). Defaults to a plain <a href> — the shell references routes but owns no routing.

Any other props go to the root element, like on a plain HTML element.

Examples

Business All PermissionsBusiness buyer holding both gated permissions — all items visible.
const items: AccountNavItem[] = [
{ key: "profile", label: t("profile"), href: "/account" },
// Shown only when the buyer holds every listed permission.
{ key: "invoices", label: t("invoices"), href: "/account/invoices", permissions: ["VIEW_INVOICES"] },
];
<AccountProvider mode="business" isAuthenticated permissions={buyer.permissions}>
<AccountShell items={items}>{children}</AccountShell>
</AccountProvider>;
Open in Storybook ↗
Business Grouped By TaskA business menu grouped by task: ordering, after the order, the company, and the buyer.
const items: AccountNavItem[] = [
{ key: "carts", label: t("carts"), href: "/account/carts", group: "ordering" },
{ key: "orders", label: t("orders"), href: "/account/orders", group: "after-order" },
{ key: "users", label: t("users"), href: "/account/users", group: "company", permissions: ["MANAGE_USERS"] },
{ key: "profile", label: t("profile"), href: "/account", group: "you" },
];
// The shipped task groups; leave an item out until its feature exists.
const groups = [{ key: "ordering" }, { key: "after-order" }, { key: "company" }, { key: "you" }];
<AccountShell items={items} groups={groups}>{children}</AccountShell>;
Open in Storybook ↗
Business Any OfanyPermissions shows an item when the buyer holds one of several: orders for a buyer who may see their colleagues' orders but not place their own.
const items: AccountNavItem[] = [
// Shown when the buyer holds at least one of these.
{ key: "orders", label: t("orders"), href: "/account/orders", anyPermissions: ["VIEW_MY_ORDERS", "VIEW_OTHERS_ORDERS"] },
];
<AccountProvider mode="business" isAuthenticated permissions={buyer.permissions}>
<AccountShell items={items}>{children}</AccountShell>
</AccountProvider>;
Open in Storybook ↗
With Router LinksrenderLink hands each item to the app's router; the shell owns no routing.
<AccountShell
items={items}
activeKey={activeKey}
renderLink={(item, props) => (
<Link href={item.href} {...props}>{item.label}</Link>
)}
>
{children}
</AccountShell>;
Open in Storybook ↗