@lotics/ui 27.17.1 → 28.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +13 -10
- package/MIGRATION.md +64 -0
- package/docs/catalog.md +97 -140
- package/docs/data_entry.md +57 -87
- package/docs/templates.md +95 -57
- package/examples/tpl_item_list.tsx +77 -36
- package/examples/tpl_record.tsx +372 -460
- package/package.json +3 -3
- package/src/checklist.tsx +339 -0
- package/src/comments_button.tsx +108 -0
- package/src/control_surface.ts +13 -0
- package/src/detail_row.tsx +2 -2
- package/src/field_annotations.tsx +1 -1
- package/src/icon_button.tsx +17 -1
- package/src/locale.tsx +12 -1
- package/src/stepper.tsx +107 -18
- package/src/stepper_layout.ts +21 -1
- package/src/table.tsx +101 -11
- package/src/pipeline.tsx +0 -231
- package/src/task.tsx +0 -518
- package/src/task_metrics.ts +0 -55
package/AGENTS.md
CHANGED
|
@@ -44,16 +44,19 @@ CURRENT major only — upgrading an app across majors is `MIGRATION.md`.
|
|
|
44
44
|
(`message`/`detail`/`onRetry`) on failure → `EmptyState` (succeeded, found nothing) →
|
|
45
45
|
`CompletionState` on done. An alert glyph inside an empty state claims the read succeeded when
|
|
46
46
|
nothing is known. → [catalog.md §Status / feedback](./docs/catalog.md).
|
|
47
|
-
- **Progress:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
- **Progress: ONE compound, TWO axes — and both are about meaning.** A run of markable rows is
|
|
48
|
+
`checklist` (`Checklist` + `ChecklistGroup` + `ChecklistItem`, over `stepper`). **`connected`**
|
|
49
|
+
asks *is this a sequence* — on for one record walking positions, off for N items handled in any
|
|
50
|
+
order, where a line claims an order the work does not have. **`mark`** asks *does ticking mean
|
|
51
|
+
DONE or CHOSEN* — a ring for completion, the square box for picking (which forms to produce,
|
|
52
|
+
which records to export). Spend the ring on a choice and a reader who learned that a filled
|
|
53
|
+
ring means "done" reads a ticked pick-list as work already carried out. It replaced separate
|
|
54
|
+
task/pipeline families that had converged on one anatomy. A GROUP is a phase — a name, optionally a
|
|
55
|
+
Show/Hide disclosure, and no body: it owns no COMPLETION, and a ring that never responds invites
|
|
56
|
+
a press it refuses. Rows tick ONE at a time; derive position from the highest stamp and one click marks
|
|
57
|
+
everything below it without inventing dates. A checklist REPORTS — a field owned by a section is
|
|
58
|
+
named as a gap with a `ChecklistNote action` that jumps there, never edited or previewed in the
|
|
59
|
+
row. Worked in `examples/tpl_record.tsx` § Progress. See `docs/catalog.md`.
|
|
57
60
|
- **`Badge` = STATUS only; supporting detail is the muted second line.** A type / category /
|
|
58
61
|
attribute / count is not a status — it belongs under its identity as `size="xs" color="muted"`,
|
|
59
62
|
never a second chip. A chip beside a name reads as its PEER (a colored one reads louder),
|
package/MIGRATION.md
CHANGED
|
@@ -4,6 +4,70 @@ Breaking changes, newest first — normally per major, plus the rare minor that
|
|
|
4
4
|
anyway (recorded under its exact version). The current contract lives in `AGENTS.md` + `docs/`;
|
|
5
5
|
this file exists only to move an app from one release to the next.
|
|
6
6
|
|
|
7
|
+
## 28.0.0 — `task` and `pipeline` merge into `checklist`
|
|
8
|
+
|
|
9
|
+
Two families had converged on one anatomy: a ring, a title, a value beside it, a muted note, a
|
|
10
|
+
detail block, an optional grouping level. What differed was a LINE between the rings — a mode,
|
|
11
|
+
not a family. The proof: a single session added `trailing`/`meta` to `TaskTitle` **and**,
|
|
12
|
+
separately, the same two to `PipelineStep`, then `tone` to `TaskCaption` and `tone`+`action` to
|
|
13
|
+
`PipelineNote`. One feature, implemented twice.
|
|
14
|
+
|
|
15
|
+
`@lotics/ui/task` and `@lotics/ui/pipeline` are **gone**. `@lotics/ui/checklist` replaces both.
|
|
16
|
+
|
|
17
|
+
**`Checklist` and the `checklist` locale slice are REUSED names, not restored components.** A
|
|
18
|
+
different `Checklist` / `ChecklistRow` shipped before v17 and was deleted there in favour of
|
|
19
|
+
`Task`; this one shares only the word and takes none of its props (`trailingWidth`,
|
|
20
|
+
`controlWidth`, `expansion`, `subtasks`). The `checklist` locale slice v17 deleted is likewise
|
|
21
|
+
back under the same key with different strings — `expand` / `collapse`, the group disclosure's
|
|
22
|
+
wording, where the old slice was note and subtask chrome. An app arriving from 16.x follows the
|
|
23
|
+
table below; nothing of its old `Checklist` carries over.
|
|
24
|
+
|
|
25
|
+
| was | now |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `<TaskList>` / `<Pipeline>` | `<Checklist connected={…}>` — the line is an AXIS |
|
|
28
|
+
| `<TaskItem>` + `<TaskStatus>` + `<TaskTitle>` | `<ChecklistItem title done current onToggle trailing meta menu>` |
|
|
29
|
+
| `<PipelineStage>` | `<ChecklistGroup title>` (a phase) — or just a `ChecklistItem` (an atomic rung) |
|
|
30
|
+
| `<PipelineStep>` | `<ChecklistItem>` |
|
|
31
|
+
| `<TaskCaption>` / `<PipelineNote>` | `<ChecklistNote tone action>` |
|
|
32
|
+
| `<PipelineActions>` / `<TaskActions>` | `<ChecklistActions>` / `ChecklistItem.menu` |
|
|
33
|
+
| `<PipelineField>` | `<ChecklistField>` |
|
|
34
|
+
| `<TaskDetail>` | a `ChecklistItem`'s own children — free-form content needs no wrapper |
|
|
35
|
+
| nested `<TaskList>` for subtasks | `<ChecklistGroup>` — groups and items are SIBLINGS in one run |
|
|
36
|
+
|
|
37
|
+
**`connected` is the whole difference.** On for a record walking positions (the line asserts
|
|
38
|
+
sequence); off for a set picked in any order, where a line claims an order the work does not
|
|
39
|
+
have.
|
|
40
|
+
|
|
41
|
+
**A group carries no control and no body.** A phase owns no completion of its own, so a ring
|
|
42
|
+
there is a control that never responds — and one identical to the pressable rings beneath it
|
|
43
|
+
invites the press it refuses. A condition hung off a heading also leaves the reader working out
|
|
44
|
+
which row it was about, so a row's wait, warning and act now sit on the row that owes them.
|
|
45
|
+
|
|
46
|
+
**Rows are ticked one at a time.** A parent that ticked its children wrote what the reader never
|
|
47
|
+
said — on a date ladder, today's date onto milestones that happened on unrecorded days. Where a
|
|
48
|
+
run is a sequence, derive position from the highest stamp: one click then marks everything below
|
|
49
|
+
it, and the rungs it passes show a BLANK date, which is the honest answer to "when".
|
|
50
|
+
|
|
51
|
+
### Also cut
|
|
52
|
+
|
|
53
|
+
- **`TaskSubRow`** and `TaskList.labelWidth`. A checklist REPORTS: it does not collect, and it
|
|
54
|
+
does not preview. A field with a home elsewhere — an assignee, an address — is named as a gap
|
|
55
|
+
by a `ChecklistNote` that links to the section owning it. An editor in a task row gave every
|
|
56
|
+
row two modes with nothing to say which one the reader was in; a rendered value (an avatar, a
|
|
57
|
+
badge) is a copy that has to be kept in step with the field's real home. `ChecklistField`
|
|
58
|
+
survives for the narrow case of a value with NO other home (a portal login created at that
|
|
59
|
+
step), and `ChecklistItem.trailing` for the row's OWN stamp.
|
|
60
|
+
- **`Marker`** — zero consumers.
|
|
61
|
+
- **`Step.partial`** — its only caller was the stage ring, and stages no longer wear one.
|
|
62
|
+
`CheckCircle`'s three positions are unchanged for direct use.
|
|
63
|
+
- `TaskList.density` — one surface used it; a run of rows has one rhythm.
|
|
64
|
+
|
|
65
|
+
### Kept
|
|
66
|
+
|
|
67
|
+
`Stepper` / `Step` remain the low-level position READOUT — a wizard's rail is not a checklist.
|
|
68
|
+
`Stepper` gains `connected` and `gap`; `Step` gains `marker={false}` for a row that groups
|
|
69
|
+
others.
|
|
70
|
+
|
|
7
71
|
## 27.15.0 — a register row's text is selectable, and a drag no longer opens the record
|
|
8
72
|
|
|
9
73
|
No API change, but two behaviors changed on **every** `PressableRow` / `TableRow` / `PressDoor`
|
package/docs/catalog.md
CHANGED
|
@@ -111,24 +111,40 @@ input chrome, so it aligns pixel-for-pixel). A stack of labelled field rows live
|
|
|
111
111
|
`DetailTable` + `DetailRow`; the record's identity band is `RecordSummary`; its money
|
|
112
112
|
summary is `Ledger`.
|
|
113
113
|
|
|
114
|
-
### Tasks
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
114
|
+
### Tasks, to-dos, phased work — ONE compound, two axes
|
|
115
|
+
|
|
116
|
+
Anything a reader marks is `checklist` — `Checklist` + `ChecklistGroup` + `ChecklistItem`. Two
|
|
117
|
+
axes carry every shape it takes, and BOTH are decisions about meaning, not looks:
|
|
118
|
+
|
|
119
|
+
- **`connected`** — is this a SEQUENCE? On for one record walking positions (the line asserts
|
|
120
|
+
order), off for N items handled in any order, where a line claims an order the work does not
|
|
121
|
+
have.
|
|
122
|
+
- **`mark`** — does ticking mean DONE or CHOSEN? `check` is a ring, `select` is the square box.
|
|
123
|
+
Reach for the square whenever the row is PICKED rather than finished — which forms to produce,
|
|
124
|
+
which records to export. Spending the ring on a choice is the failure this axis exists to
|
|
125
|
+
prevent: a reader who has learned that a filled ring means "done" reads a ticked pick-list as
|
|
126
|
+
work already carried out, and nothing on screen corrects them. (The shapes are 24px either way
|
|
127
|
+
and share one gutter, so a surface swaps between them without moving anything.)
|
|
128
|
+
|
|
129
|
+
A record's Progress and a desk's to-do list are the same component two booleans apart; they were
|
|
130
|
+
two families until the anatomy proved identical.
|
|
131
|
+
|
|
132
|
+
**A row carries its TITLE and its own stamp, and nothing else.** A checklist REPORTS: it does not
|
|
133
|
+
collect, and it does not PREVIEW. A field some section owns — an assignee, an address, a portal
|
|
134
|
+
login — is NAMED as a gap by a `ChecklistNote` whose `action` jumps to that section, never edited
|
|
135
|
+
in the row (two edit surfaces for one fact) and never rendered as a value (an avatar or badge is
|
|
136
|
+
a copy that has to be kept in step). The exceptions are narrow and stated: `ChecklistItem.trailing`
|
|
137
|
+
for the row's OWN stamp (a tick writes today, so a run filled in after the fact needs the
|
|
138
|
+
correction in reach), and `ChecklistField` for a value with NO other home.
|
|
139
|
+
|
|
140
|
+
**A list you scan DOWN columns — the same four values compared across twenty rows — is a
|
|
141
|
+
`Table`.** Grouping, filters and a per-row register belong there.
|
|
142
|
+
|
|
143
|
+
**A record's work state is a connected checklist** ([`tpl_record`](../examples/tpl_record.tsx)
|
|
144
|
+
§ Progress), where the desks are `ChecklistGroup`s and the milestones are rows. A per-desk
|
|
145
|
+
checklist without the connecting line described the work but never said where the record SAT, and
|
|
146
|
+
put the CTA a section away from the state that gated it. A register's workspace drawer renders the
|
|
147
|
+
same record, so it follows automatically; for a surface whose SUBJECT is tasks see
|
|
132
148
|
[`tpl_task_board`](../examples/tpl_task_board.tsx).
|
|
133
149
|
|
|
134
150
|
### Tabular data — pick by SCALE + intent
|
|
@@ -494,6 +510,21 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
494
510
|
heading row) where no text edge exists to betray, or give it the filled tier.
|
|
495
511
|
- **`icon_button`** — `IconButton`: the icon-only circular action (see
|
|
496
512
|
[Actions](#actions)).
|
|
513
|
+
- **`comments_button`** — `CommentsButton`: THE discussion affordance for a listed record — the
|
|
514
|
+
count and a bubble as ONE control, opening the thread. Reach for it wherever a record is listed
|
|
515
|
+
and its conversation would otherwise be invisible until opened (a register row, a card, a
|
|
516
|
+
compact header); it is `CopyButton`'s peer — the other thing a dense row lets you press — and
|
|
517
|
+
shares its surface, scale and focus ring, so a row carrying both reads as one grammar. The count
|
|
518
|
+
is INSIDE the target, never loose text beside an `IconButton`: the number is what the reader
|
|
519
|
+
aims at, and splitting them leaves half the affordance dead under the pointer. FULL INK, unlike
|
|
520
|
+
the muted values around it — everything else on a row is a fact ABOUT the record, this is people
|
|
521
|
+
talking about it and the one thing there that can be UNREAD. `subject` reaches the accessible
|
|
522
|
+
NAME only ("3 comments · Northwind Packaging" is a destination; "3 comments" on the fortieth row
|
|
523
|
+
is not) — never the visible label, which would spend row width restating whose record it is.
|
|
524
|
+
**Render it only when `count > 0`** — a zero on every quiet row is a column of noise that trains
|
|
525
|
+
the eye to skip exactly where the signal will appear. Pair it with a jump that LANDS on the
|
|
526
|
+
thread (`tpl_item_list` opens the record's drawer on its comments section), because a count the
|
|
527
|
+
reader cannot act on states that a conversation exists and leaves them to find it.
|
|
497
528
|
- **`copy_button`** — `CopyButton`: THE copy control — `value` onto the clipboard, glyph
|
|
498
529
|
flips to a check and the tooltip to the pack's "Copied" for ~2s. The confirmation follows
|
|
499
530
|
a REAL write: an unreachable clipboard throws and the button stays at rest rather than
|
|
@@ -834,8 +865,8 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
834
865
|
not a drag handle — dragging is invisible to the keyboard and fiddly on a phone, and a
|
|
835
866
|
three-to-six position list does not need it. Indent anything that follows the list (an "Add"
|
|
836
867
|
link) by `SEQUENCE_INSET` so it lands on the rail's column. Distinct from `Timeline` (an
|
|
837
|
-
activity FEED), `Stepper` (a wizard's fixed positions) and `
|
|
838
|
-
|
|
868
|
+
activity FEED), `Stepper` (a wizard's fixed positions) and `Checklist` (rows a reader MARKS —
|
|
869
|
+
a record walking positions, or a set picked) — this is the list a user EDITS.
|
|
839
870
|
- **`inline_button`** — `InlineButton`: a verb that sits INSIDE an inline field's surface
|
|
840
871
|
(the `Open` on a reference, a `Copy` on a value worth copying) rather than in the row's
|
|
841
872
|
trailing column — put it inside when the act is ABOUT THE VALUE, so it travels with what it
|
|
@@ -864,12 +895,12 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
864
895
|
wire both); invalid/cross-field STATE = a co-located `Callout`; **`flat`**
|
|
865
896
|
on a flat-text value row (`InlineStatic`, plain `Text`) tucks the annotation up by the
|
|
866
897
|
control band's slack so its gap matches a chip row's.
|
|
867
|
-
The three annotations are ONE anatomy shared with a
|
|
898
|
+
The three annotations are ONE anatomy shared with a checklist row's `ChecklistNote` — same
|
|
868
899
|
order, same alert semantics — because a record's field and a task's field are the same thing
|
|
869
900
|
on two surfaces.
|
|
870
901
|
`DetailTable`: the compound parent of
|
|
871
902
|
a row STACK — `labelWidth` (default `DETAIL_LABEL_WIDTH`, 130 — THE kit's label column, and
|
|
872
|
-
|
|
903
|
+
the record surface's) / `minHeight` (default 40, the inline-control grid) declared
|
|
873
904
|
ONCE + the `SPACE.md` (16) row gap — 8 was right while a field was a tint, but a stack of
|
|
874
905
|
BORDERED rows that close together fuses into one block. TWO columns, no third: the value
|
|
875
906
|
FILLS what the label leaves, so nothing one row does can narrow its neighbours' editors. RESPONSIVE with no prop: it
|
|
@@ -1020,6 +1051,20 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1020
1051
|
by the row's own toggle), the row shows the open wash while it is out, and the door announces
|
|
1021
1052
|
`aria-expanded`. Prefer the columns first: a fact every row needs is a column, not a reason
|
|
1022
1053
|
to expand.
|
|
1054
|
+
**`Table.count` + `TableRow.ordinal` make it a COUNTED register** — a narrow gutter left of
|
|
1055
|
+
`leading` carrying each row's position, headed by the total. Reach for it on any register
|
|
1056
|
+
long enough to scroll: it answers "how many" without paging to the end and "where am I"
|
|
1057
|
+
without counting rows, and it is what a reader coming from a spreadsheet (STT) expects to
|
|
1058
|
+
find. `count` is the single switch — omit it and no gutter is reserved, so an uncounted
|
|
1059
|
+
register keeps every pixel it had. It is CHROME, not a column: it never sorts, never drops,
|
|
1060
|
+
and is excluded from the column band, but it IS reserved space the fit accounts for.
|
|
1061
|
+
**Both numbers are the caller's**, and deliberately: `count` is what MATCHED (a paged
|
|
1062
|
+
register renders fifty of it, a filtered one counts the matches), and `ordinal` continues
|
|
1063
|
+
across pages (`offset + i + 1`) or restarts inside a group band, depending on which question
|
|
1064
|
+
the reader is asking — "which of all" or "which of these". Omit `ordinal` on a row with no
|
|
1065
|
+
position (a group band, a totals line) and the gutter stays blank so the cells beside it stay
|
|
1066
|
+
in line. A position is NEVER an identity: sort or filter and row 12 is a different record —
|
|
1067
|
+
a stable handle is a column, and it leads the cells. Worked screen: `tpl_item_list`.
|
|
1023
1068
|
- **`sort_header`** — `SortHeader` + `SortState`/`SortDir` + `cycleSort` + `sortBy` +
|
|
1024
1069
|
`SortHeaderLabels`: the sortable column header and the sort-state helpers `Table`/
|
|
1025
1070
|
`DataGrid` consumers drive.
|
|
@@ -1038,7 +1083,7 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1038
1083
|
summarizes — including a record's child list (a consol's houses, an order's lines). **Never on
|
|
1039
1084
|
a record's identity band reporting that record's own state**: derived verdicts on one record
|
|
1040
1085
|
("documents incomplete", "2 fields need checking") are the checklist a record must not carry
|
|
1041
|
-
(§`
|
|
1086
|
+
(§`checklist`) and restate at a distance what the sections below state in place.
|
|
1042
1087
|
- **`use_selection`** — `useSelection`: always-on multi-select state for a register/list —
|
|
1043
1088
|
the `selected` Set + `toggle`/`setAll`/`allSelected`/`indeterminate`/`count`/`clear`;
|
|
1044
1089
|
selectability gating stays with the caller. The checkbox-always-visible counterpart to
|
|
@@ -1068,89 +1113,6 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1068
1113
|
(`onChange(done)`) so the ring means one thing everywhere; `partial` is reached through
|
|
1069
1114
|
whatever NAMES it — a status cell, or children ticking off — never by cycling the ring. Keep
|
|
1070
1115
|
it monochrome and let colour live in the status cell.
|
|
1071
|
-
- **`task`** — `TaskList` + `TaskItem` + `TaskStatus` / `TaskTitle` / `TaskCaption` /
|
|
1072
|
-
`TaskActions` / `TaskSubRow` / `TaskDetail` — the task COMPOUND, for anything
|
|
1073
|
-
from a 5-item drawer checklist to a grouped desk board. `TaskList` owns geometry only: the two
|
|
1074
|
-
GUTTERS — `controlWidth` (the left one, that every title aligns on, and so the INDENT step) and
|
|
1075
|
-
`actionWidth` (the right one, that every ⋯ pins into; `0` on a list whose rows carry no
|
|
1076
|
-
actions) — plus `labelWidth` (the column every `TaskSubRow` renders its NAME in; default
|
|
1077
|
-
`DETAIL_LABEL_WIDTH`, 130) and `density` (`comfortable` = a 44px minimum tap target, `dense` =
|
|
1078
|
-
32 for a pointer-driven register). All four are inherited by nested lists. Everything else is
|
|
1079
|
-
composed, and JSX order is screen order — nothing inspects child types.
|
|
1080
|
-
|
|
1081
|
-
`TaskStatus` takes the `CheckCircle` (omit `onChange` for a read-only ring; a PICKER list
|
|
1082
|
-
puts a `CheckboxInput` here and sets `controlWidth={24}`). `TaskTitle` takes the
|
|
1083
|
-
`InlineTextInput variant="bare"` — or the title TEXT itself as a string child
|
|
1084
|
-
(`<TaskTitle struck={done}>{label}</TaskTitle>`), which is the READ-ONLY form: the compound
|
|
1085
|
-
applies the cell inset and the row's band, so a plain `<Text>` + a hand-rolled
|
|
1086
|
-
`TASK_TEXT_INSET` is never needed and a long title that wraps keeps its first line beside the
|
|
1087
|
-
control. It spans the content box between the gutters, like every line hung beneath it.
|
|
1088
|
-
`TaskCaption` is the row's state IN WORDS on its own line under the title — a
|
|
1089
|
-
sentence about the ROW, never a field, and never a sentence about one FIELD (that is the
|
|
1090
|
-
sub-row's own `description` / `warning` / `error`).
|
|
1091
|
-
`TaskActions` carries the row's ⋯ `ActionMenu`, pinned into the RIGHT
|
|
1092
|
-
gutter on the first line (Delete lives BEHIND it, danger-styled and last, never a bare ✕).
|
|
1093
|
-
`TaskDetail` is a FREE-FORM block under the row on the title's text edge — a chart, a table, a
|
|
1094
|
-
form with its own submit — rendered only while open. The module also exports
|
|
1095
|
-
**`TASK_TEXT_INSET`** (9), the inset an inline control puts on its own text: every
|
|
1096
|
-
slot above already applies it, so reach for it ONLY when a custom title NODE (not a cell
|
|
1097
|
-
control) has to land on the same text edge.
|
|
1098
|
-
|
|
1099
|
-
**THE ⋯ IS A COLUMN, THE MIRROR OF THE CONTROL GUTTER.** Both pinned controls sit outside the
|
|
1100
|
-
flow and the ROW reserves each edge (`actionWidth` + the row gap), so what is left between them
|
|
1101
|
-
is ONE content box every line spans exactly — title, caption, sub-row, detail, nested list. That
|
|
1102
|
-
is what keeps a list where only SOME rows carry a menu straight: a menu-less row's content ends
|
|
1103
|
-
on the same x as a menu-carrying one's, and so does everything hanging under either. A nested
|
|
1104
|
-
list hands the parent's reservation back before its own rows re-take it, so the column does not
|
|
1105
|
-
step inward per level. Declare `actionWidth={0}` when NO row in the list carries actions.
|
|
1106
|
-
|
|
1107
|
-
**THE ROW CARRIES THE TITLE; THE FIELDS THE USER CAN SET ARE SUB-ROWS BENEATH IT.** One task's
|
|
1108
|
-
own fields hang under it as **`TaskSubRow`** (`label`, the control, `description` /
|
|
1109
|
-
`warning` / `error`), indented ONE step — the same step a nested `TaskList` takes, because
|
|
1110
|
-
belonging is expressed by indentation and there is only one device for it. Label and value sit
|
|
1111
|
-
ADJACENT so the eye pairs them. **The label column is the LIST's, not the row's** — one
|
|
1112
|
-
`labelWidth` for every sub-row at every depth, exactly as `DetailTable labelWidth` is the
|
|
1113
|
-
record's — so every value on the surface starts on ONE x. A name longer than the column WRAPS
|
|
1114
|
-
inside it and its value does not move; a column each row sized to its own words is not a
|
|
1115
|
-
column (it started a short label's value at one x and a long one's at another, and any
|
|
1116
|
-
vocabulary with longer field names staggered nearly every row). The value takes the slack from
|
|
1117
|
-
a readable minimum — on a phone or in a narrow drawer it drops onto its own line under the
|
|
1118
|
-
label rather than ellipsizing beside it. Pass a form-variant `Inline*` editor (the default),
|
|
1119
|
-
`variant="bare"`: a dense grid drops the resting frame.
|
|
1120
|
-
|
|
1121
|
-
**A TASK'S FIELD ANNOTATES EXACTLY LIKE A RECORD'S FIELD.** `description` (persistent
|
|
1122
|
-
guidance), `warning` (a consequence to weigh — amber, announced) and `error` (field-level
|
|
1123
|
-
failure — danger, alert semantics) are the same three props with the same order and a11y as
|
|
1124
|
-
`DetailRow`'s, from ONE shared implementation. A fault in a single field belongs ON that
|
|
1125
|
-
field; `TaskCaption` is a sentence about the whole ROW, so demoting a field fault into one
|
|
1126
|
-
says something different.
|
|
1127
|
-
|
|
1128
|
-
**ANYTHING THAT NEEDS SCANNABLE COLUMNS IS A `Table`, NOT A `TaskList`.** The compound spent a
|
|
1129
|
-
version carrying a declared value column so cells would line up down the list; it aligned and
|
|
1130
|
-
it read worse — each field's name ended up a quarter of the surface from its control, sized for
|
|
1131
|
-
the widest value on the page. If the job is comparing the same four values across twenty rows,
|
|
1132
|
-
that is a table, and `Table`/`DataGrid` are built for it. A `DetailTable labelWidth={…}` inside
|
|
1133
|
-
a `TaskDetail` is the other shape to avoid: the list ALREADY has a label column, so a second
|
|
1134
|
-
one lands its label and its value at two more x positions matching nothing above them — a form
|
|
1135
|
-
pasted into a list. Fields belonging to the task are `TaskSubRow`s, which annotate the same way
|
|
1136
|
-
a `DetailRow` does, so there is nothing left that a nested `DetailTable` can say.
|
|
1137
|
-
|
|
1138
|
-
**A row's FIRST LINE is a BAND** — 44px `comfortable`, 32 `dense`. Both gutter controls centre
|
|
1139
|
-
in it and `TaskTitle` claims it, which is what keeps both columns of
|
|
1140
|
-
controls straight as rows grow: a caption, a sub-row, a detail block, a nested list or a
|
|
1141
|
-
wrapped title all hang BELOW the band instead of dragging the control down into the gap under
|
|
1142
|
-
the title. So every sub-line sits the band's slack (12px comfortable) beneath the title's
|
|
1143
|
-
words, the same whether the title is text or an editor. A title node TALLER than the band
|
|
1144
|
-
overrides it — an inline editor is 40px, so a `dense` list of editable titles renders 40px rows
|
|
1145
|
-
and its ring reads a few px high; `dense` is for text/static rows. A sub-row takes the TALLER
|
|
1146
|
-
of the band and the 40px inline-control height, so its label's first line still meets its
|
|
1147
|
-
control's centre in a `dense` list.
|
|
1148
|
-
|
|
1149
|
-
**Subtasks are a nested `TaskList`**, so a step IS a task: give one a field, a menu or
|
|
1150
|
-
children of its own and it works. Collapsing belongs to the app — hold a boolean and render
|
|
1151
|
-
the nested list or don't. There is deliberately **no note slot**: a task's free text is its
|
|
1152
|
-
title, a caption, or detail, and a fourth place to write invited writing it twice.
|
|
1153
|
-
|
|
1154
1116
|
- **`suggestion_chip`** — `SuggestionChip`: the dismissible SUGGESTION pill — an item the
|
|
1155
1117
|
record could have but doesn't yet (a common task, an expected line) as a `Chip` whose
|
|
1156
1118
|
press MATERIALIZES it (plus glyph + label, one tuned anatomy) and whose ✕ refuses it;
|
|
@@ -1307,39 +1269,34 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1307
1269
|
provider-wired — pass `labels` (`DEFAULT_GANTT_LABELS` is English).
|
|
1308
1270
|
- **`timeline`** — `Timeline`: a heterogeneous event LOG — per-row icon + expandable
|
|
1309
1271
|
details; models the past, NOT progress.
|
|
1310
|
-
- **`
|
|
1311
|
-
`
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
`
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
`bare` `InlineDatePicker` (reads as text, border on hover, click to edit), and the live stage
|
|
1339
|
-
still carrying its owner, its note and the act that leaves it. The date stays EDITABLE on
|
|
1340
|
-
purpose: a tick always writes today, so inert text would make a ladder filled in after the
|
|
1341
|
-
fact — every imported record — impossible to enter correctly. An unstamped rung shows no
|
|
1342
|
-
placeholder; its empty ring already says "not yet".
|
|
1272
|
+
- **`checklist`** — `Checklist` + `ChecklistGroup` + `ChecklistItem` + `ChecklistNote` /
|
|
1273
|
+
`ChecklistActions` / `ChecklistField`: THE run of tickable rows, at any
|
|
1274
|
+
altitude. It replaced a `task` family and a `pipeline` family that had converged on one
|
|
1275
|
+
anatomy — a ring, a title, a value beside it, a muted note, a detail block, an optional
|
|
1276
|
+
grouping level — differing only in whether a LINE joined the rings. **`connected` is that
|
|
1277
|
+
line, and it is the whole difference**: on for ONE record walking positions (it asserts
|
|
1278
|
+
sequence), off for a SET picked in any order, where a line claims an order the work does not
|
|
1279
|
+
have. Rows are ticked ONE AT A TIME; where the run is a sequence, derive position from the
|
|
1280
|
+
highest stamp so one click marks everything below it — a parent that ticked its children wrote
|
|
1281
|
+
what the reader never said (today's date onto milestones that happened on unrecorded days),
|
|
1282
|
+
and a rung passed without a recorded day shows a BLANK date, which is the honest answer to
|
|
1283
|
+
"when". **`ChecklistGroup` is a phase — a name, and at most a way to fold its rows away**: no
|
|
1284
|
+
COMPLETION control, because a phase
|
|
1285
|
+
owns no completion of its own and a ring there is a control that never responds (one identical
|
|
1286
|
+
to the pressable rings beneath it invites the press it refuses); and no BODY, because a
|
|
1287
|
+
condition hung off a heading leaves the reader working out which row it was about — a row's
|
|
1288
|
+
wait (`meta`), warning (`ChecklistNote`) and act (`ChecklistActions`) sit on the row that owes
|
|
1289
|
+
them. Groups and items are SIBLINGS in one run, so the ladder keeps one ring column, one text
|
|
1290
|
+
edge and one line; a flat list renders no groups at all. **A checklist REPORTS — it does not
|
|
1291
|
+
collect and it does not PREVIEW**: a field with a home elsewhere is named as a gap by a
|
|
1292
|
+
`ChecklistNote` whose `action` jumps to the section owning it, never edited here (two edit
|
|
1293
|
+
surfaces for one fact) and never rendered as a value (an avatar or badge is a copy to keep in
|
|
1294
|
+
step). The exceptions are `ChecklistItem.trailing` for the row's OWN stamp — a tick writes
|
|
1295
|
+
today, so a run filled in after the fact needs the correction in reach — and `ChecklistField`
|
|
1296
|
+
for a value with NO other home (a portal login created at that step, unreachable otherwise).
|
|
1297
|
+
`ChecklistItem.meta` is two words on the title's row; prose that grows is a `ChecklistNote`,
|
|
1298
|
+
which owns its line. Worked screens: `tpl_record` § Progress (connected, grouped) and its
|
|
1299
|
+
document desk (unconnected set).
|
|
1343
1300
|
- **`stepper`** — `Stepper` + `Step` — done/current/upcoming/warning/complete progress on a
|
|
1344
1301
|
track (horizontal) or spine (vertical); compound `<Step status>children` OR data
|
|
1345
1302
|
`steps[]`+`current`; **navigable** via `Step.onPress` (both orientations — the whole step
|
|
@@ -1350,7 +1307,7 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1350
1307
|
VERTICAL: the marker centres on the content's FIRST ROW, assumed to be one line of `sm` text.
|
|
1351
1308
|
Put anything taller on that row — an inline editor beside the label — and pass
|
|
1352
1309
|
**`Step.headHeight`** (`INLINE_CONTROL_HEIGHT` for an editor) or the marker stays pinned to
|
|
1353
|
-
the text line while the label centres in the taller row. Prefer `
|
|
1310
|
+
the text line while the label centres in the taller row. Prefer `ChecklistItem.trailing`,
|
|
1354
1311
|
which does this for you.
|
|
1355
1312
|
|
|
1356
1313
|
### Files
|