Page recipes
tier 2 — classes
Whole pages, composed from the classes on the other pages: the list a record is found in, the
record itself, and the settings behind it. Each one is the content of the shell's
.page — take the frame from Shell.
A list page
A page head whose actions fold into a menu on a narrow screen, keeping the primary one; a
toolbar with the filters on the leading side and the count on the trailing one; a card holding
a sortable table that stacks into cards on a phone; and the pager under it. When no row
matches, the table keeps its head and shows one .tr-empty row, as on
Tables — the page does not swap to an empty state for a filter
that found nothing.
Orders
Every order in the warehouse queue, newest first.
<div class="page-head">
<div class="page-head-text">
<h1>Orders</h1>
<p>Every order in the warehouse queue, newest first.</p>
</div>
<div class="page-head-actions page-head-actions--fold">
<button class="btn" type="button"><i class="ri-download-line"></i> <span>Export</span></button>
<button class="btn btn--brand btn--solid actions-keep" type="button"><i class="ri-add-line"></i> <span>New order</span></button>
<div class="menu-anchor actions-more">
<button class="btn btn--icon" type="button" data-menu-toggle aria-expanded="false" aria-label="More actions">
<i class="ri-more-2-fill"></i>
</button>
<div class="menu" hidden>
<button class="menu-item" type="button"><i class="ri-download-line"></i> <span>Export</span></button>
</div>
</div>
</div>
</div>
<div class="toolbar">
<div class="toolbar-filters">
<input class="form-input toolbar-input toolbar-input--wide" type="search" placeholder="Search orders…" aria-label="Search orders" />
<select class="form-select toolbar-input" aria-label="State">
<option>Any state</option>
<option>Pending</option>
<option>Approved</option>
<option>Rejected</option>
</select>
</div>
<div class="toolbar-actions">
<span class="toolbar-count">3 of 1,204</span>
</div>
</div>
<div class="card">
<table class="table table--stack">
<thead>
<tr>
<th aria-sort="descending"><button class="th-sort" type="button">Order</button></th>
<th aria-sort="none"><button class="th-sort" type="button">State</button></th>
<th>Owner</th>
<th class="col-num" aria-sort="none"><button class="th-sort" type="button">Lines</button></th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="Order"><div><a href="#">ORD-4209</a></div><div class="text-muted">Opened 4 min ago</div></td>
<td data-label="State"><span class="badge badge--warn">Pending</span></td>
<td data-label="Owner">Alex Fischer</td>
<td data-label="Lines" class="col-num">5</td>
</tr>
<tr>
<td data-label="Order"><div><a href="#">ORD-4204</a></div><div class="text-muted">Opened 22 min ago</div></td>
<td data-label="State"><span class="badge badge--go">Approved</span></td>
<td data-label="Owner">Alex Fischer</td>
<td data-label="Lines" class="col-num">12</td>
</tr>
<tr>
<td data-label="Order"><div><a href="#">ORD-4198</a></div><div class="text-muted">Opened 1 h ago</div></td>
<td data-label="State"><span class="badge badge--danger">Rejected</span></td>
<td data-label="Owner">Unassigned</td>
<td data-label="Lines" class="col-num">1</td>
</tr>
</tbody>
</table>
</div>
<nav class="pagination" aria-label="Pagination">
<span class="page-link" aria-disabled="true"><i class="ri-arrow-left-s-line"></i> <span>Previous</span></span>
<a class="page-link" href="#" aria-current="page" aria-label="Page 1">1</a>
<a class="page-link" href="#" aria-label="Page 2">2</a>
<a class="page-link" href="#" aria-label="Page 3">3</a>
<span class="page-gap" aria-hidden="true">…</span>
<a class="page-link" href="#" aria-label="Page 61">61</a>
<a class="page-link" href="#"><span>Next</span> <i class="ri-arrow-right-s-line"></i></a>
<span class="page-count">1–20 of 1,204</span>
</nav>
A detail page
The trail back to the list, a page head naming the record, and .sedna-split: the
record's fields in a card of .kv rows — .kv--text for a value
that is prose — beside an aside holding its history. The aside drops under the card when
the split runs out of room.
ORD-4209
Five lines, three reserved. Raised 31 July at 09:14.
Details
<nav class="breadcrumb" aria-label="Breadcrumb">
<a class="breadcrumb-item" href="#"><i class="ri-home-4-line"></i> <span>Console</span></a>
<a class="breadcrumb-item" href="#"><span>Orders</span></a>
<span class="breadcrumb-item" aria-current="page"><span>ORD-4209</span></span>
</nav>
<div class="page-head">
<div class="page-head-text">
<h1>ORD-4209</h1>
<p>Five lines, three reserved. Raised 31 July at 09:14.</p>
</div>
<div class="page-head-actions page-head-actions--fold">
<button class="btn" type="button"><i class="ri-printer-line"></i> <span>Print</span></button>
<button class="btn" type="button"><i class="ri-file-copy-line"></i> <span>Duplicate</span></button>
<button class="btn btn--go btn--solid actions-keep" type="button"><i class="ri-send-plane-line"></i> <span>Dispatch</span></button>
<div class="menu-anchor actions-more">
<button class="btn btn--icon" type="button" data-menu-toggle aria-expanded="false" aria-label="More actions">
<i class="ri-more-2-fill"></i>
</button>
<div class="menu" hidden>
<button class="menu-item" type="button"><i class="ri-printer-line"></i> <span>Print</span></button>
<button class="menu-item" type="button"><i class="ri-file-copy-line"></i> <span>Duplicate</span></button>
</div>
</div>
</div>
</div>
<div class="sedna-split">
<div class="card">
<div class="card-head"><h3>Details</h3></div>
<div class="card-body">
<div class="kv"><span class="k">Order</span><span class="v">ORD-4209</span></div>
<div class="kv"><span class="k">Region</span><span class="v">EU-Central</span></div>
<div class="kv kv--text"><span class="k">Customer</span><span class="v">Northwind Retail</span></div>
<div class="kv kv--text"><span class="k">Owner</span><span class="v">Alex Fischer, Fulfilment</span></div>
<div class="kv"><span class="k">Priority</span><span class="badge badge--warn">P3</span></div>
</div>
</div>
<aside class="card sedna-split-aside">
<div class="card-head"><strong>History</strong></div>
<div class="card-body">
<ul class="timeline">
<li data-kind="go">
<span class="timeline-when">09:41</span>
<span class="timeline-what">Three lines reserved</span>
</li>
<li data-kind="info">
<span class="timeline-when">09:20</span>
<span class="timeline-what">Assigned to Alex Fischer</span>
</li>
<li>
<span class="timeline-when">09:14</span>
<span class="timeline-what">Order raised from an e-mail</span>
</li>
</ul>
</div>
</aside>
</div>
A settings page
One .form-section per subject, each with a line saying what it is for, and one
.form-actions row for the whole form. A switch applies a choice; Save applies
the fields — if a switch should wait for Save too, make it a checkbox.
Settings
How the queue behaves for you. Saved to your account.
<div class="page-head">
<div class="page-head-text">
<h1>Settings</h1>
<p>How the queue behaves for you. Saved to your account.</p>
</div>
</div>
<form style="max-width:560px">
<fieldset class="form-section">
<legend>Notifications</legend>
<p class="form-section-hint">What reaches you while the queue is open in another tab.</p>
<div class="form-section-body">
<label class="switch">
<input type="checkbox" checked />
<span class="choice-text">
<span>Notify me about new pending orders</span>
<span class="choice-hint">A desktop notification, at most one a minute.</span>
</span>
</label>
<label class="switch"><input type="checkbox" /> <span>Play a sound on new orders</span></label>
<div class="form-field">
<label class="form-label" for="settings-quiet">Quiet hours</label>
<input class="form-input" id="settings-quiet" type="text" value="22:00 – 07:00" />
<p class="form-hint">No notifications in this window. The queue still updates.</p>
</div>
</div>
</fieldset>
<fieldset class="form-section">
<legend>Escalation</legend>
<p class="form-section-hint">Who is paged when nobody has acknowledged an order in time.</p>
<div class="form-section-body">
<div class="form-field">
<label class="form-label form-label--required" for="settings-team">Team</label>
<select class="form-input form-select" id="settings-team" required>
<option selected>Fulfilment</option>
<option>Returns</option>
</select>
</div>
<div class="form-field">
<label class="form-label" for="settings-after">Escalate after</label>
<div class="input-group">
<input class="form-input" id="settings-after" type="number" value="15" />
<span class="input-affix">minutes</span>
</div>
</div>
</div>
</fieldset>
<div class="form-actions">
<button class="btn" type="button">Cancel</button>
<button class="btn btn--brand btn--solid" type="submit">Save</button>
</div>
</form>