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.
DR.Simple_UI
Showing main. This can be ahead of the version your app has installed — check what a class says it needs before copying it. Releases (opens in a new tab)

Utilities

tier 2 — classes

Single-purpose classes, in @layer dr.utilities. Not a utility framework — the point of tier 2 is semantic classes, and a page assembled out of fifteen utilities has moved its design decisions into the markup where nobody reviews them.

The cascade layer is what makes these work. A utility is (0,1,0) and a component rule like .table th, .table td is (0,1,1), so a utility loses on specificity alone. dr.utilities sits after dr.paint, so .text-end on a table cell wins regardless of it.
What is deliberately not here. No numeric spacing scale, no colour utilities — that is what tokens are for — no display utilities, because .dr-row and .dr-col already say it with meaning, and no breakpoint prefixes, because the library has no breakpoint vocabulary and should not gain one.

Rows and columns

.dr-row, .dr-row-wrap and .dr-col are the arrangements that would otherwise be an inline style="display:flex; gap:8px" — which is most of them. .dr-push pushes everything after it to the far end.

These carry the dr- prefix because they are library-owned utilities in a shared namespace, where .row and .col are names an app is very likely to have already.

ORD-4182 Awaiting stock
<div class="dr-row dr-w-full" style="border:1px solid var(--border); padding:10px">
    <strong class="text-mono">ORD-4182</strong>
    <span class="badge badge-warn">Awaiting stock</span>
    <span class="dr-push"></span>
    <button class="btn btn-sm" type="button">Open</button>
    <button class="btn btn-sm btn-primary" type="button">Dispatch</button>
</div>

Gaps

.dr-row and .dr-col carry one gap. These four override it: .dr-gap-0 removes it, and 1, 2 and 3 are 8px, 12px and 20px from the spacing scale.

dr-gap-0no gapat all
dr-gap-18pxthe default
dr-gap-212px
dr-gap-320px
<div class="dr-col dr-gap-3">
    <div class="dr-row dr-gap-0">
        <span class="badge">dr-gap-0</span><span class="badge">no gap</span><span class="badge">at all</span>
    </div>
    <div class="dr-row dr-gap-1">
        <span class="badge">dr-gap-1</span><span class="badge">8px</span><span class="badge">the default</span>
    </div>
    <div class="dr-row dr-gap-2">
        <span class="badge">dr-gap-2</span><span class="badge">12px</span>
    </div>
    <div class="dr-row dr-gap-3">
        <span class="badge">dr-gap-3</span><span class="badge">20px</span>
    </div>
</div>

Alignment

.dr-row centres on the cross axis. .dr-start is what a row of fields with labels wants; .dr-baseline is what a row of text at different sizes wants. .dr-between pushes the ends apart, and .dr-wrap allows a second line.

dr-start Two lines,top-aligned.
dr-baseline Large and small, on one baseline.
dr-end Two lines,bottom-aligned.
dr-between pushed apart
dr-wrap onto a second line when needed
<div class="dr-col dr-gap-2">
    <div class="dr-row dr-start" style="border:1px dashed var(--border); padding:8px">
        <span class="badge">dr-start</span>
        <span class="dr-col dr-gap-0"><span>Two lines,</span><span>top-aligned.</span></span>
    </div>
    <div class="dr-row dr-baseline" style="border:1px dashed var(--border); padding:8px">
        <span class="badge">dr-baseline</span>
        <span class="text-lg">Large</span>
        <span class="text-sm">and small, on one baseline.</span>
    </div>
    <div class="dr-row dr-end" style="border:1px dashed var(--border); padding:8px">
        <span class="badge">dr-end</span>
        <span class="dr-col dr-gap-0"><span>Two lines,</span><span>bottom-aligned.</span></span>
    </div>
    <div class="dr-row dr-between" style="border:1px dashed var(--border); padding:8px">
        <span class="badge">dr-between</span>
        <span class="text-muted">pushed apart</span>
    </div>
    <div class="dr-row dr-wrap" style="max-width:260px; border:1px dashed var(--border); padding:8px">
        <span class="badge">dr-wrap</span>
        <span class="badge">onto</span>
        <span class="badge">a second</span>
        <span class="badge">line</span>
        <span class="badge">when needed</span>
    </div>
