# PageHeader

> The top of a page: breadcrumbs or a back link, the page title, a line of description, meta facts and the page's actions at the inline end.

Source: https://docs.nasaqui.com/components/page-header

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/page-header.json
```

The top of a page's content. It shows where the page sits (breadcrumbs or a back link), the page title as the one `h1`, a line of description, a row of meta facts and the page's actions at the inline end. On narrow screens the actions wrap under the title.

## When to use

- At the top of every list, detail and settings page inside `AppMain`.
- When a detail page needs a way back to its list, or a list page needs its primary action beside the title.

## When not to use

- Headings further down the page: use [`SectionHeader`](https://docs.nasaqui.com/components/section-header).
- The app's top bar (search, account, notifications): that is `AppHeader` in [`AppShell`](https://docs.nasaqui.com/components/app-shell).
- Marketing heroes: use the marketing sections.

## Import

```tsx
import { PageHeader } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { Button, PageHeader } from "@fadymondy/nasaq/web";

<PageHeader
  breadcrumbs={[{ label: "Sales", href: "/sales" }, { label: "Customers" }]}
  title="Customers"
  description="Everyone who bought from you or opened an account."
  actions={<Button>New customer</Button>}
/>;
```

## Anatomy

```
header [data-slot=page-header]
├─ nav [data-slot=page-header-breadcrumbs]   (Breadcrumb, when `breadcrumbs`)
├─ a   [data-slot=page-header-back]          (when `backHref` or `onBack`)
└─ div
   ├─ h1  [data-slot=page-header-title]
   ├─ p   [data-slot=page-header-description]
   ├─ div [data-slot=page-header-meta]
   └─ div [data-slot=page-header-actions]    (inline end; wraps below on narrow screens)
```

## API

### `PageHeader`

| Prop | Type | Default | Notes |
| --- | --- | --- | --- |
| `title` | `ReactNode` | — | Required. The page's one heading. |
| `description` | `ReactNode` | — | One or two lines under the title. |
| `breadcrumbs` | `PageHeaderCrumb[]` | — | The last crumb is the current page. |
| `backHref` | `string` | — | Shows a "Back" link above the title. |
| `onBack` | `() => void` | — | Runs instead of following `backHref`, for client-side routers. |
| `meta` | `ReactNode` | — | Small facts under the description: a `Status`, an owner, a date. |
| `actions` | `ReactNode` | — | Usually [`PageActions`](https://docs.nasaqui.com/components/page-actions) or one or two buttons. |
| `as` | `"h1" \| "h2"` | `"h1"` | Heading element. Use `h2` when the shell already owns the `h1`. |
| `labels` | `Partial<PageHeaderLabels>` | — | Overrides the built-in "Back" / "رجوع". |

Plus any `<header>` prop.

### `PageHeaderCrumb`

| Field | Type | Notes |
| --- | --- | --- |
| `label` | `ReactNode` | The crumb text. |
| `href` | `string` | Leave out on the current page. |

## Examples

### Detail page with a back link and meta

```tsx
<PageHeader
  backHref="/customers"
  title="Nour Adel"
  description="Customer since March 2024 · Riyadh"
  meta={
    <>
      <Status tone="success">Active</Status>
      <span>12 orders</span>
    </>
  }
  actions={<PageActions primary={{ id: "crm.customer.edit", label: "Edit", onSelect: edit }} />}
