Skip to content

Buttons

.sb-btn is the one button class. Intent, variant and size are separate modifiers that compose, so sb-btn sb-btn-outline sb-btn-danger sb-btn-sm is an outlined, small, danger button. With no modifiers you get a solid, primary, medium button.

Always set type="button" on a <button> that is not meant to submit a form.

<div class="sb-cluster">
<button type="button" class="sb-btn sb-btn-solid">Solid</button>
<button type="button" class="sb-btn sb-btn-soft">Soft</button>
<button type="button" class="sb-btn sb-btn-outline">Outline</button>
<button type="button" class="sb-btn sb-btn-ghost">Ghost</button>
<button type="button" class="sb-btn sb-btn-link">Link</button>
</div>
Class Effect
sb-btn Base button: layout, type, hairline border, focus ring. Defaults to solid, primary, medium.
sb-btn-solid Filled with the intent color and its on-accent ink (the default).
sb-btn-soft Tinted wash of the intent color. The text mixes the intent with the foreground per flavor (--sb-soft-ink) to stay AA on the tint.
sb-btn-outline Transparent with an intent-colored border.
sb-btn-ghost No fill or border until hover. Primary and neutral ghosts use the foreground ink.
sb-btn-link Underlined text without padding or fixed height.

An intent class sets the color the variant uses.

<div class="sb-cluster">
<button type="button" class="sb-btn sb-btn-primary">Primary</button>
<button type="button" class="sb-btn sb-btn-secondary">Secondary</button>
<button type="button" class="sb-btn sb-btn-neutral">Neutral</button>
<button type="button" class="sb-btn sb-btn-info">Info</button>
<button type="button" class="sb-btn sb-btn-success">Success</button>
<button type="button" class="sb-btn sb-btn-warning">Warning</button>
<button type="button" class="sb-btn sb-btn-danger">Danger</button>
</div>
<div class="sb-cluster">
<button type="button" class="sb-btn sb-btn-outline sb-btn-danger">Outline danger</button>
<button type="button" class="sb-btn sb-btn-soft sb-btn-success">Soft success</button>
<button type="button" class="sb-btn sb-btn-ghost sb-btn-info">Ghost info</button>
</div>
Class Color
sb-btn-primary The active accent (default).
sb-btn-secondary Ultraviolet.
sb-btn-neutral The foreground ink (--sb-fg), for low-emphasis actions.
sb-btn-info Info.
sb-btn-success Success.
sb-btn-warning Warning.
sb-btn-danger Danger.
<div class="sb-cluster">
<button type="button" class="sb-btn sb-btn-xs">Extra small</button>
<button type="button" class="sb-btn sb-btn-sm">Small</button>
<button type="button" class="sb-btn sb-btn-md">Medium</button>
<button type="button" class="sb-btn sb-btn-lg">Large</button>
</div>
<div class="sb-cluster">
<button type="button" class="sb-btn sb-btn-outline sb-btn-sm">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/></svg>
Overclock
</button>
</div>
Class Height Horizontal padding Type
sb-btn-xs 1.75rem 0.625rem text-xs
sb-btn-sm 2rem 0.75rem text-sm
sb-btn-md 2.5rem 1rem text-sm (default)
sb-btn-lg 3rem 1.25rem text-base

A direct child <svg> is sized and spaced by the button; it inherits the text color.

sb-btn-icon makes the button square (width equals the size’s height). An icon-only button has no text, so it needs an aria-label.

<div class="sb-cluster">
<button type="button" class="sb-btn sb-btn-icon sb-btn-xs" aria-label="Add"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
<button type="button" class="sb-btn sb-btn-icon sb-btn-sm sb-btn-soft" aria-label="Add"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
<button type="button" class="sb-btn sb-btn-icon sb-btn-md sb-btn-outline" aria-label="Add"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
<button type="button" class="sb-btn sb-btn-icon sb-btn-lg sb-btn-ghost" aria-label="Close"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
<button type="button" class="sb-btn sb-btn-icon sb-btn-md sb-btn-soft sb-btn-danger" aria-label="Delete"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
</div>

sb-btn-block stretches a button to the full width of its container. sb-btn-group joins adjacent buttons into one segmented control; put role="group" and an aria-label on it.

<div class="sb-stack">
<button type="button" class="sb-btn sb-btn-block sb-btn-secondary">Block button</button>
<div class="sb-cluster">
<div class="sb-btn-group" role="group" aria-label="Range">
<button type="button" class="sb-btn">Day</button>
<button type="button" class="sb-btn">Week</button>
<button type="button" class="sb-btn">Month</button>
</div>
<div class="sb-btn-group" role="group" aria-label="Alignment">
<button type="button" class="sb-btn sb-btn-outline sb-btn-sm">Left</button>
<button type="button" class="sb-btn sb-btn-outline sb-btn-sm">Center</button>
<button type="button" class="sb-btn sb-btn-outline sb-btn-sm">Right</button>
</div>
</div>
</div>
Class Effect
sb-btn-icon Square, icon-only button.
sb-btn-block Full-width button.
sb-btn-group Container that squares the inner corners and collapses the borders of child .sb-btn elements.

The CSS keys on these attributes and pseudo-classes; there are no state classes.

<div class="sb-cluster">
<button type="button" class="sb-btn" disabled>Disabled</button>
<button type="button" class="sb-btn sb-btn-soft" aria-disabled="true">aria-disabled</button>
<button type="button" class="sb-btn sb-btn-outline" disabled>Disabled outline</button>
</div>
<div class="sb-cluster">
<button type="button" class="sb-btn" aria-busy="true"><span>Saving</span></button>
<button type="button" class="sb-btn sb-btn-soft sb-btn-info" aria-busy="true"><span>Loading</span></button>
<button type="button" class="sb-btn sb-btn-outline sb-btn-success" aria-busy="true"><span>Syncing</span></button>
</div>
Selector Effect
:hover A small bloom, plus per variant: solid lightens its fill, outline takes the soft tint, ghost the raised panel fill, and soft keeps its tint. Text on a tint or fill switches to the soft ink so it stays AA. Not applied to disabled or aria-disabled buttons.
:active Moves down 1px and drops the bloom. Not applied to disabled or aria-disabled buttons.
:focus-visible Keyboard focus ring.
:disabled Dimmed, not-allowed cursor, no pointer feedback.
[aria-disabled="true"] Same look as :disabled for elements that must stay focusable. Set the behavior yourself; the attribute does not block clicks.
[aria-busy="true"] Loading: the label is hidden and a ring spinner is drawn over it. The button ignores pointer input. Wrap the text in a child element such as a <span> so it can be hidden without changing the button’s width.
  • Buttons are plain elements, so they work in OPEN//77’s CEF pages exactly as on a website.
  • Use aria-busy="true" rather than swapping the label for a spinner; the button keeps its width and the screen reader still announces its name.
  • The Vue components share this visual spec; see the Vue components for SbButton.