Skip to content
Twilight React Playground
ثيم رائدaren

CustomerLayout

componentAdvancedserverbrowser

The account area's frame: a breadcrumb band, the account menu sidebar and the page title around each account page.

import { CustomerLayout } from '@salla.sa/twilight-theme-engine/components/layout';

In plain words

The customer's account area (orders, wishlist, wallet, profile) has a frame of its own inside the store's frame: a coloured band with breadcrumbs, a side menu of the account pages, and the page title above the content. CustomerLayout is that frame, and the engine's generated account route already puts every account page inside it.

Signature

const CustomerLayout: LazyExoticComponent<(props: CustomerLayoutProps) => JSX.Element>

// CustomerLayoutProps is not exported
interface CustomerLayoutProps {
  children: ReactNode;
  page?: Page;   // the account page's loader data: title, slug, breadcrumbs
}

Example

app/components/ReturnsPage.tsx
import { useMemo } from 'react';
import { CustomerLayout } from '@salla.sa/twilight-theme-engine/components/layout';
import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
import type { Page } from '@salla.sa/twilight-theme-engine/types';
import { ReturnsList } from './ReturnsList';

// A page of your own that sits in the account frame, like the engine's account pages.
export function ReturnsPage() {
  const { t } = useTranslation();
  const page = useMemo<Page>(
    () => ({
      title: t('pages.returns.title', 'Returns'),
      slug: 'returns',
      breadcrumbs: [
        { name: t('common.titles.home'), url: '/' },
        { name: t('pages.returns.title', 'Returns'), url: '/returns' },
      ],
    }),
    [t]
  );

  return (
    <CustomerLayout page={page}>
      <ReturnsList />
    </CustomerLayout>
  );
}

How it behaves

  • Layout: a profile-header gradient-bg band with Breadcrumb when page is given; a sidebar with Salla's inline user menu (wide screens only) and, on the profile page, an avatar upload; then the content column with page.title as an <h1> above the children.

  • The engine's account layout route renders it around every /account/… page, with page taken from the deepest matched route's loader data. That route file is generated inside the engine package (.twilight/account.tsx), not in your app/routes, so a theme cannot edit it. Its loading state is CustomerLayoutSkeleton, unless a component is registered under account:layout-pending.

  • It renders inside the store frame (MasterLayout), not instead of it.

  • Account pages need a logged-in customer, so Built-in pages sends a guest to log in rather than showing it.

  • It is lazy (code-split).

Gotchas

  • The avatar upload appears only when page.slug is exactly profile, the slug the engine's profile loader sets. A profile page of your own with another slug gets no avatar upload.

Related

Source and docs