/>
```

### Client-side back

```tsx
const navigate = useNavigate();
<PageHeader onBack={() => navigate({ to: "/customers" })} title="Nour Adel" />;
```

## Accessibility

- The title renders as an `h1` by default, so every page gets one top-level heading.
- Breadcrumbs are a `nav` landmark named "Breadcrumb" / "مسار التنقل"; the current page has `aria-current="page"`.
- The back link is a real link with visible text, not an icon-only button.

## RTL & i18n

Everything uses logical properties: actions sit at the inline end, and the back arrow and breadcrumb chevrons mirror in Arabic. "Back" is built in (English and Arabic); override it with `labels`.

## Styling & tokens

- Title: `text-h1 text-foreground`. Description: `text-body-sm text-muted-foreground`. Meta: `text-caption text-muted-foreground`.
- Target parts with `[data-slot=page-header-*]`.
- Extend spacing with `className`. Do not restyle the title with raw hex.

## Do / Don't

- Do keep the title short: the noun of the page ("Customers", a customer's name).
- Do put one primary action in `actions`; the rest belong behind `PageActions`' menu.
- Don't show both breadcrumbs and a back link; pick the one that fits the depth.
- Don't wrap the header in a card.

## Related

`page-actions`, `breadcrumb`, `section-header`, `app-shell`, `status`.

## Lab

https://docs.nasaqui.com/?path=/docs/components-layout-page-header--docs

## Code

### React

```tsx
import { Button, PageHeader } from "@fadymondy/nasaq/web";

<PageHeader
  breadcrumbs={[{ label: "Sales", href: "/sales" }, { label: "Customers" }]}
  title="Customers"
  description="Everyone who bought from you or opened an account."
  actions={<Button>New customer</Button>}
/>;
```

### shadcn

```tsx
import { Button } from "@/components/ui/button";
import { PageHeader } from "@/components/ui/page-header";

<PageHeader
  breadcrumbs={[{ label: "Sales", href: "/sales" }, { label: "Customers" }]}
  title="Customers"
  description="Everyone who bought from you or opened an account."
  actions={<Button>New customer</Button>}
/>;
```

### Vue

```vue
<script setup lang="ts">
import { NqButton, NqPageHeader } from "@fadymondy/nasaq/vue";
</script>

<template>
  <NqPageHeader
    :breadcrumbs="[{ label: 'Sales', href: '/sales' }, { label: 'Customers' }]"
    title="Customers"
    description="Everyone who bought from you or opened an account."
  >
    <template #actions><NqButton>New customer</NqButton></template>
  </NqPageHeader>
</template>
```

### Blade

```blade
<x-nq::page-header
    :breadcrumbs="[['label' => 'Sales', 'href' => '/sales'], ['label' => 'Customers']]"
    title="Customers"
    description="Everyone who bought from you or opened an account."
>
    <x-slot:actions><x-nq::button>New customer</x-nq::button></x-slot:actions>
</x-nq::page-header>
```

### HTML + Alpine

```html
<header data-slot="page-header" class="flex flex-col gap-3">
            <div data-slot="page-header-breadcrumbs" class="contents"><nav data-slot="breadcrumb" aria-label="Breadcrumb"><ol data-slot="breadcrumb-list" class="flex min-w-0 flex-wrap items-center gap-1.5 text-body-sm text-muted-foreground"><li data-slot="breadcrumb-item" class="inline-flex min-w-0 items-center gap-1.5"><a data-slot="breadcrumb-link" href="/sales" class="truncate rounded-[3px] transition-colors duration-150 ease-nq outline-none hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus">Sales</a></li>
                    <li data-slot="breadcrumb-separator" role="presentation" aria-hidden="true" class="[&_svg]:size-3.5">
            <svg data-slot="icon" aria-hidden="true" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m9 18 6-6-6-6"/>
</svg>    </li>
                                    <li data-slot="breadcrumb-item" class="inline-flex min-w-0 items-center gap-1.5"><span data-slot="breadcrumb-page" aria-current="page" class="truncate text-foreground">Customers</span></li></ol></nav>
</div>
            <div class="flex flex-wrap items-start justify-between gap-x-6 gap-y-3">
        <div class="flex min-w-0 flex-1 basis-80 flex-col gap-1">
            <h1 data-slot="page-header-title" class="text-h1 text-balance text-foreground">Customers</h1>
                            <p data-slot="page-header-description" class="max-w-prose text-pretty text-body-sm text-muted-foreground">Everyone who bought from you or opened an account.</p>
                                </div>
                    <div data-slot="page-header-actions" class="flex shrink-0 flex-wrap items-center gap-2"><button data-slot="button"
     type="button"                         class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        New customer</button></div>
            </div>
</header>
```
