Connection lost. Reconnecting… attempt 1 of 8
Paused. Your work is held on the server.
Could not reconnect.
This session has expired on the server.
An unhandled error has occurred.
Sedna.UI
v0.17.0 · main

Lists

tier 2 — classes

Rows where a table would be wrong: the fields differ per row, one field dominates and the rest supports it, or each row is something the reader opens rather than compares down a column. One markup, shown as divided rows or as separate cards.

List

A row that navigates is an <a class="list-row"> filling the <li> and a row that acts is a <button class="list-row"> — never a click handler on the <li> — while a non-interactive row stays a <span> and gets no hover, pressed or focus state. .list-main holds the .list-title and the .list-sub under it, and .list-meta is the trailing slot. The action sheet is a list of button rows, and the lockup that names a person is this row with an avatar first.

<div class="card" style="max-width:520px">
    <ul class="list">
        <li>
            <a class="list-row" href="#" aria-current="true">
                <span class="avatar avatar-sm">DR</span>
                <span class="list-main">
                    <span class="list-title">VPN disconnects every few minutes</span>
                    <span class="list-sub">ORD-4204 · EU-West · Alex Fischer</span>
                </span>
                <span class="list-meta">
                    <span class="badge badge-danger">P1</span>
                    <span>22 min</span>
                </span>
            </a>
        </li>
        <li>
            <a class="list-row" href="#">
                <span class="avatar avatar-sm avatar--muted"><i class="ri-robot-line"></i></span>
                <span class="list-main">
                    <span class="list-title">Outlook will not start after the update — a title long enough to need truncating</span>
                    <span class="list-sub">ORD-4209 · EU-Central</span>
                </span>
                <span class="list-meta"><span class="badge badge-warn">P3</span><span>4 min</span></span>
            </a>
        </li>
    </ul>
</div>

Nothing in it

.list-empty is the one <li> a list holds when this view of it is empty — centred, muted, with room for a .state-art drawing. The page-level “nothing here” is an empty state; this is for a list that stays in place among its toolbar and its heading.

  • Nothing is waiting on you.
<div class="card">
    <ul class="list">
        <li class="list-empty">
            <svg class="state-art state-art--sm" aria-hidden="true"><use href="#all-done" /></svg>
            Nothing is waiting on you.
        </li>
    </ul>
</div>

Line count

.list-title and .list-sub show one line with an ellipsis until --list-lines says otherwise: a number clamps after that many lines, and none wraps freely — use it where the supporting line is a sentence, which a translation will make longer. Set it on the list, an <li> or a row to shape every line inside and align the row's leading and trailing slots to the first line; set it on one .list-title or .list-sub to shape that line alone. Row padding follows [data-density] wherever the list sits.

  • Approve Accepts the request as it stands and notifies the requester. The decision is recorded on the order and cannot be withdrawn afterwards.
  • Send back Returns the request to the requester with a comment, so they can correct the amount or add the missing receipt.
  • alex.fischer.notifications.for.approvals@example.com One line with an ellipsis, set on the title alone.
<div class="card" style="max-width:520px">
    <ul class="list" style="--list-lines: none">
        <li>
            <span class="list-row">
                <span class="avatar avatar-sm avatar--muted"><i class="ri-check-double-line"></i></span>
                <span class="list-main">
                    <span class="list-title">Approve</span>
                    <span class="list-sub">Accepts the request as it stands and notifies the requester. The decision is recorded on the order and cannot be withdrawn afterwards.</span>
                </span>
            </span>
        </li>
        <li>
            <span class="list-row">
                <span class="avatar avatar-sm avatar--muted"><i class="ri-arrow-go-back-line"></i></span>
                <span class="list-main">
                    <span class="list-title">Send back</span>
                    <span class="list-sub">Returns the request to the requester with a comment, so they can correct the amount or add the missing receipt.</span>
                </span>
            </span>
        </li>
        <li>
            <span class="list-row">
                <span class="avatar avatar-sm avatar--muted"><i class="ri-mail-line"></i></span>
                <span class="list-main">
                    <span class="list-title" style="--list-lines: 1">alex.fischer.notifications.for.approvals@example.com</span>
                    <span class="list-sub">One line with an ellipsis, set on the title alone.</span>
                </span>
            </span>
        </li>
    </ul>
</div>

List as cards

.list--cards presents the same rows as separate cards — a gap instead of dividers, each row a card surface — for a work list the reader picks from, where rows that run together are hard to tell apart. The markup does not change, so the button reset, hover, focus, disabled, density and sticky group headers all carry over, and aria-current or aria-selected draws a brand border. A .list-meta as the first child of .list-main is a line above the title.

  • Waiting on you 3
  • Decided today 2
