Primitives
The parts every element is built from, in @contraagent/elements/primitives.
Most are template functions that a Lit element calls in its render(); their
look comes from the element’s styles, which start from base
(@contraagent/elements/styles: the tokens, the status rules, chips, layout
and motion).
Reference: <cae-segmented>
A tone is the status colour a value takes: failed, attention, done,
running, muted, or neutral (the text colour). The names are the token
names (--ca-status-<tone>, Theming). An element shows a tone as
data-tone, and neutral as no attribute (toneAttr).
/** A status colour, or `neutral` for the text colour. */export type Tone = 'failed' | 'attention' | 'done' | 'running' | 'muted' | 'neutral';
/** Every tone with a status colour (a `data-tone` value): each but `neutral`. */Statuses, legends and facts
Section titled “Statuses, legends and facts”pill draws a status as a pill, statusWord as a word in a row, and
statusChip in a class the element styles. Each sets data-tone and, where a
mark belongs, data-mark (✓ done, ✕ failed, ◌ pending): the mark is drawn by
CSS and hidden from screen readers, which read the word. A pill also has the
parts pill and tone-<tone>.
legend draws a list of entries, each a swatch (a colour, a tone and a shape,
a class, or an icon of its own) and its word; add legendStyles to the
element’s styles. factLine draws a row of facts separated by | that
breaks between facts, never inside one; a fact with a tone is in its status
colour.
// Statuses, a legend and a row of facts, drawn by the primitives into an element// of your own: its styles start from `base` (the tokens and the status rules),// plus `legendStyles` for the legend.import { base, factLine, legend, legendStyles, pill, statusWord } from '@contraagent/elements';import { LitElement, html } from 'lit';
class BuildSummary extends LitElement { static override styles = [base, legendStyles];
override render() { return html`<p> ${pill({ text: 'passed', tone: 'done' })} ${pill({ text: 'failed', tone: 'failed', title: 'exit code 2' })} ${pill({ text: 'running', tone: 'running' })} ${statusWord({ text: 'queued', tone: 'attention' })} </p> <p class="meta words">${factLine(['12 jobs', { text: '1 failed', tone: 'failed' }, '4m 05s'])}</p> ${legend( [ { label: 'passed', tone: 'done', shape: 'round' }, { label: 'failed', tone: 'failed', shape: 'square' }, { label: 'queued', tone: 'attention', shape: 'ring' }, ], { label: 'Job states' }, )}`; }}
export function mount(host: HTMLElement): void { if (!customElements.get('build-summary')) customElements.define('build-summary', BuildSummary); host.replaceChildren(document.createElement('build-summary'));}icon(name, label) draws a glyph, or a template registered under name with
registerIcon. Without a label it is hidden from screen readers; with one, the
label is its tooltip and what a screen reader reads.
The segmented control
Section titled “The segmented control”<cae-segmented> is one choice among a few: a radio group, one tab stop, the
arrow keys, Home and End to choose. It sends cae-change with the chosen
value; the host keeps value.
// A segmented control: one choice among a few. The host holds the value and// answers `cae-change`; the words are the host's.import '@contraagent/elements/segmented/define';
export function mount(host: HTMLElement): void { const control = document.createElement('cae-segmented'); control.label = 'Period'; control.options = [ { value: 'day', label: 'Day' }, { value: 'week', label: 'Week' }, { value: 'month', label: 'Month', title: 'The last 30 days' }, ]; control.value = 'week'; const shown = document.createElement('p'); shown.textContent = `Showing: ${control.value}`; control.addEventListener('cae-change', (e) => (shown.textContent = `Showing: ${e.detail.value}`)); host.replaceChildren(control, shown);}Keyboard and long lists
Section titled “Keyboard and long lists”RovingFocusController gives a group of items one tab stop and moves the
focus with the arrow keys, in a row, a column or a grid (rovingStep is the
rule). windowRows is the arithmetic for drawing only the rows of a long list
that are on screen.
/** The first row drawn. */ from: number; /** The row after the last drawn. */ to: number; /** The height that stands for the rows above `from`. */ padTop: number; /** The height that stands for the rows from `to` on. */ padBottom: number;}
/** * The rows of `total` rows of `rowHeight` px that a viewport of `viewport` px, * scrolled to `scrollTop`, shows, with `overscan` more rows on each side. */