Tessera UI

Components

Spinner

Shows that something is loading. It is announced to a screen reader with the label.

The preview needs JavaScript. The code is in the Code tab.

Spinner-0.tess
<template>
  <div>
    <Spinner size="sm">Loading</Spinner>
    <Spinner>Saving your changes</Spinner>
    <Spinner size="lg">Uploading</Spinner>
  </div>
</template>

Installation

npx @pixelscriptio/tessera add Spinner
pnpm exec tessera add Spinner
yarn tessera add Spinner
bunx @pixelscriptio/tessera add Spinner
  • Works with Tessera 0.9.0 or newer.
  1. Copy and paste the code into your project

    Put it in system/components.

    system/components/Spinner.tess
    <contract>
    {
      "name": "Spinner",
      "role": "status",
      "description": "Shows that something is loading. It is announced to a screen reader with the label.",
      "since": "0.8.0",
      "parts": ["root", "ring", "label"],
      "variants": {
        "size": ["md", "sm", "lg"] // first value is the default
      },
      "slots": {
        "default": "the label, announced and not shown; Loading when empty"
      },
      "preview": {
        "slots": {
          "default": "Loading"
        }
      }
    }
    </contract>
    
    <template>
      <span class="root" role="status">
        <span class="ring" aria-hidden="true"></span>
        <span class="label"><slot>Loading</slot></span>
      </span>
    </template>
    
    <style>
    .root {
      display: inline-flex;
      color: $color.text.default;
    }
    
    .ring {
      width: $space.5;
      height: $space.5;
      border: 2px solid $color.border.default;
      border-top-color: currentColor;
      border-radius: $radius.full;
      animation: spin 0.8s linear infinite;
    }
    
    .root[data-size='sm'] .ring {
      width: $space.4;
      height: $space.4;
    }
    
    .root[data-size='lg'] .ring {
      width: $space.8;
      height: $space.8;
      border-width: 3px;
    }
    
    .label {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
    }
    
    @keyframes spin {
      to {
        transform: rotate(360deg);
      }
    }
    
    @media (prefers-reduced-motion: reduce) {
      .ring {
        animation: none;
      }
    }
    </style>
    
  2. Check your design tokens

    Your design system needs these. tessera add reports the ones that are missing; by hand, run npx @pixelscriptio/tessera check.

    color.border.default color.text.default radius.full space.4 space.5 space.8

Usage

Using Spinner

Shows that something is loading.

  • The text you give it is announced to a screen reader and not shown. With none it says "Loading". Say what is loading when more than one thing might be: Saving your changes.
  • It is a status, so it is announced politely when it appears. Remove it when the work is done.
  • For people who prefer less motion it stops turning, and the announced text still says what is happening.
  • To show where the content will go, use a Skeleton too.

The preview needs JavaScript. The code is in the Code tab.

Spinner-0.tess
<template>
  <div>
    <Spinner size="sm">Loading</Spinner>
    <Spinner>Saving your changes</Spinner>
    <Spinner size="lg">Uploading</Spinner>
  </div>
</template>

API reference

Variants

VariantValues
sizemd default sm lg

Slots

SlotContent
defaultthe label, announced and not shown; Loading when empty

Anatomy

Rolestatus
Partsroot ring label
Since0.8.0

Design tokens it uses

Your design system needs these. tessera add checks that it has them, and can add the ones it lacks.

color.border.default color.text.default radius.full space.4 space.5 space.8

Checksum

5a3ba65ebd28880ba0d1edded2df849045404a1eb51cb335058e706f891d2271