Components

Seven components, rendered from tokens.css and components.css with no page styles of their own. The section patterns that arrange them into a landing page live in sections.css and are shown in the demo.

Button

Four variants and three sizes. Every one keeps a 44px touch target, including the small one, where the visual box shrinks and the target does not.

<button class="sl-btn sl-btn-primary">Start free trial</button>
<button class="sl-btn sl-btn-secondary sl-btn-lg">Book a walkthrough</button>
<a class="sl-btn sl-btn-primary sl-btn-block" href="#">Full width</a>

Card

A surface with a divider border and the smallest shadow. The raised variant is the loudest elevation in the theme, which is why one per screen is the ceiling.

Base

Default

White surface, divider border, the small shadow. This is the card the feature triptych uses.

Muted

A recessed well rather than a raised surface, so it takes the muted ground and drops the shadow entirely.

Link

The whole card is the target. Hover lifts it two pixels and steps the shadow up one place.

<article class="sl-card">
  <div class="sl-card-header">
    <h3 class="sl-card-title">Title</h3>
    <span class="sl-badge sl-badge-neutral">Label</span>
  </div>
  <p class="sl-card-body">Body copy.</p>
  <div class="sl-card-footer"><button class="sl-btn sl-btn-secondary sl-btn-sm">Action</button></div>
</article>

Input

The border on a field is the control border rather than the divider border, which clears the 3:1 non-text floor against all three grounds. The category default of one light grey for every line leaves a form field between 1.2:1 and 1.5:1: Tailwind's gray-200 is 1.24:1 against white and its gray-300 is 1.47:1.

We send the trial link here.
Enter a number between 1 and 500.
<div class="sl-field">
  <label class="sl-label" for="work-email">Work email</label>
  <input class="sl-input" id="work-email" type="email" />
  <span class="sl-hint">We send the trial link here.</span>
</div>

Badge

Coloured text on a pale fill. Every pairing below is measured and recorded in tokens.css, and the lowest of them is 4.74:1.

On track Most chosen Renewed Needs a decision Overdue
<span class="sl-badge sl-badge-success">Renewed</span>

Segmented control

The billing period control, and a radio group rather than a switch. A switch announces as on or off and leaves a screen reader user to work out which price "on" means. Two radios with a legend announce the question and the answer, and the price swap they drive in sections.css is a CSS rule rather than a listener.

Billing period
<fieldset class="sl-segmented">
  <legend class="sl-visually-hidden">Billing period</legend>
  <label class="sl-segmented-option">
    <input type="radio" name="billing" id="billing-monthly" checked /> Monthly
  </label>
  <label class="sl-segmented-option">
    <input type="radio" name="billing" id="billing-annual" /> Annual
  </label>
</fieldset>

Table

The wrapper is part of the component. A four column comparison does not fit a 390px viewport at a readable size, so the region scrolls and carries the tabindex that makes a scrollable area reachable without a pointer.

Two rows from the demo's plan comparison.
Feature Starter Team Enterprise
People included Up to 10 Up to 100 No limit
SSO and directory sync No No Yes
<div class="sl-table-wrap" tabindex="0" role="region" aria-label="Comparison, scrollable">
  <table class="sl-table">
    <caption>What the table is for.</caption>
    <thead><tr><th scope="col">Feature</th><th scope="col">Team</th></tr></thead>
    <tbody><tr><th scope="row">Seats</th><td>Up to 100</td></tr></tbody>
  </table>
</div>