Skip to content
kitn AI/UI

Tasks

kai-tasks

Present a list of tasks the user can check off, then confirm in one go — the card stays quiet while the user picks, and only the final confirm fires with the selected ids in a single atomic event.

  • Shadow DOM
  • Select-all with indeterminate state
  • Min / max gating
  • Read-only resolved view

Feed the card via the data property (an object, so set it in JavaScript). Listen for the bubbling kai-card CustomEvent:

const el = document.querySelector('kai-tasks');
el.data = {
selectAll: true,
confirmLabel: 'Run selected',
tasks: [
{ id: 'lint', label: 'Run linter', checked: true },
{ id: 'test', label: 'Run unit tests', checked: true },
{ id: 'build', label: 'Build production bundle' },
],
};
el.addEventListener('kai-card', (e) => {
if (e.detail.kind === 'submit') {
console.log('selected ids:', e.detail.data.selected);
}
});

The element emits three verbs on kai-card:

verbwhenpayload
readyon mount{ kind: 'ready', cardId }
submituser clicks confirm{ kind: 'submit', cardId, data: { selected: string[] } }
errordata is malformed{ kind: 'error', cardId, message }
  • Gating — confirm is enabled when checked count is >= (min ?? (allowEmpty ? 0 : 1)) and <= (max ?? ∞). When max is reached, unchecked rows disable automatically.
  • Resolved state — after receiving submit, set el.resolution = { kind: 'submit', data: { selected: [...] } } to render the read-only summary.

selectAll: true with rows pre-checked; the select-all header goes indeterminate when only some rows are checked.

allowEmpty: false keeps confirm disabled until the user checks something.

min and max cap how many rows the user can pick; over-selection is blocked automatically.

Each task row accepts an optional description — a secondary line for impact notes, caveats, or reversibility hints.

After confirm, set el.resolution to render the chromed summary — checkboxes and confirm button are removed.

An empty tasks array (or malformed definition) triggers the inline error view and emits an error CardEvent.

PropertyTypeDefaultNotes
theme'auto'Color mode (`auto` follows prefers-color-scheme).
dataThe tasks definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { tasks:[…], selectAll, confirmLabel, … }`. Import `TasksCardData` from `@kitn.ai/ui` for the full shape.
cardIdStable card id correlating every emitted CardEvent. Attribute: `card-id`.
headingHeading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`.
resolutionSet when the user resolved this card; renders the read-only view. Property: `el.resolution = { kind:'submit', data:{ selected:[…] } }`.
valueControlled selection (task ids; JS property). When set, it wins over local state.
defaultValueUncontrolled initial selection (task ids; JS property), overlaying per-task `checked`.
disabledfalseFreeze the whole list + Confirm. Attribute: `disabled`.
readonlyfalseDisplay-only: rows can't be toggled and show the default cursor (no pointer, hover, or focus affordances). Keeps the look as-is. Attribute: `readonly`.
MethodSignatureNotes
(taskIds?: string[]): voidSet the checked task ids (local-only, no emit), respecting disabled/max. With no arg, select all toggleable rows.
(taskId: string, checked?: boolean): voidToggle one task by id, honoring the max gate (no `checked` = flip).
(): voidConfirm the current selection: emits the `submit` CardEvent + resolves (only when the min/max gate passes). Named `send`, not `submit`.
(options?: FocusOptions): voidFocus the task group (select-all checkbox if shown, else the first row).
(): voidTrigger the dismiss path (emit `dismiss` + collapse to the re-openable stub).
(): voidRe-open a dismissed card from its stub (emit `reopen`).

This element wraps these SolidJS components — reach for them directly when you need finer control than the props expose.

TasksCard