User
Role
Status
Created
The rules — the data-list page
- The list page is a FULL-WIDTH lister — no grid, no wrapping card (the lister brings its own frame) — in THE STANDARD SHELL (lister.md "Page markup"): the toolbar inside
.lister-main, the Filters toggle (icon + word) + the bulk Actions left, the ONE.btn-primary(New …) right; the list card holding the header (its select-all checkbox first) and the rows; the count and the pager on one.lister-footerline under it; the details as.lister-more-inset. - The collapsible
lister-panelholds two cards: Filters (title + thelister-resetReset link + the close button; the search on top, then the filter fields) and Display (order + page size). Reset — zero page code — restores the authored values and returns to page 1. - Create/edit opens in an OFFCANVAS (
.offcanvas-end; the form wraps header + body +.offcanvas-footerwith the standard button row) on former — fill, dirty guard, save pipeline,refreshpointed at the lister; former treats the parent offcanvas exactly like a modal. Sizes: default 30rem,.offcanvas-size-sm(20rem),-lg(40rem),-xl(max(40rem, 60vw) — floored at -lg),-full(100vw); on a phone (below 576px) every offcanvas is full-width. - Delete — single or bulk — stays a MODAL:
g.confirmwithdanger: true, never a hand-built one. - Row markup follows THE COLUMN STANDARD: one flex line (
d-flex align-items-center) holding the data zone.lister-cols— FIT columns: each cell declares its share, its readable minimum and (when it may hide) its priority (lister-col-w="15" lister-col-min="6rem" lister-col-priority="2"); the lister hides the least important columns by the LIST's own width — open the filter panel or narrow the window and watch Created, then Role, then Status step into the details. Cells space with padding (pe-3), never flex gap; free text getstext-truncate— a long value truncates, the columns never drift. Cell content is the person-cell pattern (tables) + status badges; secondary fields open with the card (THE STANDARD ROW, below). Every hideable cell carrieslister-col="Label": hidden, it shows up by itself at the top of the open details box —renderMoreholds only the fields that never take a column. Long texts go throughh.longText()(the eye button appears only when the text is cut). - Buttons get THEIR OWN column:
.lister-actions, fixed width via--lister-actions-won the lister root (size it to the widest action set), present IDENTICALLY on every row — a row without buttons keeps the empty zone, so text never slides under a neighbour's buttons. - Column ALIGNMENT is positional and automatic (from md up): the FIRST column aligns start; BUTTON columns align end (
.lister-actionsright-aligns its content — the action buttons); DATA columns CENTER; the LAST data column aligns end ONLY when nothing follows it — with an actions column after (this page), it stays centered; on a list without buttons it right-aligns. The lib detects the actions column from--lister-actions-wby itself — zero authoring. Override per cell with thetext-*utilities only when the page genuinely needs a different alignment. - The header row (
.lister-header— the first row of the list card: the select-all checkbox, then ONE.lister-colswith one label per column, in the rows' order) labels the columns; the lib sizes its cells like the rows' and hides a label with its column. The actions-column width is reserved AUTOMATICALLY from--lister-actions-w— never put a.lister-actionsin the header (double reservation); without the automatic one the last label would right-align at the row edge while its column stops before the buttons. Hide the header below the stacking breakpoint. - Row actions have ONE shape, in the row's count: a lone action (fixed or left by the row's status) renders as a bare
.btn-sm .btn-actions-contrastbutton; 2+ actions render the PRIMARY action + a.dropdown-toggle-splitcaret (both.btn-actions-contrast) opening the rest. Visible button AND every.dropdown-item: icon + text; destructive items LAST as.dropdown-item.text-danger, under a.dropdown-dividerwhen mixed with harmless ones, never as the visible half. THE ONE COLOR EXCEPTION: a row whose only action is DESTRUCTIVE renders it bare in the solid.btn-danger(the card below shows it; row actions are never outline;g.confirmstays mandatory). Actions never wrap and the page never authors a second shape: on a phone (or where only the name column would be left) this FIT list turns every row's actions COMPACT by itself — a menu button holding every action + the details caret, derived from the same markup. The size is.btn-smat every width — never author.btn-xson row actions; a list that crowds on mobile scopes the xs metrics below the breakpoint in its routestyle.scss(lister.md "Row actions" has the snippet). No details toggle in the row (THE STANDARD ROW, below). - THE STANDARD ROW (lister.md "The standard row"): the details open on a CARD CLICK —
rowClick: 'expand'+renderMore+lister-more-inseton the root; no caret authored at the row end — on a phone the compact actions bring the round caret back by themselves (a row is hard to tap there). "Details" repeats as a dropdown item markedlister-expand(first, above the divider) for the keyboard and assistive road; a row whose only action is Details renders it as the bare.btn-sm .btn-actions-contrastbutton. The box shows the hidden columns first (label over value), thenrenderMore's own fields in therow g-3 smallgrid — label.text-body-secondaryover value. - The row-action standard governs EVERY list row — hand-rendered rows too (the card below). The color is themable (
$actions-contrast-*in the control panel; a project overrides it inprivate/config/theme.scss— foundation "Project theming"); never substitute another button color (lister.md "Row actions"). - Keyboard comes free: row shortcuts via
lister-key(e/d/n/f here) and?for the overlay — declare them, do not write key handlers. - Empty, loading and error states are the lister's own — never rebuild them (states).
Hand-rendered rows — the same standard, no lister
1. Introduction to the platform
4 materials · quiz · 25 min
Session 12 — Advanced routing
Today 18:00 · 34 attending
Draft certificate — no file attached
Created Aug 9 · never issued
Session 11 — Rendering deep dive
Aug 12 · recording 1h 42m