Skip to content
Brok UI

Loading…

No results

Page Header

Open source

The first line of every admin screen — title, a scope line the host can rewrite in place, an optional count badge, and a wrapping action cluster.

Version
v1.0.2
Stability
stable
License
MIT
Related
Record Header
Kpi Strip
List Toolbar

Preview

Customers

Everyone who has ordered from, registered with, or been added to this store.

previews.components.admin-page-header.default.blade.php Blade
<div class="w-full">
    <x-ui.admin.page-header />
</div>

Installation

terminal
php artisan ui:add admin-page-header

Registry contract

php artisan ui:add admin-page-header writes only the files below. The CLI validates each file hash before writing and asks before it replaces a local change, unless you pass --force.

  • blade resources/views/components/ui/admin/page-header.blade.php
Registry dependencies
button badge
Packages
composer: jml/brok:^0.2

Use with AI

A brief for your coding agent: install command, usage, props, guidance and the rules. Copy it, or open a prompt about this component in an assistant.

admin-page-header.md
# Brok UI: Page Header (`admin-page-header`)

The first line of every admin screen — title, a scope line the host can rewrite in place, an optional count badge, and a wrapping action cluster.

Brok UI is a Laravel Blade component registry. Installed components are plain Blade files the app owns.

## Install

```bash
php artisan ui:add admin-page-header
```

## Usage

```blade
<div class="w-full">
    <x-ui.admin.page-header />
</div>
```

## Props

- `title` (string, default `Customers`) — The page title.
- `scope` (string|false|null, default `null`) — A sentence describing what the page covers. `null` renders a sample sentence for the preview; `false` renders none.
- `count` (int|string|null, default `null`) — A count badge beside the title.
- `countLabel` (string|null, default `null`) — Badge text when `count` is set; defaults to the bare count.
- `eyebrow` (string|null, default `null`) — A small uppercase line above the title (a module or section name).
- `as` ('h1'|'h2', default `h1`) — Heading level of the title.

## Use when

- Use to structure hierarchy, spacing, and responsiveness so content is easier to scan and navigate.
- Every admin list, record and form page: it fixes where the title, the scope sentence and the page-level actions sit.
- A list that refreshes in place must update its scope sentence — target `[data-slot="page-header-scope"]`.

## Avoid when

- Do not let layout primitives substitute for semantics, headings, or interaction rules users still need.
- A marketing section heading — use `section-heading`.
- A record edit screen whose header must stay sticky with save state — use `admin-record-header`.

## Anti-patterns

- Using visual layout as a substitute for semantic structure

## Rules

- Use the `<brok:admin-page-header>` tag (or `<x-ui.admin-page-header>`) in Blade; do not rewrite the component.
- Prefer the documented props and variants over utility-class overrides; when a utility must win, use the `!` important modifier.
- Use semantic design tokens (`bg-primary`, `text-muted-foreground`), never raw colour utilities.
- Keep the `data-slot` attributes; they are the styling and test hooks.

## Links

- Docs: https://brokui.dev/docs/components/admin-page-header
- Registry JSON (files, props, contract): https://brokui.dev/r/open/admin-page-header.json

Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.

API

manifest knowledge + registry-derived coverage

Props

Props accepted by this component: name, type, default value and description.
Prop Type Default Description
title string Customers The page title.
scope string | false | null null A sentence describing what the page covers. `null` renders a sample sentence for the preview; `false` renders none.
count int | string | null null A count badge beside the title.
countLabel string | null null Badge text when `count` is set; defaults to the bare count.
eyebrow string | null null A small uppercase line above the title (a module or section name).
as 'h1' | 'h2' h1 Heading level of the title.

Slots

  • actions — The page-level action cluster (create, import, shortcut chips). A sample Import/New pair renders when omitted.

Renders as h1, h2.

Data slots

Stable hooks for CSS overrides and browser tests.

page-header page-header-actions page-header-count page-header-eyebrow page-header-scope page-header-title

Behavior

  • The actions cluster is `min-w-0 flex-wrap`, so it wraps under the title on a narrow screen instead of pushing it sideways.
  • The scope line carries a stable `data-slot` so a host can rewrite the count without re-rendering the header.
  • Declares registry capability flags: a11y, responsive, rtl, darkMode, localized.

Guidance

Layout and content structure

Structure content hierarchy and responsive relationships.

Use when

  • Use to structure hierarchy, spacing, and responsiveness so content is easier to scan and navigate.
  • Every admin list, record and form page: it fixes where the title, the scope sentence and the page-level actions sit.
  • A list that refreshes in place must update its scope sentence — target `[data-slot="page-header-scope"]`.

Avoid when

  • Do not let layout primitives substitute for semantics, headings, or interaction rules users still need.
  • A marketing section heading — use `section-heading`.
  • A record edit screen whose header must stay sticky with save state — use `admin-record-header`.