<div class="sedna-scroll" style="max-width:420px; max-height:360px; overflow-y:auto">
    <ul class="list list--cards" style="--list-lines: 2">
        <li class="sticky-group-head sticky-group-head--rule" style="--group-head-index: 0">
            Waiting on you
            <span class="sticky-group-count">3</span>
        </li>
        <li>
            <button class="list-row" type="button" aria-current="true">
                <span class="list-main">
                    <span class="list-meta">
                        <span class="badge badge-warn">Over limit</span>
                        <span>ORD-4211</span>
                        <span>12 min</span>
                    </span>
                    <span class="list-title">Refund above the approval limit for a damaged delivery of garden furniture</span>
                    <span class="list-sub" style="--list-lines: 1">Alex Fischer · Northwind Retail · 1,240.00 EUR</span>
                </span>
            </button>
        </li>
        <li>
            <button class="list-row" type="button">
                <span class="list-main">
                    <span class="list-meta">
                        <span class="badge badge-info">Price change</span>
                        <span>ORD-4208</span>
                        <span>40 min</span>
                    </span>
                    <span class="list-title">Discount on a repeat order</span>
                    <span class="list-sub" style="--list-lines: 1">Priya Nair · Northwind Retail · 12 %</span>
                </span>
            </button>
        </li>
        <li>
            <button class="list-row" type="button" disabled>
                <span class="list-main">
                    <span class="list-meta">
                        <span class="badge">Locked</span>
                        <span>ORD-4203</span>
                        <span>1 h</span>
                    </span>
                    <span class="list-title">Credit note for a cancelled subscription, opened by another approver</span>
                    <span class="list-sub" style="--list-lines: 1">Jordan Weiss · Northwind Retail · 89.00 EUR</span>
                </span>
            </button>
        </li>

        <li class="sticky-group-head sticky-group-head--rule" style="--group-head-index: 1">
            Decided today
            <span class="sticky-group-count">2</span>
        </li>
        <li>
            <button class="list-row" type="button">
                <span class="list-main">
                    <span class="list-meta">
                        <span class="badge badge-go">Approved</span>
                        <span>ORD-4196</span>
                        <span>3 h</span>
                    </span>
                    <span class="list-title">Express shipping at no charge</span>
                    <span class="list-sub" style="--list-lines: 1">Alex Fischer · Northwind Retail · 24.90 EUR</span>
                </span>
            </button>
        </li>
        <li>
            <button class="list-row" type="button">
                <span class="list-main">
                    <span class="list-meta">
                        <span class="badge badge-danger">Declined</span>
                        <span>ORD-4190</span>
                        <span>5 h</span>
                    </span>
                    <span class="list-title">Refund without a returned item</span>
                    <span class="list-sub" style="--list-lines: 1">Priya Nair · Northwind Retail · 310.00 EUR</span>
                </span>
            </button>
        </li>
    </ul>
</div>

Stacking group headers

A grouped list in a scroll container where each header pins below the one above it instead of replacing it, so the reader keeps the whole path to where they are — scroll the card. The app supplies one number and nothing else: style="--group-head-index: 2". On a surface your own app paints, set style="--group-head-bg: var(--surface-strong)" on the list; --group-head-fg and --group-head-height are the same escape hatch for the label colour and the pinned height.

<div class="card sedna-scroll" style="max-width:460px; max-height:230px; overflow-y:auto">
    <ul class="list">
        <li class="sticky-group-head" style="--group-head-index: 0">Needs a person</li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">Mailbox quota exceeded on EXCH-02</span>
            <span class="list-sub">TCK-4182 · Contoso Logistics</span>
        </span></a></li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">Shared mailbox — who may reply?</span>
            <span class="list-sub">TCK-4179 · Fabrikam Energy</span>
        </span></a></li>

        <li class="sticky-group-head" style="--group-head-index: 1">Waiting on the customer</li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">VPN certificate renewal</span>
            <span class="list-sub">TCK-3907 · Fabrikam Energy</span>
        </span></a></li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">New starter needs a licence</span>
            <span class="list-sub">TCK-3901 · Contoso Logistics</span>
        </span></a></li>

        <li class="sticky-group-head" style="--group-head-index: 2">Decided today</li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">Password reset for a leaver</span>
            <span class="list-sub">TCK-3888 · Tailspin Freight</span>
        </span></a></li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">Printer offline in room 2.14</span>
            <span class="list-sub">TCK-3870 · Contoso Logistics</span>
        </span></a></li>
    </ul>
</div>

Group headers as a caption

--rule trades the full-width bottom border for a hairline running from the label to the end of the row, so the header reads as a caption over the rows rather than a bar across them; use it where the groups are a state the reader scans past, not a section they land in. A trailing count needs .sticky-group-count, because the rule is the header's own ::after and a pseudo-element is always the last child.

<div class="sedna-scroll" style="max-width:460px; max-height:230px; overflow-y:auto">
    <ul class="list">
        <li class="sticky-group-head sticky-group-head--rule" style="--group-head-index: 0">
            Due soon
            <span class="sticky-group-count">1</span>
        </li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">CAD workstation crashes under load</span>
            <span class="list-sub">TCK-4210 · Contoso Logistics · 2 incidents</span>
        </span></a></li>

        <li class="sticky-group-head sticky-group-head--rule" style="--group-head-index: 1">
            On track
            <span class="sticky-group-count">3</span>
        </li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">Mailbox quota exceeded on EXCH-02</span>
            <span class="list-sub">TCK-4182 · Contoso Logistics</span>
        </span></a></li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">VPN certificate renewal</span>
            <span class="list-sub">TCK-3907 · Fabrikam Energy</span>
        </span></a></li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">New starter needs a licence</span>
            <span class="list-sub">TCK-3901 · Contoso Logistics</span>
        </span></a></li>

        <li class="sticky-group-head sticky-group-head--rule" style="--group-head-index: 2">
            Nothing to do
            <span class="sticky-group-count">2</span>
        </li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">Password reset for a leaver</span>
            <span class="list-sub">TCK-3888 · Tailspin Freight</span>
        </span></a></li>
        <li><a class="list-row" href="#"><span class="list-main">
            <span class="list-title">Printer offline in room 2.14</span>
            <span class="list-sub">TCK-3870 · Contoso Logistics</span>
        </span></a></li>
    </ul>
</div>

The row in other places

.list-row--flush drops the row's own padding where the container already provides it — a table cell, a drawer header, a form row. A row with a progress bar in its subtext is work in progress, and a row inside a card meets the card's edges without a class.