Detail Page
A record detail view — shows all fields, related sub-tables, status, and contextual actions in a sidebar panel.
Components used​
Layout · Header · Card · Badge · Table · Section · Button · Modal
Code​
- HTML · @primus/ui-core
- React
- Angular
<div style="background:var(--background);width:100%;padding:1.25rem;box-sizing:border-box">
<!-- Header -->
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:1.25rem">
<div>
<div style="font-size:0.8rem;color:var(--muted-foreground);margin-bottom:0.25rem">
<a href="#" style="color:var(--muted-foreground)">Tenants</a> / Acme Corp
</div>
<div style="display:flex;align-items:center;gap:0.75rem">
<h1 style="margin:0;font-size:1.25rem;font-weight:700">Acme Corp</h1>
<span class="badge success">Active</span>
</div>
</div>
<div class="hstack">
<button class="outline small">Edit</button>
<button data-variant="danger" class="small">Suspend</button>
</div>
</div>
<div style="display:grid;grid-template-columns:1fr 260px;gap:1rem;align-items:start">
<!-- Main content -->
<div class="vstack">
<!-- Details card -->
<div class="card" style="padding:1.5rem">
<h3 style="margin:0 0 1rem;font-size:1rem;font-weight:600;padding-bottom:0.75rem;border-bottom:1px solid var(--border)">Details</h3>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:0.875rem;font-size:0.875rem">
<div><div style="color:var(--muted-foreground);font-size:0.8rem;margin-bottom:0.25rem">Plan</div><div style="font-weight:500">Enterprise</div></div>
<div><div style="color:var(--muted-foreground);font-size:0.8rem;margin-bottom:0.25rem">Billing cycle</div><div style="font-weight:500">Annual</div></div>
<div><div style="color:var(--muted-foreground);font-size:0.8rem;margin-bottom:0.25rem">Domain</div><div style="font-weight:500">acme.com</div></div>
<div><div style="color:var(--muted-foreground);font-size:0.8rem;margin-bottom:0.25rem">Region</div><div style="font-weight:500">EU West</div></div>
<div><div style="color:var(--muted-foreground);font-size:0.8rem;margin-bottom:0.25rem">Admin email</div><div style="font-weight:500">admin@acme.com</div></div>
<div><div style="color:var(--muted-foreground);font-size:0.8rem;margin-bottom:0.25rem">Created</div><div style="font-weight:500">Jan 15, 2026</div></div>
</div>
</div>
<!-- Users table -->
<div class="card" style="padding:0;overflow:hidden">
<div style="padding:0.875rem 1rem;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center">
<span style="font-weight:600;font-size:0.875rem">Users (247)</span>
<button class="outline small">+ Invite user</button>
</div>
<table style="width:100%;font-size:0.8rem;border-collapse:collapse">
<thead>
<tr style="border-bottom:1px solid var(--border)">
<th style="padding:0.625rem 1rem;text-align:left;font-weight:500;color:var(--muted-foreground)">Name</th>
<th style="padding:0.625rem 0.5rem;text-align:left;font-weight:500;color:var(--muted-foreground)">Email</th>
<th style="padding:0.625rem 0.5rem;text-align:left;font-weight:500;color:var(--muted-foreground)">Role</th>
<th style="padding:0.625rem 1rem;text-align:left;font-weight:500;color:var(--muted-foreground)">Status</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid var(--border)">
<td style="padding:0.625rem 1rem;font-weight:500">Jane Doe</td>
<td style="padding:0.625rem 0.5rem;color:var(--muted-foreground)">jane@acme.com</td>
<td style="padding:0.625rem 0.5rem">Admin</td>
<td style="padding:0.625rem 1rem"><span class="badge success" style="font-size:0.7rem">Active</span></td>
</tr>
<tr>
<td style="padding:0.625rem 1rem;font-weight:500">Bob Smith</td>
<td style="padding:0.625rem 0.5rem;color:var(--muted-foreground)">bob@acme.com</td>
<td style="padding:0.625rem 0.5rem">Member</td>
<td style="padding:0.625rem 1rem"><span class="badge success" style="font-size:0.7rem">Active</span></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Sidebar -->
<div class="vstack">
<div class="card" style="padding:1.25rem">
<h3 style="margin:0 0 0.875rem;font-size:0.9rem;font-weight:600">Subscription</h3>
<div class="vstack" style="gap:0.625rem;font-size:0.8rem">
<div style="display:flex;justify-content:space-between"><span style="color:var(--muted-foreground)">MRR</span><span style="font-weight:600;color:var(--success)">$12,000</span></div>
<div style="display:flex;justify-content:space-between"><span style="color:var(--muted-foreground)">Next invoice</span><span style="font-weight:500">Apr 1, 2026</span></div>
<div style="display:flex;justify-content:space-between"><span style="color:var(--muted-foreground)">Seats used</span><span style="font-weight:500">247 / 500</span></div>
<progress value="247" max="500" style="width:100%;margin-top:0.25rem"></progress>
</div>
</div>
<div class="card" style="padding:1.25rem">
<h3 style="margin:0 0 0.875rem;font-size:0.9rem;font-weight:600">Quick Actions</h3>
<div class="vstack" style="gap:0.5rem">
<button class="outline small" style="width:100%;justify-content:flex-start">Send invoice</button>
<button class="outline small" style="width:100%;justify-content:flex-start">Reset API key</button>
<button class="outline small" style="width:100%;justify-content:flex-start">View audit log</button>
<button class="ghost small" style="width:100%;justify-content:flex-start;color:var(--danger)">Delete tenant</button>
</div>
</div>
</div>
</div>
</div>
import {
PrimusLayout, PrimusHeader,
PrimusSection, Badge, Card,
PrimusDataTable, PrimusButton,
} from 'primus-react-ui';
const userColumns = [
{ key: 'name', header: 'Name' },
{ key: 'email', header: 'Email' },
{ key: 'role', header: 'Role' },
{ key: 'status', header: 'Status',
render: row => <Badge variant={row.statusVariant}>{row.status}</Badge> },
];
export function TenantDetailPage({ tenant }) {
return (
<PrimusLayout>
<PrimusHeader
breadcrumbs={[{ label: 'Tenants', href: '/tenants' }, { label: tenant.name }]}
title={tenant.name}
>
<PrimusButton variant="outline" onClick={() => navigate('edit')}>Edit</PrimusButton>
<PrimusButton variant="danger" onClick={openSuspendModal}>Suspend</PrimusButton>
</PrimusHeader>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 260px', gap: '1rem', alignItems: 'start' }}>
<div className="vstack">
<Card padding="md">
<PrimusSection title="Details">
<dl className="detail-grid">
<dt>Plan</dt> <dd>{tenant.plan}</dd>
<dt>Domain</dt> <dd>{tenant.domain}</dd>
<dt>Admin</dt> <dd>{tenant.adminEmail}</dd>
<dt>Region</dt> <dd>{tenant.region}</dd>
<dt>Created</dt> <dd>{formatDate(tenant.createdAt)}</dd>
</dl>
</PrimusSection>
</Card>
<PrimusDataTable
title="Users"
columns={userColumns}
data={tenant.users}
rowKey="id"
paginated
pageSize={5}
/>
</div>
<div className="vstack">
<Card padding="md">
<PrimusSection title="Subscription">
<p>MRR: {tenant.mrr}</p>
<p>Next invoice: {tenant.nextInvoice}</p>
</PrimusSection>
</Card>
<Card padding="md">
<PrimusSection title="Quick Actions">
<PrimusButton variant="outline" style={{ width: '100%' }}>Send invoice</PrimusButton>
<PrimusButton variant="outline" style={{ width: '100%' }}>Reset API key</PrimusButton>
<PrimusButton variant="outline" style={{ width: '100%' }}>View audit log</PrimusButton>
</PrimusSection>
</Card>
</div>
</div>
</PrimusLayout>
);
}
<primus-layout>
<primus-header
[breadcrumbs]="breadcrumbs"
[title]="tenant.name">
<div header-actions>
<primus-button variant="outline" (clicked)="onEdit()">Edit</primus-button>
<primus-button variant="danger" (clicked)="openSuspend()">Suspend</primus-button>
</div>
</primus-header>
<div style="display:grid;grid-template-columns:1fr 260px;gap:1rem;align-items:start">
<div class="vstack">
<div class="card" style="padding:1.5rem">
<primus-section title="Details">
<div class="detail-grid">
<span>Plan</span> <strong>{{ tenant.plan }}</strong>
<span>Domain</span> <strong>{{ tenant.domain }}</strong>
<span>Region</span> <strong>{{ tenant.region }}</strong>
<span>Created</span> <strong>{{ tenant.createdAt | date }}</strong>
</div>
</primus-section>
</div>
<primus-data-table
[columns]="userColumns"
[data]="tenant.users"
rowKey="id"
[paginated]="true"
[pageSize]="5">
</primus-data-table>
</div>
<div class="vstack">
<div class="card" style="padding:1.25rem">
<primus-section title="Subscription">
<div>MRR: <strong>{{ tenant.mrr }}</strong></div>
<div>Next invoice: <strong>{{ tenant.nextInvoice | date }}</strong></div>
</primus-section>
</div>
<div class="card" style="padding:1.25rem">
<primus-section title="Quick Actions">
<primus-button variant="outline" style="width:100%" (clicked)="sendInvoice()">Send invoice</primus-button>
<primus-button variant="outline" style="width:100%" (clicked)="resetApiKey()">Reset API key</primus-button>
<primus-button variant="outline" style="width:100%" (clicked)="viewAuditLog()">View audit log</primus-button>
</primus-section>
</div>
</div>
</div>
</primus-layout>