Use instead

  • Semantic HTML with standard flow

Anti-patterns

  • Using visual layout as a substitute for semantic structure
Anatomy
page-header page-header-eyebrow page-header-title page-header-count page-header-scope page-header-actions
Theming hooks
page-header

Accessibility

WCAG 2.2 AA Keyboard focus-visible RTL-ready Localized labels Dark mode
Keyboard
No component-owned keyboard interaction; native element behavior applies.
Focus
none
  • Exactly one page title element; the count badge is text, never colour alone.
  • Semantic HTML and a stable data-slot attribute for styling and scripting hooks.
  • Focus-visible rings use the ring token, so keyboard focus is always visible.
  • Disabled and invalid states are conveyed to assistive tech, not by color alone.
  • Targets WCAG 2.2 AA; verify contrast in light, dark, admin and customer surfaces in the preview.
  • Labels go through __() and layout uses logical properties (ms-*, text-start), so it mirrors under dir="rtl" — flip the preview to RTL to confirm.
  • Dark mode uses the same semantic tokens under the dark class; high contrast follows forced-color system tokens.

Livewire

Safe

Livewire can update this component through forwarded wire:* attributes.

Source

The exact, editable file ui:add writes into your app. Previews render this same code; there are no preview-only components.

resources/views/components/ui/admin/page-header.blade.php Blade
{{--
    Page Header — the first line of every admin screen: what this page is,
    how much of it there is, and the actions that apply to the whole page.

    The scope line carries a stable `data-slot` on purpose. A list that
    refreshes in place (server-mode filtering, a saved view applied from a
    KPI tile) must rewrite "34 orders" to "6 orders" without re-rendering the
    header; the host targets `[data-slot="page-header-scope"]` and sets its
    text. Printing the count once and leaving it stale over a filtered list
    is the bug this component exists to prevent.

    The action cluster is a slot, not a prop array: the actions on a page
    header are the page's own (create, import, a legacy-screen link, a
    shortcut chip into a saved view) and each one carries its own wiring.
    The component only decides where they sit and how they wrap.

    Generalised from the Noord-C admin's `v2/page-header.blade.php`, which
    every one of its forty rebuilt screens opened with.
--}}
@props([
    'title' => 'Customers',
    'scope' => null,
    'count' => null,
    'countLabel' => null,
    'eyebrow' => null,
    'as' => 'h1',
])

@php
    // Shapes documented in item.json knowledge.props:
    //   scope: a sentence describing what the page covers ("34 customers in this store"), rewritten in place by the host on refresh.
    //   count/countLabel: a badge beside the title ("128" / "128 records") when the scope line is not wanted.
    $tag = in_array($as, ['h1', 'h2'], true) ? $as : 'h1';

    // `null` (absent) renders a sample scope line so the docs preview reads
    // as a real header; pass `:scope="false"` for a header with no scope line.
    $scope ??= $count === null
        ? __('Everyone who has ordered from, registered with, or been added to this store.')
        : false;
@endphp

<header
    data-slot="page-header"
    data-surface="admin"
    {{ $attributes->merge(['class' => 'flex min-w-0 flex-wrap items-start justify-between gap-4']) }}
>
    <div class="min-w-0 flex-1 basis-64">
        @if ($eyebrow !== null)
            <p data-slot="page-header-eyebrow" class="text-xs font-medium tracking-wide text-muted-foreground uppercase">{{ $eyebrow }}</p>
        @endif

        <div class="flex min-w-0 flex-wrap items-center gap-2">
            <{{ $tag }} data-slot="page-header-title" class="min-w-0 truncate text-xl font-semibold tracking-tight">{{ $title }}</{{ $tag }}>

            @if ($count !== null)
                <x-ui.badge variant="secondary" data-slot="page-header-count">
                    {{ $countLabel ?? $count }}
                </x-ui.badge>
            @endif
        </div>

        @if ($scope)
            <p data-slot="page-header-scope" class="mt-2 max-w-2xl text-sm text-pretty text-muted-foreground">{{ $scope }}</p>
        @endif
    </div>

    @isset($actions)
        <div data-slot="page-header-actions" class="flex min-w-0 flex-wrap items-center gap-2">
            {{ $actions }}
        </div>
    @else
        <div data-slot="page-header-actions" class="flex min-w-0 flex-wrap items-center gap-2">
            <x-ui.button variant="outline" size="sm" href="#">{{ __('Import') }}</x-ui.button>
            <x-ui.button size="sm" href="#">{{ __('New customer') }}</x-ui.button>
        </div>
    @endisset
</header>

Ownership & lifecycle

Owner, release state, review evidence and adoption for this item.
Owner
Platform UI (@JoshJML)
Current version
1.0.2
Status
Stable
License
open
Accessibility reviewed
No review date recorded
Last breaking change
No date recorded
Deprecation
Not deprecated
Contract
v6
Foundation
≥ 1.0.0