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)

Buttons

tier 2 — classes

.btn is the base; every variant is one extra class. A panel's primary call to action is always a filled button in its semantic colour.

Choose a variant by meaning, not appearance.
ClassUse for
.btn-primaryThe neutral primary action
.btn-goSends something outward — approve, apply, send, reroute
.btn-warn-solidChanges who is in control — accept and take over
.btn-warnThe same action as a secondary, beside a green primary
.btn-dangerDestructive
Icons come from Remix Icon, bundled in the package. Link _content/DR.Simple_UI/lib/remixicon/remixicon.css and use ri-* classes on an <i>. Browse all 3,245 at remixicon.com.

Variants

The full set, all at the same height.

<button class="btn">Neutral</button>
<button class="btn btn-primary">Primary</button>
<button class="btn btn-go"><i class="ri-check-line"></i> Approve &amp; send</button>
<button class="btn btn-warn-solid"><i class="ri-user-shared-line"></i> Accept &amp; take over</button>
<button class="btn btn-warn">Take over</button>
<button class="btn btn-danger"><i class="ri-delete-bin-line"></i> Delete</button>
<button class="btn" disabled>Disabled</button>

Three sizes

.btn-sm, the default, and .btn-lg. Every control that can share a row takes the same three heights — 28px, 36px and 44px — so a button, a link, an icon button, a field and a chip line up at every size.

A badge does not: it is a label rather than a target, so it has its own scale that lines up with text instead.

Small chip Small link
Default chip Default link
Large link
<div class="dr-col dr-gap-2">
    <div class="dr-row-wrap">
        <button class="btn btn-sm">Small</button>
        <button class="btn btn-sm btn-primary"><i class="ri-check-line"></i> Small</button>
        <button class="btn btn-sm btn-icon" aria-label="Small icon"><i class="ri-refresh-line"></i></button>
        <span class="chip"><span class="chip-label">Small chip</span></span>
        <a class="btn btn-sm" href="#sizes">Small link</a>
    </div>
    <div class="dr-row-wrap">
        <button class="btn">Default</button>
        <button class="btn btn-primary"><i class="ri-check-line"></i> Default</button>
        <button class="btn btn-icon" aria-label="Default icon"><i class="ri-refresh-line"></i></button>
        <span class="chip chip-lg"><span class="chip-label">Default chip</span></span>
        <a class="btn" href="#sizes">Default link</a>
    </div>
    <div class="dr-row-wrap">
        <button class="btn btn-lg">Large</button>
        <button class="btn btn-lg btn-primary"><i class="ri-check-line"></i> Large</button>
        <button class="btn btn-lg btn-icon" aria-label="Large icon"><i class="ri-refresh-line"></i></button>
        <a class="btn btn-lg" href="#sizes">Large link</a>
    </div>
</div>

Icon-only

.btn-icon is not optional. A bare .btn keeps its text padding, so one glyph sits in a box half again as wide as it is tall — and next to a .btn-icon elsewhere in the same app the two do not match. .btn-icon squares it against .btn's own min-height, so it lines up with the text buttons beside it in both directions.

Give every icon-only button an aria-label — there is no text for a screen reader to read — and a data-tip when the glyph alone does not say what will happen. .btn-sm squares to the smaller size with it.

<button class="btn">Return to queue</button>
<button class="btn btn-icon" aria-label="Refresh" data-tip="Reload the list from the server."><i class="ri-refresh-line"></i></button>
<button class="btn btn-icon" aria-label="Copy link" data-tip="Copy a direct link to this item to the clipboard."><i class="ri-link"></i></button>
<button class="btn btn-icon btn-primary" aria-label="Save"><i class="ri-save-line"></i></button>
<button class="btn btn-icon btn-sm" aria-label="Unpin"><i class="ri-pushpin-line"></i></button>

Ghost

.btn-ghost defers its border and fill until hover, for a dense row of secondary actions — a table row's actions, a toolbar. Everything the button does is still there; only the chrome waits. It keeps the same box as a bordered button, so a ghost and a solid button in one row still line up.

<button class="btn btn-ghost btn-icon" type="button" aria-label="More actions" data-tip="Rename, duplicate, export."><i class="ri-more-2-fill"></i></button>
<button class="btn btn-ghost" type="button"><i class="ri-eye-line"></i> Preview</button>
<button class="btn btn-ghost btn-sm" type="button"><i class="ri-download-2-line"></i> Export</button>
<button class="btn" type="button">Reassign</button>

A name that is read but not shown

.visually-hidden takes text out of the rendering and leaves it in the accessibility tree. Use it where aria-label would replace a name the reader can already partly see — here the button shows a count, and the hidden span says what the count is of. It is not display:none or a zero-size box: both drop the element from the accessibility tree too, which is the opposite of the point.

Continue to the approval step
<button class="btn">
    <i class="ri-notification-3-line"></i> 12
    <span class="visually-hidden">unread notifications</span>
</button>
<a class="btn btn-primary" href="#skip-target">
    Continue <span class="visually-hidden">to the approval step</span>
</a>

.btn works on an <a> — it sets its own text-decoration and colour, so no reset is needed.

<a class="btn" href="#"><i class="ri-external-link-line"></i> Open in the warehouse</a>
<a class="btn btn-sm" href="#">Details</a>

Cancel on the left of the primary, primary last — the reading order ends on the action.

<div class="modal-footer" style="width:100%; border-top:none; padding:0;">
    <button class="btn">Cancel</button>
    <button class="btn btn-go"><i class="ri-send-plane-line"></i> Approve &amp; send</button>
</div>

Floating action button

.fab is one page-level action, pinned to a corner on a screen too small to show a toolbar. Deliberately not a general pattern: a second one has no obvious place, and the first already covers whatever is under it. .fab--icon is the circular, label-in-an-aria-label form.

It sits on the topbar's z-index rung — chrome at the same level, and it must stay below every overlay so a modal covers it. Shown here position:static; in an app it is fixed to the corner.

<div class="dr-row-wrap">
    <button class="fab" type="button" style="position:static">
        <i class="ri-add-line"></i> New order
    </button>
    <button class="fab fab--icon" type="button" style="position:static" aria-label="New order">
        <i class="ri-add-line"></i>
    </button>
</div>