Task Inline
A task in running text — one box, the title that opens it, the assignee and due date — and MakeTaskPopover, to make one from a line.
- Status
- Since
0.25.89- Accessibility pattern
- one named checkbox; the title is a button; ↗ is a named link
Last updated
Install
Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Task Inline before installation. Retain the digest printed by this command.
pnpm exec vegastack-design verify task-inlineInstall with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.
pnpm dlx shadcn@4.21.0 add @vegastack/task-inlineRun the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.
The same command installs the registry items it composes: @vegastack/avatar, @vegastack/button, @vegastack/checkbox, @vegastack/input, @vegastack/person-avatar, @vegastack/popover.
Usage
import { MakeTaskPopover, TaskInline } from "@/components/ui/task-inline";
<TaskInline
title="Order glass for block B"
done={task.done}
assignee={{ name: "Asha Rao", hue: "blue" }}
due="Fri 31 Oct"
onToggle={(done) => setDone(task.id, done)}
onOpen={() => openPeek(task.id)}
href={`/tasks/${task.id}`}
/>;A task where people write: a checklist line linked to a task, or a task named in a sentence. It
has one box — the task's done state — so a linked checklist line no longer shows the line's box
and a task glyph beside it. The title opens the task where the host shows it (onOpen, a peek),
the assignee's avatar and a due chip follow it, and ↗ to the task's own page shows on hover and
focus. It is an inline box: it wraps with its line, at that line's size.
TextEdit and MarkdownView draw a
linked checklist line with it when the host passes onTaskOpen — the line's own box stays the
task's box (checkbox={false} here). MakeTaskPopover is how such a line is made: anchored to the
line, never a modal.
Scope
- Owns: the box, the title as the task's open control, the avatar, the due chip, ↗, and the make popover's titles, keep boxes and Create.
- Does not own: the task — its state comes in through props and every change goes out through a callback — or the assignee, due date and space pickers, which the host puts in the popover's slots.
- Compose with:
PeoplePicker,DatePickerandSpacePickerinMakeTaskPopover'sassignee,dueandspace.
Anatomy
Examples
Tick, open, see who and when
done mutes the title; struck strikes a closed task through with its status tag; overdue
turns the due chip to the destructive ink. A click on a title calls onOpen and never moves a caret
or starts an edit around it.
Read-only, in a sentence
Without onToggle the box shows the state and cannot change it; without onOpen the title is
text.
The glazing team will start once Order glass for block BDue Fri 31 Oct lands on site, then the frames go in.
Make a task from a line
MakeTaskPopover points at anchor (TextEdit's onMakeTask hands over the first line's element)
and follows it as the page scrolls. The line's text is the title; Enter in it, or Create, calls
onCreate with the kept lines — return a promise and the popover stays busy until it settles, and
open if it rejects.
☐ Send the revised drawings to the client
Several lines
Each line gets a keep box and its own title; one assignee, due date and space go to every task. Create counts the lines kept.
- ☐ Measure the east wall
- ☐ Order the frames
- ☐ Book the fitters
API Reference
TaskInline
| Prop | Type | Default | Description |
|---|---|---|---|
title* | React.ReactNode | — | The task's title. |
assignee | TaskInlinePerson | null | — | Who it is assigned to: their avatar after the title. |
assigneeLabel | string | "Assigned to" | The avatar's accessible prefix. |
checkbox | boolean | true | Draw the task's checkbox. Off where the box is the host's own (a checklist line's). |
done | boolean | false | Whether the task is done: the box's state, and a muted title. |
due | string | null | — | When it is due, as the host words it ("Fri 31 Oct", "Tomorrow"): a small date chip. |
dueLabel | string | "Due" | The due chip's accessible prefix. |
href | string | null | — | The task's own page: a ↗ link at the end, shown while the task is hovered or holds focus. |
onOpen | (() => void) | — | The title was clicked (or Enter on it): open the task where the host shows it — a peek. Without it the title is plain text. |
onToggle | ((done: boolean) => void) | — | The box was ticked or unticked. Without it the box shows the state and cannot change it. |
openLabel | string | "Open task page" | The ↗ link's accessible name. |
overdue | boolean | false | The due date has passed: the chip takes the destructive ink. |
status | string | — | A small tag after the title ("Canceled", "In review"). |
struck | boolean | false | Closed without being done (canceled, a duplicate): the title struck through. |
toggleLabel | ((done: boolean) => string) | (done) => done ? "Mark task not done" : "Mark task done" | The checkbox's accessible name, by its state. |
Data attributes and CSS variables on TaskInline
| Attribute | Values |
|---|---|
data-done | "" |
data-overdue | "" |
data-slot | "task-inline" | "task-inline-assignee" | "task-inline-due" | "task-inline-open" | "task-inline-status" | "task-inline-title" |
data-struck | "" |
MakeTaskPopover
| Prop | Type | Default | Description |
|---|---|---|---|
anchor* | Element | null | — | The element it points at — the first line (TextEdit's onMakeTask hands it over). It follows
the element while the page scrolls; without one it sits at the top of the window. |
lines* | readonly MakeTaskLine[] | — | The lines to make tasks of: one title each, each line kept or skipped (several). |
onCreate* | (lines: { key: string; title: string; }[]) => void | Promise<void> | — | Create was chosen: the kept lines with their titles (trimmed, never empty). Return a promise to hold the popover busy until it settles; it stays open if the promise rejects. |
onOpenChange* | (open: boolean) => void | — | Asked to open or close (Escape, a click outside, Cancel, after Create). |
open* | boolean | — | Whether the popover is open. |
assignee | React.ReactNode | — | The host's assignee picker, one for every task made. |
cancelLabel | string | "Cancel" | The Cancel button's text. |
createLabel | string | lines.length > 1 ? `Create ${kept} tasks` : "Create task" | The Create button's text. |
due | React.ReactNode | — | The host's due date picker. |
space | React.ReactNode | — | The host's space picker. |
title | string | lines.length > 1 ? `Make ${n} tasks` : "Make a task" | The heading. |
titleMaxLength | number | 500 | The longest title a line takes, in characters: the title inputs stop there, so an over-long title can't be typed (and can't fail the whole batch on the server). |
Data attributes and CSS variables on MakeTaskPopover
| Attribute | Values |
|---|---|
data-slot | "make-task-popover" | "make-task-popover-actions" | "make-task-popover-anchor" | "make-task-popover-fields" | "make-task-popover-line" | "make-task-popover-lines" | "make-task-popover-title" |
Accessibility
- The box is a checkbox named for what it does ("Mark task done"); read-only, it still reports its state.
- The title is a button (Enter or Space opens the task); ↗ is a link named by
openLabel. - The avatar is named "Assigned to Asha Rao"; the due chip reads "Due Fri 31 Oct".
- The popover is named by its heading; Escape closes it and returns focus.
| Key | Action |
|---|---|
| Space | Ticks or unticks the box |
| Enter / Space | On the title: opens the task |
| Enter | In a title in the popover: creates the task(s) |
| Escape | Closes the popover |
| Contract | States tested |
|---|---|
| Behaviour | default, done, struck, overdue, read-only, open, pending |
| Accessibility | labeled |
| Visual | default, done, struck, overdue |