Resource Pages
Authenticated resource workflows — searchable and selectable index, create, edit, and detail pages with activity history, plus the operator set: an alert-led index, a waiting-for work queue, a stepped record and one create/edit form with save blockers.
Preview
{{--
Admin Record — the record detail screen for working a list in sequence.
Generalised from the Noord-C admin's `orders/show.blade.php`: an attention
banner zone, a sticky record header (title, status, dirty state, action
cluster), previous/next stepping so an operator never has to return to the
list to reach the next record, a tabbed body, a side rail of related
cards, and an activity timeline.
Rule carried over from the source spec, and the reason `actions` has no
per-action `disabled`: an action the viewer may not take is ABSENT, not
rendered-and-disabled. The caller filters `actions` to what the viewer is
eligible for before it ever reaches this page.
Left out on purpose (domain logic the consumer supplies): money/VAT
arithmetic, carrier/warehouse specifics, and any eligibility rule for
which action or status transition applies to THIS record.
--}}
@props([
'title' => '#1042',
'subtitle' => 'Webshop, Mollie, Aug 22, 2026, ref PO-1042',
'indexHref' => '#',
'indexLabel' => 'Orders',
'status' => 'processing',
'statusOptions' => null,
'dirty' => true,
'navigation' => null,
'alerts' => null,
'actions' => null,
'lines' => null,
'totals' => null,
'sideCards' => null,
'activity' => null,
])
@php
$statusOptions ??= [
['value' => 'awaiting_payment', 'label' => 'Awaiting payment', 'tone' => 'soft-warning'],
['value' => 'processing', 'label' => 'Processing', 'tone' => 'soft-info'],
['value' => 'shipped', 'label' => 'Shipped', 'tone' => 'soft-info'],
['value' => 'delivered', 'label' => 'Delivered', 'tone' => 'soft-success'],
['value' => 'on_hold', 'label' => 'On hold', 'tone' => 'soft-destructive'],
];
$navigation ??= [
'previous' => ['href' => '#', 'label' => '#1041'],
'next' => ['href' => '#', 'label' => '#1043'],
'position' => 'Record 12 of 128',
];
$alerts ??= [
[
'tone' => 'warning',
'title' => 'Payment not yet confirmed',
'description' => 'The payment provider has not confirmed this order in 22 minutes. Fulfilment is on hold until it settles.',
],
];
$actions ??= [
'primary' => ['key' => 'ship', 'label' => 'Mark as shipped', 'kind' => 'submit', 'url' => '#'],
'secondary' => [
['key' => 'invoice', 'label' => 'Send invoice', 'kind' => 'submit', 'url' => '#'],
['key' => 'packing-slip', 'label' => 'Print packing slip', 'kind' => 'link', 'url' => '#', 'newTab' => true],
],
// No "Refund" here: this order has not been paid yet, so a refund is
// not eligible — the action is absent, not disabled.
'menu' => [
['key' => 'export-timeline', 'label' => 'Export timeline', 'kind' => 'link', 'url' => '#'],
['key' => 'cancel', 'label' => 'Cancel order', 'kind' => 'dialog'],
],
];
$lines ??= [
['name' => 'Wireless keyboard — graphite', 'meta' => 'SKU KB-2201', 'quantity' => 1, 'total' => '€64.00'],
['name' => 'USB-C hub, 7-port', 'meta' => 'SKU HB-0087', 'quantity' => 2, 'total' => '€96.00'],
['name' => 'Desk mat, wool felt — charcoal', 'meta' => 'SKU DM-1140', 'quantity' => 1, 'total' => '€28.50'],
];
$totals ??= [
['label' => 'Subtotal', 'value' => '€188.50'],
['label' => 'Shipping', 'value' => '€6.95'],
['label' => 'VAT (21%)', 'value' => '€41.02'],
['label' => 'Total', 'value' => '€236.47', 'emphasis' => true],
];
$sideCards ??= [
[
'title' => 'Payment',
'description' => 'Mollie, iDEAL',
'rows' => [
['label' => 'Method', 'value' => 'iDEAL'],
['label' => 'Status', 'value' => 'Pending confirmation'],
['label' => 'Reference', 'value' => 'tr_8sK3n0qP2x'],
],
'action' => ['label' => 'View in Mollie', 'href' => '#'],
],
[
'title' => 'Customer',
'description' => 'Els Bakker',
'rows' => [
['label' => 'Email', 'value' => 'els.bakker@example.com'],
['label' => 'Orders placed', 'value' => '7'],
['label' => 'Customer since', 'value' => 'Mar 2024'],
],
'action' => ['label' => 'View customer', 'href' => '#'],
],
[
'title' => 'Fulfilment',
'description' => 'PostNL, Standard',
'rows' => [
['label' => 'Warehouse', 'value' => 'Utrecht DC'],
['label' => 'Promised by', 'value' => 'Aug 26, 2026'],
['label' => 'Address', 'value' => 'Kerkstraat 12, 3512 AA Utrecht'],
],
'action' => null,
],
];
$activity ??= [
['actor' => 'Maya Chen', 'initials' => 'MC', 'action' => 'changed the status to', 'target' => 'Processing', 'time' => '12 minutes ago', 'datetime' => now()->subMinutes(12)->toIso8601String()],
['actor' => 'System', 'initials' => '⚙', 'action' => 'received a payment webhook for', 'target' => 'tr_8sK3n0qP2x', 'time' => '22 minutes ago', 'datetime' => now()->subMinutes(22)->toIso8601String()],
['actor' => 'Noah Williams', 'initials' => 'NW', 'action' => 'added a note:', 'target' => 'Customer asked to combine with order #1039.', 'time' => 'Yesterday', 'datetime' => now()->subDay()->toIso8601String()],
['actor' => 'Els Bakker', 'initials' => 'EB', 'action' => 'placed this order', 'target' => '', 'time' => 'Aug 22, 2026', 'datetime' => '2026-08-22T09:14:00+02:00'],
];
@endphp
<main
id="main-content"
data-slot="admin-record-page"
data-surface="admin"
data-visual-contracts="VC-006"
{{ $attributes->merge(['class' => 'min-h-screen bg-background text-foreground pb-16']) }}
>
<div
data-slot="admin-record-header"
class="sticky top-0 z-20 border-b border-border bg-background px-4 py-4 sm:px-6"
>
<div class="flex flex-wrap items-center justify-between gap-4">
<x-ui.breadcrumb>
<x-ui.breadcrumb.list>
<x-ui.breadcrumb.item>
<x-ui.breadcrumb.link :href="$indexHref">{{ __($indexLabel) }}</x-ui.breadcrumb.link>
</x-ui.breadcrumb.item>
<x-ui.breadcrumb.separator />
<x-ui.breadcrumb.item>
<x-ui.breadcrumb.page>{{ __($title) }}</x-ui.breadcrumb.page>
</x-ui.breadcrumb.item>
</x-ui.breadcrumb.list>
</x-ui.breadcrumb>
@if ($navigation)
<nav class="flex shrink-0 items-center gap-2" aria-label="{{ __('Record navigation') }}">
@if (! empty($navigation['position']))
<span class="text-xs text-muted-foreground">{{ __($navigation['position']) }}</span>
@endif
<x-ui.button
variant="outline"
size="icon-sm"
:href="$navigation['previous']['href'] ?? null"
:disabled="empty($navigation['previous'])"
:icon-label="__('Previous record:record', ['record' => $navigation['previous']['label'] ?? ''])"
>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4 rtl:rotate-180" aria-hidden="true"><path d="m15 18-6-6 6-6" /></svg>
</x-ui.button>
<x-ui.button
variant="outline"
size="icon-sm"
:href="$navigation['next']['href'] ?? null"
:disabled="empty($navigation['next'])"
:icon-label="__('Next record: :record', ['record' => $navigation['next']['label'] ?? ''])"
>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4 rtl:rotate-180" aria-hidden="true"><path d="m9 18 6-6-6-6" /></svg>
</x-ui.button>
</nav>
@endif
</div>
<div class="mt-4 flex flex-wrap items-start justify-between gap-x-6 gap-y-4">
<div class="min-w-0">
<div class="flex flex-wrap items-center gap-x-2 gap-y-2">
<h1 class="text-xl font-semibold tracking-tight">{{ __($title) }}</h1>
<x-ui.status-select :value="$status" :options="$statusOptions" />
@if ($dirty)
<x-ui.badge variant="soft-warning">{{ __('Unsaved changes') }}</x-ui.badge>
@endif
</div>
<p class="mt-2 text-xs text-muted-foreground">{{ __($subtitle) }}</p>
</div>
<div class="flex shrink-0 flex-wrap items-center gap-2">
@if ($dirty)
<x-ui.button variant="ghost" size="sm">{{ __('Discard') }}</x-ui.button>
<x-ui.button variant="secondary" size="sm">{{ __('Save changes') }}</x-ui.button>
@endif
@foreach ($actions['secondary'] ?? [] as $action)
<x-ui.button
variant="outline"
size="sm"
:type="($action['kind'] ?? 'link') === 'submit' ? 'submit' : 'button'"
:href="($action['kind'] ?? 'link') === 'link' ? ($action['url'] ?? '#') : null"
:target="($action['newTab'] ?? false) ? '_blank' : null"
:rel="($action['newTab'] ?? false) ? 'noopener noreferrer' : null"
>
{{ __($action['label'] ?? '') }}
</x-ui.button>
@endforeach
@if (! empty($actions['primary']))
<x-ui.button size="sm">{{ __($actions['primary']['label'] ?? '') }}</x-ui.button>
@endif
@if (! empty($actions['menu']))
<x-ui.dropdown :anchored="true">
<x-ui.dropdown.trigger
:aria-label="__('More actions for :record', ['record' => $title])"
class="inline-flex size-9 items-center justify-center rounded-md border border-border text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
>
<svg aria-hidden="true" viewBox="0 0 16 16" fill="currentColor" class="size-4">
<circle cx="3" cy="8" r="1.25" /><circle cx="8" cy="8" r="1.25" /><circle cx="13" cy="8" r="1.25" />
</svg>
</x-ui.dropdown.trigger>
<x-ui.dropdown.content align="end">
@foreach ($actions['menu'] as $action)
<x-ui.dropdown.item :href="($action['kind'] ?? 'link') === 'link' ? ($action['url'] ?? '#') : null">
{{ __($action['label'] ?? '') }}
</x-ui.dropdown.item>
@endforeach
</x-ui.dropdown.content>
</x-ui.dropdown>
@endif
</div>
</div>
</div>
<div class="mx-auto max-w-6xl px-4 py-6 sm:px-6">
@if (! empty($alerts))
<div class="mb-6 space-y-2" data-slot="admin-record-alerts">
@foreach ($alerts as $alert)
<x-ui.alert :variant="$alert['tone'] ?? 'warning'">
<div class="text-sm font-semibold">{{ __($alert['title'] ?? '') }}</div>
@if (! empty($alert['description']))
<p class="mt-2 max-w-2xl text-xs leading-5 text-pretty opacity-90">{{ __($alert['description']) }}</p>
@endif
</x-ui.alert>
@endforeach
</div>
@endif
<div class="grid items-start gap-6 lg:grid-cols-[minmax(0,1fr)_20rem]">
<div class="min-w-0">
<x-ui.tabs default="details">
<x-ui.tabs.list aria-label="{{ __('Record sections') }}">
<x-ui.tabs.trigger value="details">{{ __('Details') }}</x-ui.tabs.trigger>
<x-ui.tabs.trigger value="activity">{{ __('Activity') }}</x-ui.tabs.trigger>
</x-ui.tabs.list>
<x-ui.tabs.content value="details">
<x-ui.card>
<x-ui.card.content class="p-0">
<x-ui.table>
<x-ui.table.header>
<x-ui.table.row>
<x-ui.table.head>{{ __('Item') }}</x-ui.table.head>
<x-ui.table.head class="text-end">{{ __('Qty') }}</x-ui.table.head>
<x-ui.table.head class="text-end">{{ __('Total') }}</x-ui.table.head>
</x-ui.table.row>
</x-ui.table.header>
<x-ui.table.body>
@foreach ($lines as $line)
<x-ui.table.row>
<x-ui.table.cell>
<span class="block font-medium">{{ $line['name'] ?? '' }}</span>
@if (! empty($line['meta']))
<span class="block text-xs text-muted-foreground">{{ $line['meta'] }}</span>
@endif
</x-ui.table.cell>
<x-ui.table.cell class="text-end tabular-nums">{{ $line['quantity'] ?? '' }}</x-ui.table.cell>
<x-ui.table.cell class="text-end font-medium tabular-nums">{{ $line['total'] ?? '' }}</x-ui.table.cell>
</x-ui.table.row>
@endforeach
</x-ui.table.body>
</x-ui.table>
<x-ui.separator />
<dl class="space-y-2 p-4">
@foreach ($totals as $total)
<div class="flex items-center justify-between gap-4 text-sm">
<dt @class(['text-muted-foreground', 'font-medium text-foreground' => $total['emphasis'] ?? false])>{{ __($total['label'] ?? '') }}</dt>
<dd @class(['tabular-nums', 'font-semibold text-foreground' => $total['emphasis'] ?? false])>{{ $total['value'] ?? '' }}</dd>
</div>
@endforeach
</dl>
</x-ui.card.content>
</x-ui.card>
</x-ui.tabs.content>
<x-ui.tabs.content value="activity">
<x-ui.card>
<x-ui.card.content class="pt-6">
<x-ui.audit-log
variant="plain"
:grouped="false"
:label="__('Record activity')"
:empty-label="__('No activity has been recorded yet.')"
:events="collect($activity)->map(fn (array $event): array => [
'actor' => ['name' => $event['actor'] ?? '', 'initials' => $event['initials'] ?? ''],
'action' => __($event['action'] ?? ''),
'subject' => $event['target'] ?? '',
'at' => $event['datetime'] ?? null,
])->all()"
/>
</x-ui.card.content>
</x-ui.card>
</x-ui.tabs.content>
</x-ui.tabs>
</div>
<aside class="space-y-6" data-slot="admin-record-side-rail">
@foreach ($sideCards as $card)
<x-ui.card>
<x-ui.card.header>
<x-ui.card.title>{{ __($card['title'] ?? '') }}</x-ui.card.title>
@if (! empty($card['description']))
<x-ui.card.description>{{ __($card['description']) }}</x-ui.card.description>
@endif
</x-ui.card.header>
<x-ui.card.content>
<dl class="space-y-2">
@foreach ($card['rows'] ?? [] as $row)
<div class="flex items-start justify-between gap-4 text-sm">
<dt class="shrink-0 text-muted-foreground">{{ __($row['label'] ?? '') }}</dt>
<dd class="min-w-0 text-end break-words text-foreground">{{ $row['value'] ?? '' }}</dd>
</div>
@endforeach
</dl>
</x-ui.card.content>
@if (! empty($card['action']))
<x-ui.card.footer>
<x-ui.button variant="ghost" size="sm" :href="$card['action']['href'] ?? '#'">
{{ __($card['action']['label'] ?? '') }}
</x-ui.button>
</x-ui.card.footer>
@endif
</x-ui.card>
@endforeach
</aside>
</div>
</div>
</main>
Installation
php artisan ui:add pages/admin-record
Registry contract
Install confidence
php artisan ui:add pages/admin-record
writes only the generated targets below. The CLI validates each file hash before writing and
prompts before replacing local changes unless --force is used.
- Version
- 1.0.3
- License
- open
- Stability
- stable
- Contract
- v4
- Foundation
- ≥ 1.0.0
| Type | Generated target |
|---|---|
| blade | resources/views/pages/admin-record.blade.php |
Registry dependencies
Package dependencies
composer: jml/brok:^0.2
Use with AI
A brief for your coding agent: what the page is, the install command, how to render it, its props and the rules. Copy it, or open a prompt about this page in an assistant.
# Brok UI page: Admin Record (`admin-record`)
A record detail screen for working a list in sequence: an attention banner zone, a sticky record header with status, dirty state, and an action cluster of only the actions the viewer may take, previous/next stepping, a tabbed body, a side rail of related cards, and an activity timeline.
Brok UI is a Laravel Blade registry. `ui:add` copies this page into the app as plain Blade the app owns; it composes installed `<brok:*>` primitives and semantic design tokens.
## Install
```bash
php artisan ui:add pages/admin-record
```
## Render it
```blade
<x-pages.admin-record />
```
## Props
- `title` (string, default `#1042`) — Record identifier and page heading.
- `subtitle` (string, default `Webshop, Mollie, Aug 22, 2026, ref PO-1042`) — One-line identity summary under the title.
- `index-href` (string, default `#`) — Breadcrumb destination back to the index.
- `index-label` (string, default `Orders`) — Breadcrumb label for the index.
- `status` (string, default `processing`) — Current status value, matched against statusOptions.
- `status-options` (array|null, default `null`) — Status vocabulary for <x-ui.status-select>: ['value','label','tone'].
- `dirty` (bool, default `true`) — Whether the record has local unsaved changes. Renders a badge and save/discard actions in the header when true.
- `navigation` (array|null, default `null`) — ['previous' => ['href','label']|null, 'next' => ['href','label']|null, 'position' => 'Record 12 of 128']. A missing side renders its stepper button disabled, never absent, matching ordinary pagination.
- `alerts` (array|null, default `null`) — Attention-banner entries: each is ['tone','title','description','actionLabel','actionHref']. Most severe first.
- `actions` (array|null, default `null`) — ['primary' => action|null, 'secondary' => [action], 'menu' => [action]]. Only actions the viewer may take are present — an ineligible action is absent, never rendered disabled.
- `lines` (array|null, default `null`) — Line items for the Details tab: each is ['name','meta','quantity','total'].
- `totals` (array|null, default `null`) — Totals rows under the line items: each is ['label','value','emphasis' => bool].
- `side-cards` (array|null, default `null`) — Related-content cards for the side rail: each is ['title','description','rows' => [['label','value']],'action' => ['label','href']|null].
- `activity` (array|null, default `null`) — Chronological actor, action, target, time, datetime, and initials entries for the Activity tab.
## Use when
- Building the show route for a record an operator opens from a worked list and needs to step through in sequence.
- The record has more state than a plain metadata list: a status that changes, actions gated by permission or workflow state, and a history worth showing as a timeline.
## Avoid when
- The record has no workflow actions and no activity history — use the simpler pages/resource-page-detail instead.
- There is no list to step through — drop the previous/next stepper rather than rendering it with both sides empty.
## Rules
- Render the installed page with `<x-pages.admin-record />` and pass data through its props; edit the copied file only for structural changes.
- Keep the semantic design tokens (`bg-background`, `text-muted-foreground`); never swap in raw colour utilities.
- Keep the `data-slot` attributes and the logical (start/end) spacing so the markup still mirrors under `dir="rtl"`.
## Links
- Docs: https://brokui.dev/pages/admin-record
- Registry JSON (files, props, contract): https://brokui.dev/r/open/pages/admin-record.json
Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.
Guidance
Use when
- Building the show route for a record an operator opens from a worked list and needs to step through in sequence.
- The record has more state than a plain metadata list: a status that changes, actions gated by permission or workflow state, and a history worth showing as a timeline.
Avoid when
- The record has no workflow actions and no activity history — use the simpler pages/resource-page-detail instead.
- There is no list to step through — drop the previous/next stepper rather than rendering it with both sides empty.
Anti-patterns
- Do not replace semantic props with conflicting utility classes.
- Do not remove labels, focus styles, or state attributes.
- Anatomy
- Theming hooks
Usage
Render the page as a component, or wire it to a route. Pass data where useful:
<x-pages.admin-record />
Built from blocks & primitives
This page composes installed <brok:*> primitives and semantic design
tokens only — it does not reimplement any primitive. Re-theme it (light, dark, admin, customer) by
editing CSS variables; flip the preview to RTL to confirm it mirrors.
Source
The exact, editable file ui:add writes
into your app. The preview above renders this same source — there are no preview-only pages.
{{--
Admin Record — the record detail screen for working a list in sequence.
Generalised from the Noord-C admin's `orders/show.blade.php`: an attention
banner zone, a sticky record header (title, status, dirty state, action
cluster), previous/next stepping so an operator never has to return to the
list to reach the next record, a tabbed body, a side rail of related
cards, and an activity timeline.
Rule carried over from the source spec, and the reason `actions` has no
per-action `disabled`: an action the viewer may not take is ABSENT, not
rendered-and-disabled. The caller filters `actions` to what the viewer is
eligible for before it ever reaches this page.
Left out on purpose (domain logic the consumer supplies): money/VAT
arithmetic, carrier/warehouse specifics, and any eligibility rule for
which action or status transition applies to THIS record.
--}}
@props([
'title' => '#1042',
'subtitle' => 'Webshop, Mollie, Aug 22, 2026, ref PO-1042',
'indexHref' => '#',
'indexLabel' => 'Orders',
'status' => 'processing',
'statusOptions' => null,
'dirty' => true,
'navigation' => null,
'alerts' => null,
'actions' => null,
'lines' => null,
'totals' => null,
'sideCards' => null,
'activity' => null,
])
@php
$statusOptions ??= [
['value' => 'awaiting_payment', 'label' => 'Awaiting payment', 'tone' => 'soft-warning'],
['value' => 'processing', 'label' => 'Processing', 'tone' => 'soft-info'],
['value' => 'shipped', 'label' => 'Shipped', 'tone' => 'soft-info'],
['value' => 'delivered', 'label' => 'Delivered', 'tone' => 'soft-success'],
['value' => 'on_hold', 'label' => 'On hold', 'tone' => 'soft-destructive'],
];
$navigation ??= [
'previous' => ['href' => '#', 'label' => '#1041'],
'next' => ['href' => '#', 'label' => '#1043'],
'position' => 'Record 12 of 128',
];
$alerts ??= [
[
'tone' => 'warning',
'title' => 'Payment not yet confirmed',
'description' => 'The payment provider has not confirmed this order in 22 minutes. Fulfilment is on hold until it settles.',
],
];
$actions ??= [
'primary' => ['key' => 'ship', 'label' => 'Mark as shipped', 'kind' => 'submit', 'url' => '#'],
'secondary' => [
['key' => 'invoice', 'label' => 'Send invoice', 'kind' => 'submit', 'url' => '#'],
['key' => 'packing-slip', 'label' => 'Print packing slip', 'kind' => 'link', 'url' => '#', 'newTab' => true],
],
// No "Refund" here: this order has not been paid yet, so a refund is
// not eligible — the action is absent, not disabled.
'menu' => [
['key' => 'export-timeline', 'label' => 'Export timeline', 'kind' => 'link', 'url' => '#'],
['key' => 'cancel', 'label' => 'Cancel order', 'kind' => 'dialog'],
],
];
$lines ??= [
['name' => 'Wireless keyboard — graphite', 'meta' => 'SKU KB-2201', 'quantity' => 1, 'total' => '€64.00'],
['name' => 'USB-C hub, 7-port', 'meta' => 'SKU HB-0087', 'quantity' => 2, 'total' => '€96.00'],
['name' => 'Desk mat, wool felt — charcoal', 'meta' => 'SKU DM-1140', 'quantity' => 1, 'total' => '€28.50'],
];
$totals ??= [
['label' => 'Subtotal', 'value' => '€188.50'],
['label' => 'Shipping', 'value' => '€6.95'],
['label' => 'VAT (21%)', 'value' => '€41.02'],
['label' => 'Total', 'value' => '€236.47', 'emphasis' => true],
];
$sideCards ??= [
[
'title' => 'Payment',
'description' => 'Mollie, iDEAL',
'rows' => [
['label' => 'Method', 'value' => 'iDEAL'],
['label' => 'Status', 'value' => 'Pending confirmation'],
['label' => 'Reference', 'value' => 'tr_8sK3n0qP2x'],
],
'action' => ['label' => 'View in Mollie', 'href' => '#'],
],
[
'title' => 'Customer',
'description' => 'Els Bakker',
'rows' => [
['label' => 'Email', 'value' => 'els.bakker@example.com'],
['label' => 'Orders placed', 'value' => '7'],
['label' => 'Customer since', 'value' => 'Mar 2024'],
],
'action' => ['label' => 'View customer', 'href' => '#'],
],
[
'title' => 'Fulfilment',
'description' => 'PostNL, Standard',
'rows' => [
['label' => 'Warehouse', 'value' => 'Utrecht DC'],
['label' => 'Promised by', 'value' => 'Aug 26, 2026'],
['label' => 'Address', 'value' => 'Kerkstraat 12, 3512 AA Utrecht'],
],
'action' => null,
],
];
$activity ??= [
['actor' => 'Maya Chen', 'initials' => 'MC', 'action' => 'changed the status to', 'target' => 'Processing', 'time' => '12 minutes ago', 'datetime' => now()->subMinutes(12)->toIso8601String()],
['actor' => 'System', 'initials' => '⚙', 'action' => 'received a payment webhook for', 'target' => 'tr_8sK3n0qP2x', 'time' => '22 minutes ago', 'datetime' => now()->subMinutes(22)->toIso8601String()],
['actor' => 'Noah Williams', 'initials' => 'NW', 'action' => 'added a note:', 'target' => 'Customer asked to combine with order #1039.', 'time' => 'Yesterday', 'datetime' => now()->subDay()->toIso8601String()],
['actor' => 'Els Bakker', 'initials' => 'EB', 'action' => 'placed this order', 'target' => '', 'time' => 'Aug 22, 2026', 'datetime' => '2026-08-22T09:14:00+02:00'],
];
@endphp
<main
id="main-content"
data-slot="admin-record-page"
data-surface="admin"
data-visual-contracts="VC-006"
{{ $attributes->merge(['class' => 'min-h-screen bg-background text-foreground pb-16']) }}
>
<div
data-slot="admin-record-header"
class="sticky top-0 z-20 border-b border-border bg-background px-4 py-4 sm:px-6"
>
<div class="flex flex-wrap items-center justify-between gap-4">
<x-ui.breadcrumb>
<x-ui.breadcrumb.list>
<x-ui.breadcrumb.item>
<x-ui.breadcrumb.link :href="$indexHref">{{ __($indexLabel) }}</x-ui.breadcrumb.link>
</x-ui.breadcrumb.item>
<x-ui.breadcrumb.separator />
<x-ui.breadcrumb.item>
<x-ui.breadcrumb.page>{{ __($title) }}</x-ui.breadcrumb.page>
</x-ui.breadcrumb.item>
</x-ui.breadcrumb.list>
</x-ui.breadcrumb>
@if ($navigation)
<nav class="flex shrink-0 items-center gap-2" aria-label="{{ __('Record navigation') }}">
@if (! empty($navigation['position']))
<span class="text-xs text-muted-foreground">{{ __($navigation['position']) }}</span>
@endif
<x-ui.button
variant="outline"
size="icon-sm"
:href="$navigation['previous']['href'] ?? null"
:disabled="empty($navigation['previous'])"
:icon-label="__('Previous record:record', ['record' => $navigation['previous']['label'] ?? ''])"
>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4 rtl:rotate-180" aria-hidden="true"><path d="m15 18-6-6 6-6" /></svg>
</x-ui.button>
<x-ui.button
variant="outline"
size="icon-sm"
:href="$navigation['next']['href'] ?? null"
:disabled="empty($navigation['next'])"
:icon-label="__('Next record: :record', ['record' => $navigation['next']['label'] ?? ''])"
>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4 rtl:rotate-180" aria-hidden="true"><path d="m9 18 6-6-6-6" /></svg>
</x-ui.button>
</nav>
@endif
</div>
<div class="mt-4 flex flex-wrap items-start justify-between gap-x-6 gap-y-4">
<div class="min-w-0">
<div class="flex flex-wrap items-center gap-x-2 gap-y-2">
<h1 class="text-xl font-semibold tracking-tight">{{ __($title) }}</h1>
<x-ui.status-select :value="$status" :options="$statusOptions" />
@if ($dirty)
<x-ui.badge variant="soft-warning">{{ __('Unsaved changes') }}</x-ui.badge>
@endif
</div>
<p class="mt-2 text-xs text-muted-foreground">{{ __($subtitle) }}</p>
</div>
<div class="flex shrink-0 flex-wrap items-center gap-2">
@if ($dirty)
<x-ui.button variant="ghost" size="sm">{{ __('Discard') }}</x-ui.button>
<x-ui.button variant="secondary" size="sm">{{ __('Save changes') }}</x-ui.button>
@endif
@foreach ($actions['secondary'] ?? [] as $action)
<x-ui.button
variant="outline"
size="sm"
:type="($action['kind'] ?? 'link') === 'submit' ? 'submit' : 'button'"
:href="($action['kind'] ?? 'link') === 'link' ? ($action['url'] ?? '#') : null"
:target="($action['newTab'] ?? false) ? '_blank' : null"
:rel="($action['newTab'] ?? false) ? 'noopener noreferrer' : null"
>
{{ __($action['label'] ?? '') }}
</x-ui.button>
@endforeach
@if (! empty($actions['primary']))
<x-ui.button size="sm">{{ __($actions['primary']['label'] ?? '') }}</x-ui.button>
@endif
@if (! empty($actions['menu']))
<x-ui.dropdown :anchored="true">
<x-ui.dropdown.trigger
:aria-label="__('More actions for :record', ['record' => $title])"
class="inline-flex size-9 items-center justify-center rounded-md border border-border text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
>
<svg aria-hidden="true" viewBox="0 0 16 16" fill="currentColor" class="size-4">
<circle cx="3" cy="8" r="1.25" /><circle cx="8" cy="8" r="1.25" /><circle cx="13" cy="8" r="1.25" />
</svg>
</x-ui.dropdown.trigger>
<x-ui.dropdown.content align="end">
@foreach ($actions['menu'] as $action)
<x-ui.dropdown.item :href="($action['kind'] ?? 'link') === 'link' ? ($action['url'] ?? '#') : null">
{{ __($action['label'] ?? '') }}
</x-ui.dropdown.item>
@endforeach
</x-ui.dropdown.content>
</x-ui.dropdown>
@endif
</div>
</div>
</div>
<div class="mx-auto max-w-6xl px-4 py-6 sm:px-6">
@if (! empty($alerts))
<div class="mb-6 space-y-2" data-slot="admin-record-alerts">
@foreach ($alerts as $alert)
<x-ui.alert :variant="$alert['tone'] ?? 'warning'">
<div class="text-sm font-semibold">{{ __($alert['title'] ?? '') }}</div>
@if (! empty($alert['description']))
<p class="mt-2 max-w-2xl text-xs leading-5 text-pretty opacity-90">{{ __($alert['description']) }}</p>
@endif
</x-ui.alert>
@endforeach
</div>
@endif
<div class="grid items-start gap-6 lg:grid-cols-[minmax(0,1fr)_20rem]">
<div class="min-w-0">
<x-ui.tabs default="details">
<x-ui.tabs.list aria-label="{{ __('Record sections') }}">
<x-ui.tabs.trigger value="details">{{ __('Details') }}</x-ui.tabs.trigger>
<x-ui.tabs.trigger value="activity">{{ __('Activity') }}</x-ui.tabs.trigger>
</x-ui.tabs.list>
<x-ui.tabs.content value="details">
<x-ui.card>
<x-ui.card.content class="p-0">
<x-ui.table>
<x-ui.table.header>
<x-ui.table.row>
<x-ui.table.head>{{ __('Item') }}</x-ui.table.head>
<x-ui.table.head class="text-end">{{ __('Qty') }}</x-ui.table.head>
<x-ui.table.head class="text-end">{{ __('Total') }}</x-ui.table.head>
</x-ui.table.row>
</x-ui.table.header>
<x-ui.table.body>
@foreach ($lines as $line)
<x-ui.table.row>
<x-ui.table.cell>
<span class="block font-medium">{{ $line['name'] ?? '' }}</span>
@if (! empty($line['meta']))
<span class="block text-xs text-muted-foreground">{{ $line['meta'] }}</span>
@endif
</x-ui.table.cell>
<x-ui.table.cell class="text-end tabular-nums">{{ $line['quantity'] ?? '' }}</x-ui.table.cell>
<x-ui.table.cell class="text-end font-medium tabular-nums">{{ $line['total'] ?? '' }}</x-ui.table.cell>
</x-ui.table.row>
@endforeach
</x-ui.table.body>
</x-ui.table>
<x-ui.separator />
<dl class="space-y-2 p-4">
@foreach ($totals as $total)
<div class="flex items-center justify-between gap-4 text-sm">
<dt @class(['text-muted-foreground', 'font-medium text-foreground' => $total['emphasis'] ?? false])>{{ __($total['label'] ?? '') }}</dt>
<dd @class(['tabular-nums', 'font-semibold text-foreground' => $total['emphasis'] ?? false])>{{ $total['value'] ?? '' }}</dd>
</div>
@endforeach
</dl>
</x-ui.card.content>
</x-ui.card>
</x-ui.tabs.content>
<x-ui.tabs.content value="activity">
<x-ui.card>
<x-ui.card.content class="pt-6">
<x-ui.audit-log
variant="plain"
:grouped="false"
:label="__('Record activity')"
:empty-label="__('No activity has been recorded yet.')"
:events="collect($activity)->map(fn (array $event): array => [
'actor' => ['name' => $event['actor'] ?? '', 'initials' => $event['initials'] ?? ''],
'action' => __($event['action'] ?? ''),
'subject' => $event['target'] ?? '',
'at' => $event['datetime'] ?? null,
])->all()"
/>
</x-ui.card.content>
</x-ui.card>
</x-ui.tabs.content>
</x-ui.tabs>
</div>
<aside class="space-y-6" data-slot="admin-record-side-rail">
@foreach ($sideCards as $card)
<x-ui.card>
<x-ui.card.header>
<x-ui.card.title>{{ __($card['title'] ?? '') }}</x-ui.card.title>
@if (! empty($card['description']))
<x-ui.card.description>{{ __($card['description']) }}</x-ui.card.description>
@endif
</x-ui.card.header>
<x-ui.card.content>
<dl class="space-y-2">
@foreach ($card['rows'] ?? [] as $row)
<div class="flex items-start justify-between gap-4 text-sm">
<dt class="shrink-0 text-muted-foreground">{{ __($row['label'] ?? '') }}</dt>
<dd class="min-w-0 text-end break-words text-foreground">{{ $row['value'] ?? '' }}</dd>
</div>
@endforeach
</dl>
</x-ui.card.content>
@if (! empty($card['action']))
<x-ui.card.footer>
<x-ui.button variant="ghost" size="sm" :href="$card['action']['href'] ?? '#'">
{{ __($card['action']['label'] ?? '') }}
</x-ui.button>
</x-ui.card.footer>
@endif
</x-ui.card>
@endforeach
</aside>
</div>
</div>
</main>
Ownership & lifecycle
Owner, release state, review evidence and adoption for this item.
- Owner
- Platform UI (@JoshJML)
- Current version
-
1.0.3 - Status
- Stable
- License
-
open - Deprecation
- Not deprecated
- Contract
-
v4 - Foundation
-
≥ 1.0.0