Component

Button

An ink fill that turns into an outline when you point at it. One primary button per view, two or three words, verb first.

Default

Hover either of the first two: the fill and the outline swap places over 0.4s on the brand spring. That inversion is the whole interaction - there is no shadow, no lift and no colour change.

Variants

ClassWhat it doesWhere
.lr-btnInk fill, mist labelThe one primary action on a page
.lr-btn--outlineStarts as an outline, fills on hoverThe secondary action beside it
.lr-btn--sm6px by 16px paddingInside a card or a header
.lr-btn--whiteWhite fill, ink labelOn a photo or the stage
.lr-btn--blockStretches to its containerAt the bottom of a plan card

On a photo the white button inverts to a 30% white outline rather than to ink, so it stays readable over the sky.

With an icon

A 24px icon with a 12px gap. One icon, on one side. The label still has to make sense on its own.

In a card

Solo

For one person invoicing a handful of clients.

Start for free

Measurements

PropertyDefaultSmall
Padding12px 24px6px 16px
Radius20px, superellipse(1.5)20px, superellipse(1.5)
Border1px solid ink1px solid ink
LabelInter 400, 16px / 1.5, +0.01emInter 400, 16px / 1.5
Icon24px, 12px gap24px, 12px gap
FillInk #27272AInk #27272A
Label colourMist #FAFAFAMist #FAFAFA

States

StateFillLabelBorder
RestInkMistInk
HoverTransparentInkInk
FocusUnchangedUnchangedPlus a 2px ink ring, 3px offset
Rest, outlineTransparentInkInk
Hover, outlineInkMistInk
Rest, whiteWhiteInkWhite
Hover, whiteTransparentWhite30% white

The transition runs 0.4s on --lr-spring across background, colour and border together, so nothing arrives late.

Markup

<a class="lr-btn" href="/signup">Start for free</a>

<button class="lr-btn lr-btn--outline" type="button">Book a demo</button>

<a class="lr-btn lr-btn--sm" href="/invoices/new">
  Send invoice
  <svg class="lr-i" aria-hidden="true"><use href="#i-arrow-right"/></svg>
</a>

Labels

Do. Two or three words, verb first, sentence case.

Don't. Shout, use title case, or write a label that could belong to any button on the page.

How many

One primary button per view. A second action goes beside it as an outline; a third is a text link or it does not belong there.

Do. Pair one ink button with one outline so the eye knows where to go.

Don't. Fill three buttons and let them compete.

Width

  • A button hugs its label. It only stretches with --block, at the bottom of a plan card.
  • On a phone a block button is comfortable; a full-width button in a header is not.
  • Never set a fixed width - Georgian labels run longer than English ones.

Never

  • A gradient fill. The gradient belongs on tiles.
  • A shadow, a lift or a scale on hover.
  • A button inside a button, or a card that is entirely one button.
  • An icon with no label in a place where the icon is not obvious.

Contrast

Mist on ink is 14.3:1 at rest, ink on white 14.9:1 on hover. Both pass at any size. The white variant on a photo relies on the photo, so it needs the stage scrim behind it.

Focus

A 2px ink ring at a 3px offset, never removed. On the white variant the ring turns white so it survives the photo behind it.

.lr-btn:focus-visible { outline: 2px solid var(--lr-ink); outline-offset: 3px; }
.lr-btn--white:focus-visible { outline-color: #fff; }

Semantics

  • A button that navigates is an <a> with an href. A button that acts on the page is a <button>. Never a div.
  • An icon-only button needs aria-label; the icon itself stays aria-hidden.
  • Do not add role="button" to something that is already a button.

Target size

The default button is 48px tall including its border, which clears the 44px touch target on a phone. The small variant is 36px, so keep it off touch surfaces unless it has 8px of clear space around it.

Motion

Only colour moves, so there is nothing to disable - but the system turns the transition off anyway under prefers-reduced-motion, and the hover state still arrives, instantly.