Draft the OKR for Q3
Outline goals, key results, and timelines for the next quarter.
Schema-driven task card with time-aware color coding, popup and inline editing, clipboard and drag-drop payloads, and permission predicates.
Task Card is a time-aware task renderer for workflow apps, content schedulers, and agent run-queues. It carries the standard task fields (name, description, status, active, target/creator person, multi-image, multi-link, dates) and paints urgency onto the card border via an OKLCH ramp (green → red, urgency direction; past expireAt pins full red). The engine accepts setAt + startAt + expireAt OR duration with deterministic precedence (expireAt wins). Two edit modes ship in v0.1: a popup dialog form (default) and an inline-toggle mode (editable=true) where fields swap to inputs in place. JSON I/O mirrors card-tree patterns — controlled (value) or uncontrolled (defaultValue), 12-method imperative handle (getValue / getTree / isDirty / markClean / focusItem / copy / paste / setBorderColor / toggleActive / setLocked / openEdit / closeEdit), clipboard via application/x-ilinxa-task+json MIME + Cmd/Ctrl+C/V, HTML5 DnD with the same payload. Granular events (onFieldEdited / onStatusChanged / onItemAdded / onItemRemoved / onItemMoved / onColorOverridden / onActiveToggled / onLockedToggled / onCopy / onPaste / onChange) cover every mutation. Permissions mirror card-tree: declarative permissions matrix (default / byLevel / byItem with inherit cascade) + six per-action predicates + onPermissionDenied for analytics. Companion: ships taskCardKanbanRenderer for kanban-board with dragHandle:'shell' (v0.3 — the whole card is the drag activator; the adapter passes canDragItem={()=>false} to disable the card's own HTML5 drag so the two DnD systems don't fight). Per-card collapsibility (chevron in header) hides body + nested children to compact deep trees. v0.3 adds: a two-line header so the title never truncates to nothing; an editable status badge that becomes a status-change dropdown (statusEditable, default true); status tones (TaskStatusOption.tone done/blocked → gray border + dimmed overlay + auto-collapse) that decouple the status signal from the time-driven urgency border; and a priority + labels model extension (TaskItem.priority / labels with priorityOptions / labelOptions) rendered as a header meta row. Color override surfaces as a centered Dialog with palette swatches + custom CSS color input + an Auto button that clears the override and hands control back to the time engine.
pnpm dlx shadcn@latest init"registries": {
"@ilinxa": "https://ui.ilinxa.com/r/{name}.json"
}pnpm dlx shadcn@latest add @ilinxa/task-cardAdd -fixtures for dummy data:
pnpm dlx shadcn@latest add @ilinxa/task-card-fixturesDemo clock frozen at 2026-05-20T12:00:00.000Z so the border colors stay deterministic.
Outline goals, key results, and timelines for the next quarter.
Auth middleware rewrite — flagged by legal compliance.
Three-level nested example. Each child has its own dates.
The header gains a priority badge + label chips (border/text color only). The done / blocked statuses carry a tone so terminal cards get a gray border, a dimmed overlay, and auto-collapse. Turn on editableabove, then use the status badge (or the overlay's badge) to change status — changing a terminal status clears the overlay.
Priority + labels surface in the header meta row.
4 demos · click the pencil icon (or the action menu) to edit · Cmd/Ctrl+C / Cmd/Ctrl+V on a focused card copies / pastes as child · drag a card onto another's children area to paste.
kanban-boardThe same TaskCard slots into a kanban column via the exported taskCardKanbanRenderer. Grab a card anywhere to drag it across columns and drop it anywhere in a column; the card body keeps full edit / collapse semantics (renderer's dragHandle:"shell" + canDragItem disabled so the two drag systems don't fight).
Outline goals, key results, and timelines for the next quarter.
Auth middleware rewrite — flagged by legal compliance.
Note + todo renderers co-exist on the same board. Grab a todo card anywhere to drag it (shell-drag), and drop it anywhere in a column. The card body keeps full edit / collapse semantics.
Reach for TaskCard when you need a time-aware task surface — agent run queues, content schedules, sprint cards, workflow tasks. The card carries the standard task fields out of the box, paints urgency directly onto the chrome via the time engine, and is fully data-interactive (JSON I/O, clipboard, drag-drop).
For lightweight tree-row rendering (collapsible sub-items, inline checkbox, single-line description preview), reach for the sibling task-tree procomp — shares the same TaskItem schema so drags + clipboard payload work cross-procomp. For kanban, use kanban-board + the renderer exported below.
import { TaskCard } from "@/components/task-card";
export function Example() {
return (
<TaskCard
defaultValue={{
id: "task-001",
name: "Review pull request #482",
status: "in-progress",
active: true,
setAt: "2026-05-19T09:00:00Z",
expireAt: "2026-05-21T17:00:00Z",
}}
editable
/>
);
}The engine normalizes (now − startAt) / (expireAt − startAt) to [0, 1] and maps it through an OKLCH ramp — green at 0, red at 1. Past expireAt pins to full red. If expireAt is absent, duration is used instead. Per-item borderColor overrides the engine for that node. Set colorRamp to swap presets: 'default' | 'muted' | 'vivid' | 'monochrome' — or pass a custom function for full control.
onPermissionDenied fires with reason: 'locked'.Every card has a chevron at the left of its header. Clicking it collapses the card's body (description, time-info, chips, links, images) andits nested children — only the header stays visible. Per-item, independent at every depth. The collapse flag is UI-only state in the component's reducer (collapsedIds: ReadonlySet<string>) — it is not stored on TaskItem, so JSON I/O round-trips ignore it. Remounting via key resets all collapse state.
Click the action menu (...) on any card and choose Override color… to open a centered Dialog: 8 curated OKLCH palette swatches, a free-text input for any CSS color string, and an Autobutton (with sparkle icon) that clears the override and hands rendering back to the time engine. Dialog (vs Popover) avoids an outside-click race with the action menu's dismissal.
Use the imperative ref handle to copy(), paste(), getValue(), or getTree(). When a card has keyboard focus, Cmd/Ctrl+C copies it and Cmd/Ctrl+V pastes from the clipboard as a child. Drag a card onto another card's children area to drop the JSON payload as a child. The clipboard uses MIME application/x-ilinxa-task+json with a text/plain JSON fallback for browsers without custom-MIME support.
The engine reads new Date() at render time, which means server- and client-rendered HTML can compute slightly different border colors when nowisn't frozen. The card mitigates this with suppressHydrationWarning on the article root — the visual flash is sub-frame and the data is consistent server→client. For deterministic SSR (snapshot tests, server-rendered HTML caching), pass a frozen now: now={new Date("2026-05-20T12:00:00Z")}.
The package exports taskCardKanbanRenderer — a typed KanbanCardRenderer<TaskItem> with dragHandle: "header" so the kanban grip strip handles outer column reorder while the card body keeps its full edit / collapse / nested-DnD semantics. Drop it into the KanbanBoard renderers array alongside (or instead of) the built-in card renderers. The kanban-board demo on its own detail page shows mixed renderers; below is the minimum wiring.
import { KanbanBoard, kanbanCardRenderer } from "@/components/kanban-board";
import { taskCardKanbanRenderer } from "@/components/task-card";
import type { KanbanData } from "@/components/kanban-board";
const initial: KanbanData = {
swimlanes: [],
columns: [
{
id: "col-todo",
title: "To do",
color: "slate",
items: [
{
id: "kanban-task-1",
rendererId: "task-card", // matches renderer.id
data: {
id: "task-001",
name: "Review PR #482",
status: "todo",
active: true,
setAt: "2026-05-19T09:00:00Z",
expireAt: "2026-05-21T17:00:00Z",
},
},
],
},
{ id: "col-doing", title: "In progress", color: "lime", items: [] },
{ id: "col-done", title: "Done", color: "emerald", items: [] },
],
};
export function TaskKanbanExample() {
return (
<KanbanBoard
renderers={[kanbanCardRenderer, taskCardKanbanRenderer]}
defaultData={initial}
aria-label="Task kanban"
/>
);
}rendererId: "task-card" on each kanban item must match taskCardKanbanRenderer.id — the board uses this to look up the renderer for each item. Items with no matching renderer show a placeholder card.
todo-card-tree-node sibling adapter, shipping separately): exposes a NodeRenderer that wraps this card.TaskItem schema and DnD payload so drags cross-procomp.