Pill
A read-only tag for descriptive metadata — difficulty, topic, format, phase.
When to Use
.detail-pill and .ae-difficulty-pill classes that grew across the apps.
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.
<?= 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.
<?= 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.
<?= ws_pill('Small', ['size' => 'sm', 'color' => 'plan']) ?>
<?= ws_pill('Design', ['icon' => 'palette', 'color' => 'facilitate']) ?>States
| State | Behavior |
|---|---|
| Default | The only state. Pills are static <span>s with no hover, focus, active, selected, or disabled treatment. |
| Unknown colour key | Emits .ws-pill--{key}, which matches no rule — the pill renders with base styling only. Stick to the five documented keys. |
| Long text | Pills 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.
<?= 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
| Option | Type | Default | Purpose |
|---|---|---|---|
$text | string | '' | Positional label. One or two words. |
variant | string | 'tint' | solid | ghost | tint |
color | string | 'neutral' | learn | plan | facilitate | reflect | neutral |
size | string | 'md' | sm | md |
icon | string | null | Optional leading Material Symbols icon |
class | string | '' | Additional CSS classes |
attrs | array | [] | 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
| Concern | Behavior |
|---|---|
| ARIA | None applied, and none needed — the pill is text in a <span>, read in document order alongside whatever it labels. |
| Keyboard | Not focusable. If a pill ever needs to filter or toggle, it's the wrong component. |
| Colour independence | The 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. |
| Icons | Decorative and unlabelled. Never ship an icon-only pill; there'd be no accessible text at all. |
| Contrast | Each variant/colour pair uses tested tokens. The ghost variant is the lightest — check it against any non-standard background before using it there. |
Tokens
| Token | Used for |
|---|---|
--phase-learn / --phase-learn-light | Learn colour key, solid and tint fills |
--phase-plan / --phase-plan-light | Plan colour key |
--phase-facilitate / --phase-facilitate-light | Facilitate colour key |
--phase-reflect / --phase-reflect-light | Reflect colour key |
--gray-100 | Neutral tint fill |
--color-ink / --color-ink-secondary | Label colour on tint and ghost |
--color-border-dark | Ghost variant border |
--radius-full | The pill shape itself |
--text-caption / --text-micro | Label size at md and sm |
--font-body / --font-semibold | Face and weight |
CSS Classes
| Class | Purpose |
|---|---|
.ws-pill | Base styles and the full radius |
.ws-pill--tint | Tinted fill (default) |
.ws-pill--solid | Solid fill with inverse text |
.ws-pill--ghost | Outline only |
.ws-pill--learn / --plan / --facilitate / --reflect | Phase colour keys |
.ws-pill--neutral | Neutral grey key |
.ws-pill--sm / --md | Size modifiers |
Files
| File | Purpose |
|---|---|
includes/components/helpers.php | ws_pill() helper function |
includes/components/pill.php | Template — variant and colour class assembly |
includes/components/components.css | Styles (.ws-pill rules) |