Canvas Design System
Main Site Tokens

Pill

A read-only tag for descriptive metadata — difficulty, topic, format, phase.

When to Use

Use when: You're tagging content with a descriptive attribute that the reader scans — "Beginner", "Remote-friendly", "Design". It replaces the hand-rolled .detail-pill and .ae-difficulty-pill classes that grew across the apps.
Don't use when: The tag can be removed or clicked — use a Chip Input chip or a Button. For a measurement or status use Badge; for an agenda item's type use Activity Badge.

Variants

Style

Three weights of the same tag. tint is the default and the right choice nearly always; solid is for a single pill that must stand out; ghost is for dense rows where fills would overwhelm.

Tint (default) Solid Ghost
<?= ws_pill('Tint (default)', ['variant' => 'tint', 'color' => 'learn']) ?>
<?= ws_pill('Solid', ['variant' => 'solid', 'color' => 'learn']) ?>
<?= ws_pill('Ghost', ['variant' => 'ghost', 'color' => 'learn']) ?>

Colour

Five colour keys. Since Red Unification the four phase keys all resolve to the same red, so in practice the meaningful distinction is phase versus neutral — the four below are identical by design, not by accident. Keep passing the semantically correct phase so the markup stays truthful if the palette ever diverges again.

Learn Plan Facilitate Reflect Neutral
<?= ws_pill('Learn', ['color' => 'learn']) ?>
<?= ws_pill('Neutral', ['color' => 'neutral']) ?>

Sizes and icons

Two sizes. An optional leading icon helps when several pills of different kinds sit in one row.

Small Medium palette Design school Beginner
<?= ws_pill('Small', ['size' => 'sm', 'color' => 'plan']) ?>
<?= ws_pill('Design', ['icon' => 'palette', 'color' => 'facilitate']) ?>

States

StateBehavior
DefaultThe only state. Pills are static <span>s with no hover, focus, active, selected, or disabled treatment.
Unknown colour keyEmits .ws-pill--{key}, which matches no rule — the pill renders with base styling only. Stick to the five documented keys.
Long textPills don't truncate. A long label stretches the pill and can wrap, so keep to one or two words.

Real-World Usage

An exercise detail header: difficulty and format as pills, with the measurable facts left to Badge. The split is the useful rule — pills describe, badges measure.

Assumption Mapping
school Beginner videocam Remote-friendly 30 min
<?= ws_pill($ex['difficulty'], ['icon' => 'school', 'color' => 'learn', 'size' => 'sm']) ?>
<?php if ($ex['remote_friendly']): ?>
    <?= ws_pill('Remote-friendly', ['icon' => 'videocam', 'color' => 'neutral', 'size' => 'sm']) ?>
<?php endif; ?>
<?= ws_duration($ex['duration'] . ' min') ?>

Options

OptionTypeDefaultPurpose
$textstring''Positional label. One or two words.
variantstring'tint'solid | ghost | tint
colorstring'neutral'learn | plan | facilitate | reflect | neutral
sizestring'md'sm | md
iconstringnullOptional leading Material Symbols icon
classstring''Additional CSS classes
attrsarray[]Extra HTML attributes as key/value pairs

Note there's no id option — unlike most components in the set. Pass one through attrs if you need it.

Accessibility

ConcernBehavior
ARIANone applied, and none needed — the pill is text in a <span>, read in document order alongside whatever it labels.
KeyboardNot focusable. If a pill ever needs to filter or toggle, it's the wrong component.
Colour independenceThe label always carries the meaning. Since every phase colour now renders the same red, colour conveys almost nothing on its own — which makes the text mandatory, not optional.
IconsDecorative and unlabelled. Never ship an icon-only pill; there'd be no accessible text at all.
ContrastEach variant/colour pair uses tested tokens. The ghost variant is the lightest — check it against any non-standard background before using it there.

Tokens

TokenUsed for
--phase-learn / --phase-learn-lightLearn colour key, solid and tint fills
--phase-plan / --phase-plan-lightPlan colour key
--phase-facilitate / --phase-facilitate-lightFacilitate colour key
--phase-reflect / --phase-reflect-lightReflect colour key
--gray-100Neutral tint fill
--color-ink / --color-ink-secondaryLabel colour on tint and ghost
--color-border-darkGhost variant border
--radius-fullThe pill shape itself
--text-caption / --text-microLabel size at md and sm
--font-body / --font-semiboldFace and weight

CSS Classes

ClassPurpose
.ws-pillBase styles and the full radius
.ws-pill--tintTinted fill (default)
.ws-pill--solidSolid fill with inverse text
.ws-pill--ghostOutline only
.ws-pill--learn / --plan / --facilitate / --reflectPhase colour keys
.ws-pill--neutralNeutral grey key
.ws-pill--sm / --mdSize modifiers

Files

FilePurpose
includes/components/helpers.phpws_pill() helper function
includes/components/pill.phpTemplate — variant and colour class assembly
includes/components/components.cssStyles (.ws-pill rules)