</div>

Sizing and spacing

.dr-fill is the flex child that takes the remaining room, and it includes min-width: 0 — without which the child refuses to shrink below its content and every ellipsis inside it stops working. .dr-shrink-0 is the opposite, for the avatar and the badge that must not compress.

.dr-mt-* and .dr-mb-* are block margins only, in the same four steps. There is no inline pair: horizontal placement belongs to the layout, not to a utility on the child. .dr-scroll-x creates a horizontal scroller — .dr-scroll styles one, which is a different job.

JW A very long single line that has to be cut rather than push the badge out of the row dr-fill
dr-center Two lines,centred on the cross axis.

dr-mt-0 kills a component's own top margin; dr-mb-1 adds 8px.

dr-mt-1 and dr-mb-2 — 8px above, 12px below.

dr-mt-2 and dr-mb-3 — 12px above, 20px below.

dr-mt-3 adds 20px; dr-mb-0 removes the last bottom margin.

OrderCustomerRegionWarehouseTotal
ORD-4182Priya NairEU-WestRotterdam1,240.00
<div class="dr-col dr-gap-2" style="max-width:420px">
    <div class="dr-row" style="border:1px dashed var(--border); padding:8px">
        <span class="avatar avatar-sm dr-shrink-0">JW</span>
        <span class="dr-fill text-truncate">
            A very long single line that has to be cut rather than push the badge out of the row
        </span>
        <span class="badge dr-shrink-0">dr-fill</span>
    </div>
    <div style="border:1px dashed var(--border); padding:8px">
        <button class="btn dr-w-full">dr-w-full</button>
    </div>
    <div class="dr-row dr-center" style="border:1px dashed var(--border); padding:8px">
        <span class="badge">dr-center</span>
        <span class="dr-col dr-gap-0"><span>Two lines,</span><span>centred on the cross axis.</span></span>
    </div>
    <div class="dr-col dr-gap-0" style="border:1px dashed var(--border); padding:8px">
        <p class="dr-mt-0 dr-mb-1">dr-mt-0 kills a component's own top margin; dr-mb-1 adds 8px.</p>
        <p class="dr-mt-1 dr-mb-2">dr-mt-1 and dr-mb-2 — 8px above, 12px below.</p>
        <p class="dr-mt-2 dr-mb-3">dr-mt-2 and dr-mb-3 — 12px above, 20px below.</p>
        <p class="dr-mt-3 dr-mb-0">dr-mt-3 adds 20px; dr-mb-0 removes the last bottom margin.</p>
    </div>
    <div class="dr-scroll-x dr-scroll" tabindex="0" role="group" aria-label="Order detail table"
         style="border:1px dashed var(--border)">
        <table class="table" style="min-width:640px">
            <thead><tr><th>Order</th><th>Customer</th><th>Region</th><th>Warehouse</th><th class="col-num">Total</th></tr></thead>
            <tbody><tr><td>ORD-4182</td><td>Priya Nair</td><td>EU-West</td><td>Rotterdam</td><td class="col-num">1,240.00</td></tr></tbody>
        </table>
    </div>
</div>

Text

The alignment utilities are logical (start / end), so they mirror with the document direction like everything else in the library.

.text-truncate is one line with an ellipsis and includes min-width: 0 for the same reason as .dr-fill. .text-clamp-2 and -3 cut after that many lines. .text-break breaks inside a word when there is nowhere else — an id, a URL, a path in a narrow column.

.text-sm and .text-lg are one type step either side of the body size, for a line that has to be quieter or louder without becoming a heading.

Default alignment1,204
Muted86
whk_live_8f2c1d0
.text-nowrap .text-start .text-center
A single line long enough that it has to be cut with an ellipsis rather than wrapped kept

.text-clamp-3 cuts after three lines with an ellipsis, however long the text is. This paragraph is deliberately longer than two lines so that the cut is visible, and it goes on for a while after that to make the point.

.text-break/pipelines/eu-west/reconciliation-2026-08-03T12-04-31Z.ndjson

