@lotics/ui 21.1.0 → 21.3.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 +7 -0
- package/MIGRATION.md +16 -0
- package/docs/catalog.md +24 -7
- package/docs/templates.md +70 -21
- package/examples/tpl_record.tsx +181 -353
- package/package.json +2 -1
- package/src/locale.tsx +6 -3
- package/src/pipeline.tsx +156 -0
- package/src/progress_bar.tsx +14 -2
- package/src/step_progress.tsx +8 -0
- package/src/stepper.tsx +40 -20
package/AGENTS.md
CHANGED
|
@@ -27,6 +27,13 @@ CURRENT major only — upgrading an app across majors is `MIGRATION.md`.
|
|
|
27
27
|
license to hand-roll.
|
|
28
28
|
- **One canonical component per data role** (member → `MemberChip`, select → `OptionBadge`,
|
|
29
29
|
files → `FilePreview` family, …) — the catalog's Reach-by-role outranks neighboring code.
|
|
30
|
+
- **Progress: rows of WORK vs positions of ONE thing.** N items ticked in any order, every row
|
|
31
|
+
the same shape → `task` (`TaskList`). ONE record walking ordered stages where the stage decides
|
|
32
|
+
which fields, conditions and act are even offered → **`pipeline`** (`Pipeline` +
|
|
33
|
+
`PipelineStage`, over `stepper`) — worked in `examples/tpl_record.tsx` § Progress, which it took
|
|
34
|
+
over FROM a per-desk checklist. Rendering positions as a checklist forces every row to carry
|
|
35
|
+
every control and never says where the record sits; rendering work items as a pipeline implies
|
|
36
|
+
an order that is not there.
|
|
30
37
|
- **`Badge` = STATUS only; supporting detail is the muted second line.** A type / category /
|
|
31
38
|
attribute / count is not a status — it belongs under its identity as `size="xs" color="muted"`,
|
|
32
39
|
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,22 @@ 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
|
+
## 21.2.0 — `Stepper` is a list, not a progressbar
|
|
8
|
+
|
|
9
|
+
No API changed, but the RENDERED role did, so a test that queried it breaks:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
page.getByRole("progressbar", { name: "Pick path" }) // BEFORE
|
|
13
|
+
page.getByRole("list", { name: "Pick path" }) // AFTER — <ul> of <li>, one per Step
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`progressbar` is a range widget: without `aria-valuenow`/`min`/`max` it announces as an
|
|
17
|
+
indeterminate "busy", and its children are PRESENTATIONAL — which hid every step's label, and
|
|
18
|
+
in a `Pipeline` the date pickers, selects and buttons a stage carries. A sequence of named
|
|
19
|
+
positions is a `list` whose live entry has `aria-current="step"`. `StepProgress` keeps
|
|
20
|
+
`progressbar` — its segments really are decoration over one quantity — and now carries the
|
|
21
|
+
values it was missing.
|
|
22
|
+
|
|
7
23
|
## v21 from 20.x
|
|
8
24
|
|
|
9
25
|
**`FilesEditor` is a COMPOUND.** It rendered a fixed toolbar — Upload · Select · Download all,
|
package/docs/catalog.md
CHANGED
|
@@ -112,9 +112,10 @@ its NAME beside it), never a `DetailTable` in a `TaskDetail`, which declares a g
|
|
|
112
112
|
The SAME composition serves a record's 5–8-task drawer checklist and a grouped desk board,
|
|
113
113
|
because a sub-row reflows instead of being authored per surface; add `SuggestionChip` commons +
|
|
114
114
|
`CaptureRow` for the checklist case. **A list you scan DOWN columns — the same four values
|
|
115
|
-
compared across twenty rows — is a `Table`, not a `TaskList`.**
|
|
116
|
-
[`tpl_record`](../examples/tpl_record.tsx)
|
|
117
|
-
|
|
115
|
+
compared across twenty rows — is a `Table`, not a `TaskList`.** And a record's own PROGRESS is
|
|
116
|
+
not a checklist at all — that's `Pipeline` ([`tpl_record`](../examples/tpl_record.tsx) § Progress).
|
|
117
|
+
See [`tpl_item_list`](../examples/tpl_item_list.tsx) for the checklist grammar, and
|
|
118
|
+
[`tpl_task_board`](../examples/tpl_task_board.tsx) for columns.
|
|
118
119
|
|
|
119
120
|
### Tabular data — pick by SCALE + intent
|
|
120
121
|
|
|
@@ -158,7 +159,9 @@ plain sm tabular count beside it — the cell/heading/peek-trigger meter; a capt
|
|
|
158
159
|
above a tiny bar reads misaligned. **The track clamps at 100%, the caption does not** — over
|
|
159
160
|
its max it reads `2,100 / 2,000 · 105%`, because a meter that says "100%" when you are over
|
|
160
161
|
tells the reader they are exactly at the limit. Numbers format in the reader's locale, so
|
|
161
|
-
never hand-format the value you pass in
|
|
162
|
+
never hand-format the value you pass in — when display precision differs from the true value
|
|
163
|
+
(whole credits off a fractional balance), `formatValue` reshapes the caption text and leaves
|
|
164
|
+
the fill and the percentage exact) / `StackedProgressBar` / `StepProgress`, `Breakdown` (a
|
|
162
165
|
stacked bar + ranked share rows, pressable to drill; `maxRows` folds the long tail behind a
|
|
163
166
|
"Show N more" toggle — `labels` to localize — so several facet cards align to one height in
|
|
164
167
|
a row), `Funnel` (a CONVERSION funnel — ordered stages as bars that NARROW; the step
|
|
@@ -687,7 +690,7 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
687
690
|
VALUE-FIRST: the date drops its resting calendar glyph, a select drops its chevron (the column
|
|
688
691
|
header + the uniformly-editable grid are the affordance; the saving spinner still shows). For a
|
|
689
692
|
DENSE, uniformly-editable surface — a register/`DataGrid` column, a task row (worked example:
|
|
690
|
-
`tpl_task_board`'s columns, `
|
|
693
|
+
`tpl_task_board`'s columns, `tpl_item_list`'s rows).
|
|
691
694
|
|
|
692
695
|
There is NO separate `*Cell` component family — a data-grid cell is `<InlineSelect variant="cell" …/>`,
|
|
693
696
|
not a `SelectCell`. (Naming a component for a USE, and duplicating the picker stack to flip two
|
|
@@ -983,7 +986,9 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
983
986
|
plain sm tabular count beside it.
|
|
984
987
|
- **`stacked_progress_bar`** — `StackedProgressBar`: one whole split across segments (a
|
|
985
988
|
status mix on one bar).
|
|
986
|
-
- **`step_progress`** — `StepProgress`: N-of-M dots/segments progress.
|
|
989
|
+
- **`step_progress`** — `StepProgress`: N-of-M dots/segments progress. A real `progressbar`
|
|
990
|
+
(valuenow/min/max) because its segments are decoration over ONE quantity — the opposite
|
|
991
|
+
case from `stepper`, whose steps carry content a `progressbar` would hide.
|
|
987
992
|
- **`breakdown`** — `Breakdown`: a stacked bar + ranked share rows, pressable to drill;
|
|
988
993
|
`maxRows` folds the long tail behind a localized "Show N more" toggle
|
|
989
994
|
(`BreakdownLabels`).
|
|
@@ -1020,11 +1025,23 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1020
1025
|
provider-wired — pass `labels` (`DEFAULT_GANTT_LABELS` is English).
|
|
1021
1026
|
- **`timeline`** — `Timeline`: a heterogeneous event LOG — per-row icon + expandable
|
|
1022
1027
|
details; models the past, NOT progress.
|
|
1028
|
+
- **`pipeline`** — `Pipeline` + `PipelineStage` + `PipelineField` / `PipelineNote` /
|
|
1029
|
+
`PipelineActions` — the handoff COMPOUND: one record walking ordered STAGES where each stage
|
|
1030
|
+
owns its own fields, conditions and act. Composes over `stepper` (which renders position
|
|
1031
|
+
only). Reach for it over `task` when the rows are POSITIONS rather than work items — one thing
|
|
1032
|
+
moving, one stage live, different controls per stage; `task` is N identical rows ticked in any
|
|
1033
|
+
order. `PipelineNote` is a condition ON a stage (never a `Callout` above the run);
|
|
1034
|
+
`PipelineField` stays editable on a PASSED stage, which is what makes a mis-entry fixable.
|
|
1035
|
+
Worked screen: `examples/tpl_record.tsx` § Progress — the desks (Sales → Operations →
|
|
1036
|
+
Accounting) ARE the stages, each owning the facts it stamps and, on the live one, the act
|
|
1037
|
+
that leaves it. A `PipelineStage` is deliberately NOT pressable: its body holds the controls.
|
|
1023
1038
|
- **`stepper`** — `Stepper` + `Step` — done/current/upcoming/warning/complete progress on a
|
|
1024
1039
|
track (horizontal) or spine (vertical); compound `<Step status>children` OR data
|
|
1025
1040
|
`steps[]`+`current`; **navigable** via `Step.onPress` (both orientations — the whole step
|
|
1026
1041
|
is the tap target) + `active` to wash the selected one, so it doubles as a section/phase
|
|
1027
|
-
switcher; the guided-run / agent-feed primitive.
|
|
1042
|
+
switcher; the guided-run / agent-feed primitive. It is a **`list` of `listitem`s** with
|
|
1043
|
+
`aria-current="step"` on the live one — a sequence of NAMED positions whose steps carry
|
|
1044
|
+
their own content is a list, never a `progressbar`.
|
|
1028
1045
|
|
|
1029
1046
|
### Files
|
|
1030
1047
|
|
package/docs/templates.md
CHANGED
|
@@ -41,8 +41,10 @@ the package index is [../AGENTS.md](../AGENTS.md).
|
|
|
41
41
|
| A register / consolidated work-list (browse, per-row action, bulk action) | `tpl_item_list` |
|
|
42
42
|
| A guided sequence of physical tasks (scan, confirm, next) | `tpl_pick` |
|
|
43
43
|
| Splitting one source amount across many targets | `tpl_allocate` |
|
|
44
|
-
| A record's create/edit surface — also the settings shape
|
|
44
|
+
| A record's create/edit surface — also the settings shape | `tpl_record` |
|
|
45
|
+
| A checklist ON a record (the canonical task-list grammar) | `tpl_item_list` (its Tasks section) |
|
|
45
46
|
| A team task board (inline-managed grouped table) | `tpl_task_board` |
|
|
47
|
+
| One record HANDED between desks — stages that each own their controls | `tpl_record` (its Progress section) |
|
|
46
48
|
| Financial statements | `tpl_statements` |
|
|
47
49
|
| A scoped lookup report with export | `tpl_report` |
|
|
48
50
|
| A week calendar + agenda | `tpl_calendar` |
|
|
@@ -258,10 +260,10 @@ left panel as the bare circular `BackButton`). First paint is a `Skeleton` MIRRO
|
|
|
258
260
|
layout, never a spinner. It absorbed the old order-form, inline-record, intake, settings,
|
|
259
261
|
billing, and quick-capture templates. Top → bottom:
|
|
260
262
|
|
|
261
|
-
- A MINIMAL header: `RecordSummary` (title · subtitle ONLY — no stage chip, no metric;
|
|
262
|
-
carries
|
|
263
|
+
- A MINIMAL header: `RecordSummary` (title · subtitle ONLY — no stage chip, no metric; Progress
|
|
264
|
+
carries the desk, Handoff carries what it created, money lives in Billing), then the record's
|
|
263
265
|
ATTENTION state as a co-located `Callout` (e.g. overdue — record-scoped state reads here;
|
|
264
|
-
field-scoped state stays on its field), then a quiet `SummaryLine` (
|
|
266
|
+
field-scoped state stays on its field), then a quiet `SummaryLine` (desk · documents
|
|
265
267
|
· to collect).
|
|
266
268
|
- **GENERAL — the MAIN details, FIRST in the rail**; every later section is supplementary.
|
|
267
269
|
A `SubsectionStack` (space-only beat) of a headingless LEAD group (the key facts) plus
|
|
@@ -283,20 +285,15 @@ billing, and quick-capture templates. Top → bottom:
|
|
|
283
285
|
(author-only edit/delete; attachments as a pressable `FileGrid` → gallery preview; a
|
|
284
286
|
file-capable edit form injected via `renderEditForm`) + THE kit `Composer` (attach via
|
|
285
287
|
`actionsButton`, staged files in its `files` slot) — never a bespoke comment box.
|
|
286
|
-
- **
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
the
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
`TaskList` of four child ticks, each a `TaskItem` with a STRING `TaskTitle`; every other row
|
|
296
|
-
holds an empty array and renders no list at all. There is no built-in expander: collapsing is
|
|
297
|
-
the app's call, and this template always shows them. It is the line to copy — a booking's steps
|
|
298
|
-
carry only a tick, so they stay child rows; anything needing its own due date or assignee is a
|
|
299
|
-
task instead.
|
|
288
|
+
- **Progress** — the desk handoff as the ordered positions it is: a bare `Pipeline` over
|
|
289
|
+
Sales → Operations → Accounting. Each REACHED stage owns the facts it stamps as
|
|
290
|
+
`PipelineField`s (taken-on `InlineDatePicker`, owner `InlineMemberSelect`) and keeps them
|
|
291
|
+
editable once the record has moved on; the LIVE one adds its condition (`PipelineNote`, e.g.
|
|
292
|
+
past the due date) and the single act that leaves it (`PipelineActions` → the handoff dialog).
|
|
293
|
+
An unreached stage is its title alone. `meta` carries how long the desk has held it — prose
|
|
294
|
+
the reader can't set, never the date that the stage's own field already shows. See § The
|
|
295
|
+
handoff shape for the rules; for a record that genuinely needs a CHECKLIST, the task-list
|
|
296
|
+
grammar is worked in `tpl_item_list`.
|
|
300
297
|
- **Documents** — the Agents "Document desk" pattern (this template is its worked example —
|
|
301
298
|
see the Agents chapter below): the register `Table` (search · Add files) whose selection
|
|
302
299
|
feeds the `FloatingActionBar` → ONE "Use AI" fork (extract / cross-check / edit-with-AI).
|
|
@@ -385,9 +382,16 @@ billing, and quick-capture templates. Top → bottom:
|
|
|
385
382
|
here: the dialog collects the receiver (`MemberSelect`, confirm disabled until chosen) +
|
|
386
383
|
an optional note; confirm writes the trail mark and the SIBLING record, shown as the same
|
|
387
384
|
linked-record box (its drawer holds the reference info + Open record + **Recall**). After
|
|
388
|
-
the handoff there is NO further CTA
|
|
389
|
-
|
|
390
|
-
|
|
385
|
+
the handoff there is NO further CTA — the act to leave the NEW desk rides that desk's stage
|
|
386
|
+
in Progress, and this section shows only what the handoff produced (with an empty state when
|
|
387
|
+
it has produced nothing yet).
|
|
388
|
+
|
|
389
|
+
Recall is the undo: confirmed, it withdraws the sibling, clears the custody stamp that
|
|
390
|
+
handoff wrote, and returns the record to the desk BEFORE it — one step, never a jump to the
|
|
391
|
+
first desk, which would silently drop the desks between. History is NEVER erased (the trail
|
|
392
|
+
keeps both marks) and the CTA returns, so redo is possible. **Only the LATEST handoff offers
|
|
393
|
+
Recall.** Undoing a superseded one would leave the record behind a sibling that still exists
|
|
394
|
+
— the stage and the linked records would disagree — so a walk-back is one handoff at a time.
|
|
391
395
|
- **Danger zone** — with the full section anatomy (heading + description) like every other
|
|
392
396
|
section; the fenced red `DangerZone` card is the section's BODY.
|
|
393
397
|
- A LEFT OUTLINE RAIL (`MenuButton` + `useSectionNav`) — **the rail is the page's COMPLETE
|
|
@@ -415,6 +419,51 @@ billing, and quick-capture templates. Top → bottom:
|
|
|
415
419
|
below that it collapses to the pinned bar. Sizing the column is the SHELL's job — inner
|
|
416
420
|
blocks are plain `width: "100%"`, never a second `maxWidth` + `alignSelf: "center"`.
|
|
417
421
|
|
|
422
|
+
### The handoff shape — `Pipeline`, and where it lives
|
|
423
|
+
|
|
424
|
+
One record walking N ordered stages, where **the stage decides what you can see and do**: work
|
|
425
|
+
passed between desks — an application through intake → review → production → filing, a claim
|
|
426
|
+
through submitted → assessed → paid.
|
|
427
|
+
|
|
428
|
+
It is NOT its own template. A handoff is something a RECORD does, so it renders as one section
|
|
429
|
+
OF that record — see `tpl_record` § Progress, where the desks (Sales → Operations → Accounting)
|
|
430
|
+
become the stages, each owning the facts it stamps (taken-on, owner) and the live one carrying
|
|
431
|
+
the act that leaves it.
|
|
432
|
+
|
|
433
|
+
**It replaced a per-desk CHECKLIST, and that swap is the lesson.** Ticking boxes described the
|
|
434
|
+
WORK; it never said where the record SAT, so the reader had to infer position from which group
|
|
435
|
+
still had unticked rows — and the handoff CTA sat in a different section entirely, the act
|
|
436
|
+
divorced from the state that gated it. A stage says the position outright, and the act rides the
|
|
437
|
+
stage it belongs to. Reach for a checklist only when the rows are genuinely N independent
|
|
438
|
+
tickable items (`TaskList`); a record's own progress is a pipeline.
|
|
439
|
+
|
|
440
|
+
Built on the `Pipeline` compound (`Pipeline` · `PipelineStage` · `PipelineField` ·
|
|
441
|
+
`PipelineNote` · `PipelineActions`), which composes over `Stepper` — `Stepper` renders POSITION,
|
|
442
|
+
this adds the anatomy that turns a position into a workspace.
|
|
443
|
+
|
|
444
|
+
Three rules the anatomy holds, each learned from getting it wrong:
|
|
445
|
+
|
|
446
|
+
- **Only the CURRENT stage carries an act.** A control on an unreached stage invites acting out
|
|
447
|
+
of order — and where the stage is derived from the highest stamp, one stray press jumps the
|
|
448
|
+
record past the desk that owns it. On a passed stage it re-offers something already done.
|
|
449
|
+
- **A condition belongs to its stage.** "Sent back", "rejected", "waiting on the customer" are
|
|
450
|
+
facts about ONE stage, so they render inside it (`PipelineNote`) rather than as a `Callout`
|
|
451
|
+
above the run, which reads as "something is wrong with this record" and sits nowhere near the
|
|
452
|
+
control that answers it.
|
|
453
|
+
- **A passed stage stays correctable** — its date (clearable, which is how you walk a record
|
|
454
|
+
BACK) and any field it owns. Otherwise a value typed wrong becomes unreachable the moment the
|
|
455
|
+
record moves on, and the only fix is direct table access.
|
|
456
|
+
- **The stage that OPENS gets stamped by the act that opened it**, and the TERMINAL act is not
|
|
457
|
+
a handoff. Handing off asks whom (a dialog) and writes that answer into the receiving stage's
|
|
458
|
+
own fields — coming up blank re-asks a question just answered. Finishing has no receiving
|
|
459
|
+
desk, so it asks for confirmation and nothing else; routing it through the same dialog is how
|
|
460
|
+
a template ends up asking "Assignee at Closed" and then confirming nothing.
|
|
461
|
+
|
|
462
|
+
**Altitude rule**: the pipeline is ONE record's progress. N records each at their own stage is
|
|
463
|
+
a REGISTER (`tpl_item_list`) with a derived stage column — the same ladder module feeding both,
|
|
464
|
+
so a row's badge and its filter bucket can never disagree. Rows that are structurally identical
|
|
465
|
+
and tickable in any order are a `tpl_task_board`, not a pipeline.
|
|
466
|
+
|
|
418
467
|
### `tpl_task_board` — the columns shape
|
|
419
468
|
|
|
420
469
|
The manager's board: a search · group-by · filter toolbar over a grouped, sortable grid of
|