.text-sm default .text-lg
<div class="dr-col" style="max-width:420px">
    <table class="table">
        <tr><td>Default alignment</td><td class="text-end text-nums">1,204</td></tr>
        <tr><td class="text-muted">Muted</td><td class="text-end text-nums">86</td></tr>
        <tr><td class="text-mono">whk_live_8f2c1d</td><td class="text-end text-nums">0</td></tr>
    </table>
    <div class="dr-row" style="border:1px solid var(--border); padding:8px">
        <span class="text-nowrap">.text-nowrap</span>
        <span class="text-start dr-fill">.text-start</span>
        <span class="text-center dr-fill">.text-center</span>
    </div>
    <div class="dr-row" style="border:1px solid var(--border); padding:8px">
        <span class="text-truncate">A single line long enough that it has to be cut with an ellipsis rather than wrapped</span>
        <span class="badge dr-shrink-0">kept</span>
    </div>
    <p class="text-clamp-3 dr-mb-0" style="border:1px solid var(--border); padding:8px">
        .text-clamp-3 cuts after three lines with an ellipsis, however long the text is. This
        paragraph is deliberately longer than two lines so that the cut is visible, and it goes on
        for a while after that to make the point.
    </p>
    <p class="text-break dr-mb-0 text-mono" style="border:1px solid var(--border); padding:8px; max-width:200px">
        .text-break/pipelines/eu-west/reconciliation-2026-08-03T12-04-31Z.ndjson
    </p>
    <div class="dr-row">
        <span class="text-sm">.text-sm</span>
        <span>default</span>
        <span class="text-lg">.text-lg</span>
    </div>
</div>

Hidden, but not gone

.visually-hidden takes text out of the rendering and leaves it in the accessibility tree — a name for an icon-only control, a table caption, the target of an aria-describedby. Add --focusable and it comes back when reached by keyboard, which is how a skip link works.

Focus me with Tab to reveal this link
Reloading — this content is stale and not interactive.
Reserved space follows: invisible but still occupying its width
<div class="dr-col" style="max-width:420px">
    <a class="btn visually-hidden visually-hidden--focusable" href="#utilities">
        Focus me with Tab to reveal this link
    </a>
    <div class="card dr-busy" aria-busy="true">
        <div class="card-body">Reloading — this content is stale and not interactive.</div>
    </div>
    <div class="dr-row">
        <span>Reserved space follows:</span>
        <span class="dr-invisible">invisible but still occupying its width</span>
    </div>
</div>

State, dividers and print

.dr-busy dims a block and stops interaction while it reloads. Pair it with aria-busy="true", which is the part that is announced.

.dr-invisible is not a replacement for the hidden attribute: use the attribute, which also removes the element from the accessibility tree and the tab order. This is only for hiding something that must keep its space.

.dr-disabled is for something unavailable that is not a <button>, <input> or <a> — those have the disabled attribute, which is announced and removes them from the tab order, and this is no substitute for it. Add aria-disabled="true" alongside.

.dr-divider-top and -bottom are a hairline between rows without an <hr>. .dr-no-print and .dr-print-only are the two every printed page needs.

Reloading — this content is stale and not interactive.
Reserved space follows: invisible but still occupying its width
A row with .dr-divider-bottom 1
and another 2
Export (not available)
.dr-no-print — on screen only .dr-print-only — on paper only
<div class="dr-col" style="max-width:460px">
    <div class="card dr-busy" aria-busy="true">
        <div class="card-body">Reloading — this content is stale and not interactive.</div>
    </div>
    <div class="dr-row">
        <span>Reserved space follows:</span>
        <span class="dr-invisible">invisible but still occupying its width</span>
    </div>
    <div class="dr-col dr-gap-0">
        <div class="dr-row dr-divider-bottom" style="padding:8px 0">
            <span class="dr-fill">A row with .dr-divider-bottom</span>
            <span class="badge">1</span>
        </div>
        <div class="dr-row dr-divider-bottom" style="padding:8px 0">
            <span class="dr-fill">and another</span>
            <span class="badge">2</span>
        </div>
    </div>
    <div class="dr-row">
        <span class="dr-disabled" aria-disabled="true"><i class="ri-download-2-line"></i> Export (not available)</span>
    </div>
    <div class="dr-row">
        <span class="dr-no-print">.dr-no-print — on screen only</span>
        <span class="dr-print-only">.dr-print-only — on paper only</span>
    </div>
</div>