@lotics/ui 47.5.2 → 47.6.1
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 +22 -3
- package/MIGRATION.md +61 -62
- package/docs/ai_patterns.md +9 -2
- package/docs/catalog.md +43 -6
- package/docs/composition.md +148 -10
- package/docs/data_entry.md +8 -0
- package/docs/reviewing.md +56 -2
- package/examples/tpl_attendance.tsx +1 -1
- package/package.json +3 -1
- package/src/alert.tsx +1 -1
- package/src/avatar.tsx +1 -1
- package/src/avatar.web.tsx +1 -1
- package/src/avatar_group.tsx +1 -1
- package/src/bar_chart.tsx +10 -1
- package/src/board.tsx +1 -1
- package/src/button.tsx +4 -4
- package/src/cell_stack.tsx +140 -0
- package/src/column_filter.tsx +1 -1
- package/src/combobox.tsx +2 -2
- package/src/comments_thread.tsx +2 -2
- package/src/count.tsx +32 -16
- package/src/date_calendar.tsx +2 -2
- package/src/date_filter.tsx +1 -1
- package/src/diff_value.tsx +2 -2
- package/src/eyebrow.tsx +1 -1
- package/src/file_thumbnail.tsx +2 -2
- package/src/file_thumbnail_grid.tsx +1 -1
- package/src/filter_chip.tsx +5 -2
- package/src/finding.tsx +19 -2
- package/src/form_field.tsx +1 -1
- package/src/inline_date_picker.tsx +1 -1
- package/src/inline_edit.tsx +2 -1
- package/src/line_chart.tsx +3 -1
- package/src/list_item.tsx +1 -1
- package/src/loading.tsx +1 -1
- package/src/matrix.tsx +1 -1
- package/src/member_chip.tsx +1 -1
- package/src/member_profile_card.tsx +1 -1
- package/src/menu_list_item.tsx +2 -2
- package/src/metric.tsx +1 -1
- package/src/option_list.tsx +1 -1
- package/src/page_header.tsx +26 -25
- package/src/pagination.tsx +1 -1
- package/src/pie_chart.tsx +4 -2
- package/src/progress_bar.tsx +20 -11
- package/src/radio_picker.tsx +3 -3
- package/src/section_heading.tsx +74 -5
- package/src/segmented_control.tsx +1 -1
- package/src/select.tsx +1 -1
- package/src/shortcut_badge.tsx +1 -1
- package/src/stacked_bar_chart.tsx +1 -1
- package/src/switcher.tsx +1 -1
- package/src/table.tsx +46 -8
- package/src/tabs.tsx +2 -2
- package/src/text.tsx +2 -7
- package/src/text_ink.ts +96 -0
- package/src/text_link.tsx +1 -1
- package/src/text_utils.ts +1 -46
- package/src/thumbnail_stack.tsx +1 -1
- package/src/time_picker.tsx +1 -1
- package/src/timeline.tsx +1 -1
- package/src/tokens.ts +28 -4
- package/src/tooltip.tsx +1 -1
- package/src/uploading_thumbnail.tsx +1 -1
package/AGENTS.md
CHANGED
|
@@ -16,9 +16,9 @@ CURRENT major only — upgrading an app across majors is `MIGRATION.md`.
|
|
|
16
16
|
|---|---|
|
|
17
17
|
| [docs/catalog.md](./docs/catalog.md) | **The complete inventory** — incl. `just_arrived` (`useJustArrived` + `TableRow`'s `justArrived`: the one-shot wash a row wears when it LANDS, so a realtime push is visible rather than one row of two hundred silently changing) — Reach-by-role (each data role → the ONE canonical component) + every `@lotics/ui/<module>` entry point (incl. `@lotics/ui/vite`'s `loticsOptimizeDeps` + `loticsResolve()` — the pre-bundle list and the whole `resolve` block a custom-code app's `vite.config.ts` imports rather than hand-carries, dev-link included). Read before building any screen; reuse first. |
|
|
18
18
|
| [docs/data_entry.md](./docs/data_entry.md) | Which editing pattern for which job — inline edit, fieldset forms, choosing a CHOICE control by option count, find-or-create (`Combobox`), line items, handoffs, phased records, billing, tags, dispositions, attachments (`InlineFiles` for a record ROW, the `FilesEditor` COMPOUND for a whole section, plus the three-way file INTAKE), stage gates, and the commit-on-blur vs action-press ordering law. |
|
|
19
|
-
| [docs/ai_patterns.md](./docs/ai_patterns.md) | AI acts, the human stays in charge — composer, live run feed (`AgentRun`), the one law's split — it turns on WHO supplied the values; findings, provenance, confidence; **after the run** — a stored record that fills up from several writers; the whole run in a dialog, **stopping**; **review surfaces compose from atoms** — `DiffValue`, `DiffMark`, `useChangeSet`. |
|
|
20
|
-
| [docs/composition.md](./docs/composition.md) | The design-language contract — **the form comes before the treatment** (name what the subject IS before reaching for parts), canvas + content column, heading altitude, register vs inset rows, the button ladder, master-detail `Drawer`, the register's rhythm, craft and TRIAGE bands, where the accent goes, theming as an app-level ESCAPE HATCH, color discipline, typography, **one fact one surface** (a chooser over the thing it chooses is a SELECTOR, not a second card grid; a control that only swaps one number for another is replaced by showing both), **a width floor answers can this be READ and never can this be operated** (the operating question passes a row whose every string is already cut), **a status column earns its slot by carrying a REASON rather than a state** (the floor asks for the fact to be visible, not for a badge), **a row subject's supporting line takes a REFERENCE and never a sentence** (an explanation truncates to the clause the reader already knew), **a list stays fast by keeping IDENTITY rather than memoizing** (key by the record not the index; `memo` is the last resort and does nothing against a freshly-built prop), and where a commit sits. |
|
|
21
|
-
| [docs/reviewing.md](./docs/reviewing.md) | **Reviewing a screen you built — and the answer when one "looks bad"** — the other docs say what good looks like; this one says how to find out whether you achieved it. Run it BEFORE the deploy: a typecheck, a lint, a test and `app check` are all blind to how a screen reads. GATES that outrank every treatment question, then the probes, each naming what to COLLECT and the SIGNATURE in the numbers — including the truncation sweep (a row whose halves both measure fine and whose text is cut) the summary-vs-facet check (a strip that keeps describing the unfiltered set) and the derivable-column test (a status badge its neighbour already answers) and the cross-FRAME check (what the screen destroys when a row arrives — the one defect that exists in no single frame). Plus the extraction snippets, what measurement cannot see, and how to act on a finding. |
|
|
19
|
+
| [docs/ai_patterns.md](./docs/ai_patterns.md) | AI acts, the human stays in charge — composer, live run feed (`AgentRun`), the one law's split — it turns on WHO supplied the values; findings, provenance, confidence (`Finding` is filed here because AI produces most of them, NOT because it is AI-only — a rules-derived contradiction is as in scope as an extraction's); **after the run** — a stored record that fills up from several writers; the whole run in a dialog, **stopping**; **review surfaces compose from atoms** — `DiffValue`, `DiffMark`, `useChangeSet`. |
|
|
20
|
+
| [docs/composition.md](./docs/composition.md) | The design-language contract — **the form comes before the treatment** (name what the subject IS before reaching for parts), canvas + content column, heading altitude, register vs inset rows, the button ladder, master-detail `Drawer`, the register's rhythm, craft and TRIAGE bands, where the accent goes, theming as an app-level ESCAPE HATCH, color discipline, typography, **one fact one surface** (a chooser over the thing it chooses is a SELECTOR, not a second card grid; a control that only swaps one number for another is replaced by showing both), **a width floor answers can this be READ and never can this be operated** (the operating question passes a row whose every string is already cut), **a status column earns its slot by carrying a REASON rather than a state** (the floor asks for the fact to be visible, not for a badge), **an identity mark's GLYPH is derived from the name's distinguishing part** (an organization's first word is its legal form, so untreated every row marks one letter), **a row subject's supporting line takes a REFERENCE and never a sentence** (an explanation truncates to the clause the reader already knew), **a list stays fast by keeping IDENTITY rather than memoizing** (key by the record not the index; `memo` is the last resort and does nothing against a freshly-built prop), and where a commit sits. |
|
|
21
|
+
| [docs/reviewing.md](./docs/reviewing.md) | **Reviewing a screen you built — and the answer when one "looks bad"** — the other docs say what good looks like; this one says how to find out whether you achieved it. Run it BEFORE the deploy: a typecheck, a lint, a test and `app check` are all blind to how a screen reads. GATES that outrank every treatment question, then the probes, each naming what to COLLECT and the SIGNATURE in the numbers — including the truncation sweep (a row whose halves both measure fine and whose text is cut) the summary-vs-facet check (a strip that keeps describing the unfiltered set) and the derivable-column test (a status badge its neighbour already answers) the first-line drift a column shows when its cell is sometimes one line and sometimes two, and the cross-FRAME check (what the screen destroys when a row arrives — the one defect that exists in no single frame). Plus the extraction snippets, what measurement cannot see, and how to act on a finding. |
|
|
22
22
|
| [docs/testing.md](./docs/testing.md) | Driving the kit in a browser — the three anatomies where the a11y tree says one thing and a driver must do another: a `PressDoor` row whose named button always intercepts pointer events (by design), portalled overlays that render at the top of the DOM, and custom pointer drag that `dragTo` cannot move. |
|
|
23
23
|
| [docs/templates.md](./docs/templates.md) | The map of `examples/tpl_*.tsx` — what shape each template solves and which to start from (copy + adapt, never import) — plus the record-surface composition rules (pipeline order, static shape, decision budget) and the ACTIVITY shape — a communications feed where the row's label is the GIST and the body varies by medium, one anatomy rather than a row type per kind. |
|
|
24
24
|
|
|
@@ -81,6 +81,19 @@ CURRENT major only — upgrading an app across majors is `MIGRATION.md`.
|
|
|
81
81
|
identity. And a radius is a PROPORTION of the box (`proportionalRadius`), because a component
|
|
82
82
|
sized by data renders as a pill at one height and barely a corner at another.
|
|
83
83
|
→ [composition.md §"A body, not an edge"](./docs/composition.md).
|
|
84
|
+
- **A subject over one qualifying line is `CellStack`, never two `Text`s in a `View`.** It owns
|
|
85
|
+
the whole stacked-pair rule — which rung the caption takes (from what ELSE separates the pair),
|
|
86
|
+
which lines are tightened, and the zero gap. A hand-rolled pair gets one of the three wrong
|
|
87
|
+
silently: the excess comes from the LINE BOX, so no margin and no gap exists to explain it and
|
|
88
|
+
no spacing probe can see it.
|
|
89
|
+
→ [catalog.md §"Lists, tables & registers"](./docs/catalog.md),
|
|
90
|
+
[composition.md §"Typography"](./docs/composition.md).
|
|
91
|
+
- **An exception a CHECK produced is `Finding`; a state with nothing to contradict it is a
|
|
92
|
+
`Callout`.** The discriminator is the shape of what was found, never who found it — two
|
|
93
|
+
readings that disagree plus a magnitude is a `Finding` whether an extraction or a rules engine
|
|
94
|
+
compared them. Reaching for a Callout on a real contradiction throws away the ranking, the
|
|
95
|
+
delta and the provenance, and the call site cannot get them back.
|
|
96
|
+
→ [catalog.md §"Status / feedback"](./docs/catalog.md), `src/finding.tsx`.
|
|
84
97
|
- **`Badge` = STATUS only; supporting detail is the muted second line.** A type / category /
|
|
85
98
|
attribute / count is not a status — it belongs under its identity as `size="xs" color="muted"`,
|
|
86
99
|
never a second chip. →
|
|
@@ -151,6 +164,12 @@ CURRENT major only — upgrading an app across majors is `MIGRATION.md`.
|
|
|
151
164
|
`detail` + `expanded` reveal the detail beneath the row; keep the drawer for a heavy form.
|
|
152
165
|
→ [composition.md §"No dead rows"](./docs/composition.md),
|
|
153
166
|
[catalog.md §"Lists, tables & registers"](./docs/catalog.md).
|
|
167
|
+
- **A register with a TRAILING CONTROL beside multi-line cells passes `Table align="top"`.**
|
|
168
|
+
Centring is per cell, so one taller cell drops the control below the field it acts on by a
|
|
169
|
+
data-dependent amount. Without such a control keep the default — centring is what makes a
|
|
170
|
+
one-line cell sit level with its two-line neighbours rather than stranded at the top.
|
|
171
|
+
→ [composition.md §"No dead rows"](./docs/composition.md),
|
|
172
|
+
[reviewing.md probe 8d](./docs/reviewing.md).
|
|
154
173
|
- **ONE LEFT EDGE — a row that paints a wash BLEEDS it, and never insets its content.**
|
|
155
174
|
`marginHorizontal: -ROW_WASH_BLEED` absorbed by an equal `paddingHorizontal` is net zero, so
|
|
156
175
|
a row's content sits on its container's own edge. **An indent is legible only when something
|
package/MIGRATION.md
CHANGED
|
@@ -101,7 +101,68 @@ exported for anything that needs the same lane geometry.
|
|
|
101
101
|
There are deliberately **no dependency connectors**. Lane order and bar position already carry
|
|
102
102
|
the sequence, and elbow arrows over an already-ruled grid restate it as line noise.
|
|
103
103
|
|
|
104
|
+
## 47.0.0
|
|
105
|
+
**`Text`'s `color` drops every palette name, and `inverted` becomes `onInverse`.** The vocabulary
|
|
106
|
+
is now seven ROLES and no shades: `default`, `muted`, `inactive`, `onInverse`, `danger`, `warning`,
|
|
107
|
+
`success`. `zinc-900` / `zinc-700` / `zinc-500` / `zinc-400` no longer typecheck.
|
|
108
|
+
|
|
109
|
+
```diff
|
|
110
|
+
-<Text color="zinc-500">{caption}</Text>
|
|
111
|
+
+<Text color="muted">{caption}</Text>
|
|
112
|
+
-<Text color="inverted">{label}</Text>
|
|
113
|
+
+<Text color="onInverse">{label}</Text>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Map them: `zinc-900` → `default` (it was the same ink under a second name), `zinc-700` and
|
|
117
|
+
`zinc-500` → `muted`, `zinc-400` → `inactive`. **Text previously set to `zinc-500` gets slightly
|
|
118
|
+
darker**, which is the point — it clears AA on white by 0.33 (4.83:1) and FAILS on `zinc-100`, the
|
|
119
|
+
kit's own selected-row ground, at 4.40:1, for text at `sm`/`xs` where the bar is 4.5. A call site
|
|
120
|
+
naming a shade cannot know which ground it will land on; a role is resolved once against the
|
|
121
|
+
darkest ground the kit paints. `text_ink_contrast.test.ts` now asserts this for every ink, over a
|
|
122
|
+
list the `TextColor` type is DERIVED from, so a new ink cannot ship unchecked.
|
|
123
|
+
|
|
124
|
+
`inverted` → `onInverse` names the GROUND rather than the operation: it is the one ink that is
|
|
125
|
+
illegal on the canvas, and the contract a caller needs is "there must be a dark surface under this".
|
|
126
|
+
|
|
127
|
+
**`TextColor`, `getTextColor` and `TEXT_COLORS` moved** from `@lotics/ui/text_utils` to
|
|
128
|
+
**`@lotics/ui/text_ink`**, which is react-native-free so `@lotics/ui/tokens` can be imported by an
|
|
129
|
+
app that hand-rolls plain DOM. `text_utils` keeps the input-metrics exports.
|
|
130
|
+
|
|
131
|
+
**New: the ink vocabulary is addressable.** `TEXT_INK` is an alias table (`muted` → `zinc.600`),
|
|
132
|
+
`textInkTokens()` serializes both layers in the W3C Design Tokens format with the alias intact for
|
|
133
|
+
a Figma Variables import, and `getCssVariables()` gains `--lotics-ink-*` pointing at the primitive
|
|
134
|
+
var rather than copying its value.
|
|
135
|
+
|
|
104
136
|
## 46.3.0
|
|
137
|
+
**Six components lay themselves out differently at NARROW widths, and the three charts no longer
|
|
138
|
+
claim their host's height.** No type changes and nothing to edit — but each of these was invisible
|
|
139
|
+
at 1280 and therefore invisible to the width most reviews measure, so a screen you signed off at a
|
|
140
|
+
desk width may look different on a phone now (better, is the intent).
|
|
141
|
+
|
|
142
|
+
- **`Tabs` scrolls.** The strip was a plain row with no wrap and no scroller, so once the options
|
|
143
|
+
exceeded the container the trailing tabs were cut by whatever clipped the surface — a tab band
|
|
144
|
+
partitions a register, so on a phone a whole band was unreachable. It is now a horizontal
|
|
145
|
+
`ScrollView`. If you wrapped `Tabs` in your own scroller, delete yours; nesting two is what
|
|
146
|
+
makes a strip that scrolls in one direction only.
|
|
147
|
+
- **`BarChart`, `LineChart` and `PieChart` are content-sized.** All three declared `flex: 1` on
|
|
148
|
+
their root, which RN-Web resolves to a zero basis on the parent's main axis — so dropping one
|
|
149
|
+
into a card body (a vertical stack) collapsed it to no height and painted its fixed-height
|
|
150
|
+
content outside the card. `Funnel` and `Breakdown` were content-sized all along. **If you
|
|
151
|
+
neutralised this by wrapping a chart in a row, that wrapper is now unnecessary**; a chart that
|
|
152
|
+
should fill a box is told so on the box.
|
|
153
|
+
- **`SectionHeading`'s actions wrap as ONE group.** With two verbs, one stayed on the title row
|
|
154
|
+
and the other dropped to the next at a different indent, so a single action group rendered as
|
|
155
|
+
two unrelated controls. Two or more trailing children are now wrapped in one row that moves
|
|
156
|
+
together, and the heading top-aligns so that group rides the title's FIRST line instead of the
|
|
157
|
+
centre of a column whose height came from however many lines the description wrapped to. One
|
|
158
|
+
trailing child keeps the previous geometry exactly.
|
|
159
|
+
- **`Finding`'s headline stacks at narrow widths.** Side by side, a title long enough to wrap
|
|
160
|
+
broke AROUND the delta and the sentence read as two fragments with a number interposed. It
|
|
161
|
+
never overflowed — it only wrapped mid-sentence — so no clipping probe saw it.
|
|
162
|
+
- **`PageHeader`'s description sits with the title, above the actions.** It rendered after the
|
|
163
|
+
whole title row, and that row wraps, so at narrow widths the reading order became title → verbs
|
|
164
|
+
→ the sentence explaining them. `actions` was effectively unusable on any header with a
|
|
165
|
+
`description`.
|
|
105
166
|
|
|
106
167
|
**A `Text` with `numberOfLines` now declares `flexShrink: 1` + `minWidth: 0` for you.**
|
|
107
168
|
A clamp that cannot shrink cannot clamp: on web a clamped `Text` is `white-space: nowrap`, so
|
|
@@ -189,7 +250,6 @@ so `status` changes identity whenever a decision does — which a screen that me
|
|
|
189
250
|
`review.status` needs, and which a predicate held out of the dependency lists could not give.
|
|
190
251
|
|
|
191
252
|
## 46.0.0
|
|
192
|
-
|
|
193
253
|
**`AgentRun` / `AgentProgress` drop `stepsLabel`, and the `agentRun` locale slice drops `steps`.**
|
|
194
254
|
The run row no longer prints a step count — not on the folded run row, not on a settled
|
|
195
255
|
`ToolGroup` header. The tally was a number a reader could act on in no way: while the run is live
|
|
@@ -216,7 +276,6 @@ now share a name once the work is expanded (the run row and the step it was name
|
|
|
216
276
|
`getAllByLabelText(...)[0]` over `getByLabelText` there.
|
|
217
277
|
|
|
218
278
|
## 45.9.0
|
|
219
|
-
|
|
220
279
|
**`BrandMark` no longer carries product logos, and `SwitchButton` takes `leading` instead of
|
|
221
280
|
`brand`.** `BRAND_NAMES` drops `gmail`, `outlook` and `google-drive`; the kit's marks are the
|
|
222
281
|
single-colour CC0 silhouettes that NAME a channel — `facebook`, `zalo`, `linkedin`, `x`,
|
|
@@ -234,7 +293,6 @@ A retired name no longer typechecks, and a bundle compiled against an older kit
|
|
|
234
293
|
where the mark was rather than throwing.
|
|
235
294
|
|
|
236
295
|
## 45.5.0
|
|
237
|
-
|
|
238
296
|
**`InlineSelect` and `InlineMemberSelect` are a `combobox`, not a `button`.** They rest as a
|
|
239
297
|
`<div role="combobox">` carrying `aria-expanded`, where they rested as a `<button>`
|
|
240
298
|
(`InlineMemberSelect` is built on `InlineSelect`, so it follows). Other inline fields are
|
|
@@ -273,7 +331,6 @@ owners, since ticking the box also opened the file. A slot the docs tell you to
|
|
|
273
331
|
cannot be inside the control.
|
|
274
332
|
|
|
275
333
|
## 45.0.0 — a section heading stops shouting over the panel that holds it
|
|
276
|
-
|
|
277
334
|
*A MAJOR, because an export was removed.* Every consumer pinning `^44.x` is excluded by design:
|
|
278
335
|
the removal below breaks a build, and the altitude change silently re-ranks headings in any pane
|
|
279
336
|
that already composes its body in a content region. Neither should arrive with a routine install —
|
|
@@ -330,7 +387,6 @@ sat a rung AND a weight below its own peers, measured live as 12px/400 beside 14
|
|
|
330
387
|
structural role, same treatment.
|
|
331
388
|
|
|
332
389
|
## 44.9.3 — an option's description stops being erased, and a pivot's headers rejoin the ramp
|
|
333
|
-
|
|
334
390
|
**`OptionList` no longer suppresses `getOptionDescription` when `renderOptionContent` is set.**
|
|
335
391
|
The two are independent facts about an option — how its value renders, and a subtitle under it —
|
|
336
392
|
and one was erasing the other. A caller who wanted both had one slot for two things, so they put
|
|
@@ -347,7 +403,6 @@ reading as a caption that lost its value."* A screen carrying both a `Table` and
|
|
|
347
403
|
rendered the same structural role two ways.
|
|
348
404
|
|
|
349
405
|
## 44.9.3 — the rules probe could not see a rule
|
|
350
|
-
|
|
351
406
|
**`docs/reviewing.md`'s probe 3 collector missed border-drawn rules and counted transparent
|
|
352
407
|
spacers.** Docs only, no code change — but this is the method app authors run, so it shipped a
|
|
353
408
|
blind spot: it selected on "thin and wide" with no paint check, which counts a zero-height flex
|
|
@@ -361,7 +416,6 @@ edge rather than the box origin, and reports what each rule SEPARATES — which
|
|
|
361
416
|
actually asks.
|
|
362
417
|
|
|
363
418
|
## 44.9.2 — a pivot's figures actually align, and a ledger row keeps its own name
|
|
364
|
-
|
|
365
419
|
**`Matrix.Grid`'s cell stretches its figure instead of centring it, so 44.9.1's right-alignment
|
|
366
420
|
actually applies.** A `Text` centred by its parent shrink-wraps, so the `align="right"` added in
|
|
367
421
|
44.9.1 had nothing to align against and the value cells never moved — while the headers and totals,
|
|
@@ -393,7 +447,6 @@ own code; that is the component's job.
|
|
|
393
447
|
for one line.
|
|
394
448
|
|
|
395
449
|
## 44.9.1 — a pivot's figures align, and a ledger row stops losing its own name
|
|
396
|
-
|
|
397
450
|
No API is removed and nothing fails to compile. Three renders change.
|
|
398
451
|
|
|
399
452
|
**`Matrix` right-aligns its figures instead of centring them.** Every value, column
|
|
@@ -426,7 +479,6 @@ keeps 55 and the caption 16. Any caller that dropped `meta` at small widths to d
|
|
|
426
479
|
can stop.
|
|
427
480
|
|
|
428
481
|
## 44.8.0 — a value column gets its own floor, and eight defaults stop fighting their own docs
|
|
429
|
-
|
|
430
482
|
No API is removed. Three of these change what an existing screen renders, so read them even
|
|
431
483
|
though nothing will fail to compile.
|
|
432
484
|
|
|
@@ -532,7 +584,6 @@ heading row WRAPS rather than crushing its title; `Accordion`'s meta yields befo
|
|
|
532
584
|
`CardHeaderTitle` reads the ⓘ's name from the locale pack; and `ReferenceField`'s peek footer
|
|
533
585
|
gives its clear the same resting surface as the verb beside it.
|
|
534
586
|
## 44.5.0 — `Pagination` drops the page index
|
|
535
|
-
|
|
536
587
|
The pager rendered a range AND a page index — `16–30 of 45` beside `Page 2 of 3`. Both answer
|
|
537
588
|
"where am I", and the second enables no decision the first does not: how much is left is in the
|
|
538
589
|
total, and whether this is the end is in the disabled arrow. The index is gone; the range is the
|
|
@@ -555,7 +606,6 @@ total, so a `Table` paired with the pager takes **`counted`** instead of `count`
|
|
|
555
606
|
the matched total prints twice a few rows apart.
|
|
556
607
|
|
|
557
608
|
## 44.4.0 — `MemberChip`'s `marker` is gone
|
|
558
|
-
|
|
559
609
|
A minor that broke a type, recorded here under its exact version rather than held
|
|
560
610
|
for a major: `marker` existed for one release, had a single consumer inside the
|
|
561
611
|
kit, and underlined the chip's name to say "this opens something".
|
|
@@ -578,7 +628,6 @@ requested `md`), because two lines of text stand taller than a 28px avatar. Sing
|
|
|
578
628
|
beside a two-line chip will need the number.
|
|
579
629
|
|
|
580
630
|
## 44.0.0 — `Finding` is horizontal, and `FindingComparison` is gone
|
|
581
|
-
|
|
582
631
|
`Finding` stacked six blocks — badge, title, detail, a labelled row per side, a hairline, the
|
|
583
632
|
delta, then `Sources` chips. It spent roughly 200px to say one sentence and one figure, buried
|
|
584
633
|
the delta in the middle where nothing scans it, and named every source twice: once in the
|
|
@@ -616,7 +665,6 @@ composes. Readings render at `sm` rather than `xs` — they are the values the f
|
|
|
616
665
|
and hierarchy comes from weight and colour, never from shrinking the evidence.
|
|
617
666
|
|
|
618
667
|
## 43.5.0 — registers, type and theming all change appearance
|
|
619
|
-
|
|
620
668
|
No API is removed and nothing throws, but four DEFAULTS moved, so every register and every avatar
|
|
621
669
|
in your app renders differently on upgrade. Each is reversible at the call site if you need the
|
|
622
670
|
old look while you catch up.
|
|
@@ -708,7 +756,6 @@ prop (`"open"` — no gallery), `Avatar`'s `shape` prop, and the `avatar_tone` /
|
|
|
708
756
|
`avatar_props` / `type_ramp` modules.
|
|
709
757
|
|
|
710
758
|
## 43.3.0 — a `bare` inline field sits on the column, and Enter finishes a one-line one
|
|
711
|
-
|
|
712
759
|
Two fixes to `Inline*`, both of them behaviour a caller cannot see in a prop name.
|
|
713
760
|
|
|
714
761
|
**A `bare` field now aligns its TEXT, not its box.** The field surface carries 8px
|
|
@@ -739,7 +786,6 @@ paragraph break and blur saves, exactly as before. **If you wrote
|
|
|
739
786
|
line budget** — that is now what says so.
|
|
740
787
|
|
|
741
788
|
## 43.0.0 — a time is PICKED, and there is nothing to type
|
|
742
|
-
|
|
743
789
|
`TimePicker` is no longer a segmented text field. It is the value on a pressable
|
|
744
790
|
control — the bordered surface a `Select` uses — that opens an **hour / minute /
|
|
745
791
|
day-period** picker. `InlineTimePicker` is the same thing on the inline shell.
|
|
@@ -813,7 +859,6 @@ needs the pointer, set `CURSOR_ACTION` in its style — and if it is built on th
|
|
|
813
859
|
react-native `Pressable`, note that the pointer is what you get by DEFAULT, from
|
|
814
860
|
react-native-web, unless you set `CURSOR_DEFAULT`.
|
|
815
861
|
## 42.5.0 — an expanded `Timeline` row shows its whole label
|
|
816
|
-
|
|
817
862
|
The label was clamped to two lines whether the row was open or shut. Expanding a
|
|
818
863
|
row is a request to see more of what is there, so a label that stays truncated
|
|
819
864
|
through it leaves the caller exactly one way to make its own label readable:
|
|
@@ -826,7 +871,6 @@ Nothing else changes: a collapsed row is identical, and a row whose label alread
|
|
|
826
871
|
fitted in two lines is identical open or shut.
|
|
827
872
|
|
|
828
873
|
## 42.4.0 — `Picker` is named by its `FormField`, and its way back to empty has a name
|
|
829
|
-
|
|
830
874
|
Two fixes to the same control, both about a thing on screen that the control did
|
|
831
875
|
not actually say.
|
|
832
876
|
|
|
@@ -867,7 +911,6 @@ site passing `placeholder` **as** the empty option's name should move that strin
|
|
|
867
911
|
which is why they were all rendering blanks.
|
|
868
912
|
|
|
869
913
|
## 42.0.0 — `DateFilter`'s presets are a listbox, and "Custom" is not one of them
|
|
870
|
-
|
|
871
914
|
Three defects with one root: the preset row used EMPHASIS to mean "current state", inside a
|
|
872
915
|
panel where emphasis means "action".
|
|
873
916
|
|
|
@@ -901,7 +944,6 @@ object you pass — it is an excess property now and the compiler will point at
|
|
|
901
944
|
matches no preset simply leaves every row unselected, which is what it always meant.
|
|
902
945
|
|
|
903
946
|
## 41.4.0 — embedded markdown is demoted in the OUTLINE, not only on the type ladder
|
|
904
|
-
|
|
905
947
|
`<Markdown variant="embedded">` sized its headings down and left them as the tags the author
|
|
906
948
|
wrote, so an `h2` inside a record value still landed in heading navigation as a PEER of the
|
|
907
949
|
page's own sections. Measured on a record surface, the outline read:
|
|
@@ -918,7 +960,6 @@ a section's level. **Nothing to migrate** — document-scale markdown is untouch
|
|
|
918
960
|
embedded type scale is unchanged.
|
|
919
961
|
|
|
920
962
|
## 41.3.0 — `Timeline` rows, embedded markdown, and a disclosure that is not a link
|
|
921
|
-
|
|
922
963
|
Nothing here removes an API or breaks a type. Two of the changes alter what your rows render on
|
|
923
964
|
sight; the rest is additive.
|
|
924
965
|
|
|
@@ -1001,7 +1042,6 @@ Anything that MUTATES still carries a control surface — `Button` in chrome, `I
|
|
|
1001
1042
|
field. Nothing to migrate: existing `Link`/`TextLink` usage is unaffected.
|
|
1002
1043
|
|
|
1003
1044
|
## 41.1.0 — `FileRows` no longer captions every row with the file type
|
|
1004
|
-
|
|
1005
1045
|
`meta` defaulted to the file-type label, so a row read `contract.pdf` with `PDF` under it. The
|
|
1006
1046
|
type was already stated three other ways — the `FileBadge`'s colour, the label printed inside
|
|
1007
1047
|
that glyph, and the filename's own extension — so the caption was a fourth statement of one
|
|
@@ -1024,7 +1064,6 @@ Better: pass something the NAME does not already carry — what an invoice cover
|
|
|
1024
1064
|
it, when it landed. That is what a second line is for.
|
|
1025
1065
|
|
|
1026
1066
|
## 41.0.0 — `RingGauge` is `ProgressRing`, and circular progress is one component
|
|
1027
|
-
|
|
1028
1067
|
`RingGauge` is **deleted**. `ProgressRing` replaces it and covers both what it did and the
|
|
1029
1068
|
bare arc it could not.
|
|
1030
1069
|
|
|
@@ -1066,7 +1105,6 @@ decoration inside a labelled control, and it means a bare ring must never be the
|
|
|
1066
1105
|
carrying a meaning — whatever owns it says what it measures.
|
|
1067
1106
|
|
|
1068
1107
|
## 40.0.0 — `PopoverContent` decides its own presentation; `small` is gone
|
|
1069
|
-
|
|
1070
1108
|
`PopoverContent` took a `small` prop meaning "render as a bottom sheet". It now asks
|
|
1071
1109
|
`useScreenSize()` itself. **Delete the prop** — passing it is a type error.
|
|
1072
1110
|
|
|
@@ -1095,7 +1133,6 @@ remains exported for its real uses — deciding whether a surface is a `Dialog`
|
|
|
1095
1133
|
at all, sizing touch targets, showing a keyboard shortcut.
|
|
1096
1134
|
|
|
1097
1135
|
## 39.0.0 — `PageHeader.leading` is `trailing`, and it renders AFTER the title
|
|
1098
|
-
|
|
1099
1136
|
38.0.0 shipped `leading`, a slot before the title. It is now **`trailing`**, in the same
|
|
1100
1137
|
place in the props but rendered on the other side of the title text.
|
|
1101
1138
|
|
|
@@ -1120,7 +1157,6 @@ The layout law is unchanged and now covers both: the TITLE gives way and wraps,
|
|
|
1120
1157
|
`trailing` and `actions` keep their width.
|
|
1121
1158
|
|
|
1122
1159
|
## 38.0.0 — the `lg` avatar is a control (40), not a size (48)
|
|
1123
|
-
|
|
1124
1160
|
`AVATAR_PX.lg` was 48 and `AVATAR_TEXT.lg` was `lg` type. They are now **40** and `md`
|
|
1125
1161
|
type. Every `size="lg"` avatar — `Avatar`, `MemberChip`, `GroupAvatar` — renders 8px
|
|
1126
1162
|
smaller. Nothing to pass; there is no way to ask for 48.
|
|
@@ -1148,7 +1184,6 @@ a title, hiding the CTA at narrow widths, or capping the header's width, that wo
|
|
|
1148
1184
|
is now what is distorting the layout — drop it.
|
|
1149
1185
|
|
|
1150
1186
|
## 37.0.0 — `PageContent`'s side gutter is a token, and responsive
|
|
1151
|
-
|
|
1152
1187
|
`PageContent` padded `16` at every width. It now uses `pagePad` from
|
|
1153
1188
|
`@lotics/ui/spacing` — **16 on a phone, 32 wider**. Nothing to pass; the only visible
|
|
1154
1189
|
change is that a wide page breathes where it used to sit 16px off the chrome.
|
|
@@ -1175,7 +1210,6 @@ whether `PageContent` would do — it carries the centred `maxWidth` column and
|
|
|
1175
1210
|
title band most screens re-type by hand.
|
|
1176
1211
|
|
|
1177
1212
|
## 36.0.0 — seven components stopped announcing English; their strings moved to the pack
|
|
1178
|
-
|
|
1179
1213
|
**Nothing to change if you pass a shipped pack** (`en` / `vi`) — both carry every
|
|
1180
1214
|
new entry, and no component API changed. A HAND-BUILT pack must add them:
|
|
1181
1215
|
|
|
@@ -1229,7 +1263,6 @@ If a surface of yours is genuinely not a button, say so (`accessibilityRole="lin
|
|
|
1229
1263
|
…) — or reach for `PressableRow`, which carries no role by design.
|
|
1230
1264
|
|
|
1231
1265
|
## 35.0.0 — `FilterChip` has no Clear footer; the × is the clear
|
|
1232
|
-
|
|
1233
1266
|
`FilterChip` no longer renders a Clear button in its popover footer. **Nothing to
|
|
1234
1267
|
change at a call site** — `onClear` and `clearLabel` are unchanged, and the × on
|
|
1235
1268
|
the pill still clears, still carries `clearLabel` as its tooltip, and still
|
|
@@ -1258,7 +1291,6 @@ controls with no per-option deselect), put one in the `footer` slot, which is
|
|
|
1258
1291
|
still there and is now the only thing that draws a footer band.
|
|
1259
1292
|
|
|
1260
1293
|
## 34.0.0 — one avatar rung fits a control band
|
|
1261
|
-
|
|
1262
1294
|
**`AVATAR_PX.md` is 28, not 36.** Nothing to change at a call site — `md` is still
|
|
1263
1295
|
the default and still shows two initials — but every `Avatar`, `MemberChip` and
|
|
1264
1296
|
`GroupAvatar` on that rung renders 8px smaller (its initials drop a type rung with
|
|
@@ -1302,7 +1334,6 @@ Two knock-on effects worth looking at once:
|
|
|
1302
1334
|
It always claimed to; it was 2px more padded, invisible at one line.
|
|
1303
1335
|
|
|
1304
1336
|
## 33.0.0 — `DrawerScrollArea`
|
|
1305
|
-
|
|
1306
1337
|
A `Drawer` gets the content primitive its siblings already had, named to match
|
|
1307
1338
|
`DialogScrollArea`. **Wrap your drawer body in it and delete the padding you were
|
|
1308
1339
|
applying:**
|
|
@@ -1343,7 +1374,6 @@ Import `DRAWER_GUTTER` in both cases; a hardcoded `20` stops matching the day it
|
|
|
1343
1374
|
moves.
|
|
1344
1375
|
|
|
1345
1376
|
## 32.0.0 — `Table`'s `align` prop is gone; rows are centred
|
|
1346
|
-
|
|
1347
1377
|
`align?: "center" | "top"` and the `TableAlign` type are removed. `center` was the
|
|
1348
1378
|
default and nothing shipped on `top`, so a caller passing nothing is unaffected.
|
|
1349
1379
|
|
|
@@ -1364,7 +1394,6 @@ stack — `computeTableFit` already drops to stacked below the register floor. R
|
|
|
1364
1394
|
that, or move the content to a record page. Do not reintroduce a cross-axis knob.
|
|
1365
1395
|
|
|
1366
1396
|
## 31.0.0 — avatar `size` is a rung, not a pixel count
|
|
1367
|
-
|
|
1368
1397
|
`Avatar`, `MemberChip` and `GroupAvatar` no longer take `size?: number`. They take
|
|
1369
1398
|
`size?: AvatarSize` — `"sm" | "md" | "lg" | "xl"` = **24 / 36 / 48 / 72** — defaulting to `md`.
|
|
1370
1399
|
|
|
@@ -1405,7 +1434,6 @@ The initials' TYPE SIZE now follows the rung instead of being a fixed `xs`. Most
|
|
|
1405
1434
|
large rungs: an avatar that was 80px wore 12px letters and looked empty; at `xl` it wears 28px.
|
|
1406
1435
|
|
|
1407
1436
|
## 30.0.0 — a washed row bleeds; content sits on the container's edge
|
|
1408
|
-
|
|
1409
1437
|
No API changed. Every register, table and choice list **moves its content 20px
|
|
1410
1438
|
left** onto its container's own edge, because `PressableRow` (all three
|
|
1411
1439
|
variants), `ChoiceList` and `Table` now bleed their hover/selection wash outward
|
|
@@ -1428,7 +1456,6 @@ padding, so a column that used to drop at a given width may now survive. Nothing
|
|
|
1428
1456
|
that was visible becomes hidden — the change only ever un-drops.
|
|
1429
1457
|
|
|
1430
1458
|
## 29.0.0 — review surfaces compose from atoms
|
|
1431
|
-
|
|
1432
1459
|
`ChangeReview` and its family are DELETED, replaced by three layout-free pieces. The
|
|
1433
1460
|
`change_review` export and the `changeReview` locale slice are gone. Apps pinned to 28.x are
|
|
1434
1461
|
unaffected until they upgrade.
|
|
@@ -1454,7 +1481,6 @@ The opinionated stack is not gone, it is demoted: build it in your own screen fr
|
|
|
1454
1481
|
Every app needed a slightly different shape, which is why one container could not serve them.
|
|
1455
1482
|
|
|
1456
1483
|
## 28.2.0 — `SubsectionHeadingTitle` takes a `description`
|
|
1457
|
-
|
|
1458
1484
|
Additive; nothing to change. The heading ramp's three rungs are meant to carry the SAME slots
|
|
1459
1485
|
and differ only in type size — `description` was missing from the middle one, so a group that
|
|
1460
1486
|
needed a muted line under its title had to borrow the section rung above it or hand-roll a
|
|
@@ -1474,7 +1500,6 @@ a dropped file says which bucket it belongs to) carries those regions at subsect
|
|
|
1474
1500
|
The rung is unchanged (`###`, lg semibold, level 3) — only the slot is new.
|
|
1475
1501
|
|
|
1476
1502
|
## 28.1.0 — `ChecklistItem` can announce more than its title
|
|
1477
|
-
|
|
1478
1503
|
Additive; nothing to change. `accessibilityLabel` overrides the row's accessible name, which
|
|
1479
1504
|
still defaults to `title`. It exists for a surface carrying one checklist PER person, party or
|
|
1480
1505
|
period, where the same row labels repeat and only the headings between them tell the copies
|
|
@@ -1488,7 +1513,6 @@ and always about a CONTROL's text rather than a step's, which is why it did not
|
|
|
1488
1513
|
of `task` into `checklist`.
|
|
1489
1514
|
|
|
1490
1515
|
## 28.0.0 — `task` and `pipeline` merge into `checklist`
|
|
1491
|
-
|
|
1492
1516
|
Two families had converged on one anatomy: a ring, a title, a value beside it, a muted note, a
|
|
1493
1517
|
detail block, an optional grouping level. What differed was a LINE between the rings — a mode,
|
|
1494
1518
|
not a family. The proof: a single session added `trailing`/`meta` to `TaskTitle` **and**,
|
|
@@ -1552,7 +1576,6 @@ it, and the rungs it passes show a BLANK date, which is the honest answer to "wh
|
|
|
1552
1576
|
others.
|
|
1553
1577
|
|
|
1554
1578
|
## 27.15.0 — a register row's text is selectable, and a drag no longer opens the record
|
|
1555
|
-
|
|
1556
1579
|
No API change, but two behaviors changed on **every** `PressableRow` / `TableRow` / `PressDoor`
|
|
1557
1580
|
in every app:
|
|
1558
1581
|
|
|
@@ -1572,7 +1595,6 @@ reads as a selection, not a press. Programmatic `fireEvent.click` / `press()` ar
|
|
|
1572
1595
|
The shipped `en` / `vi` packs carry it; a HAND-AUTHORED pack must add it or it will not typecheck.
|
|
1573
1596
|
|
|
1574
1597
|
## 27.13.3 — a stacked `Table` row's identity cell no longer renders its column label
|
|
1575
|
-
|
|
1576
1598
|
No API change, but the rendered output changed on NARROW containers only (below the
|
|
1577
1599
|
two-column floor, where `Table` stacks). The identity cell — column 0 — used to render as a
|
|
1578
1600
|
`DetailRow` spread like every other cell, so its column label appeared beside the value. It
|
|
@@ -1591,7 +1613,6 @@ and it had nowhere to go: a label and a full-width identity on one line with not
|
|
|
1591
1613
|
made the label collapse under a long value, which is what a narrow register used to render.
|
|
1592
1614
|
|
|
1593
1615
|
## 27.4.0 — a `Select` trigger announces as `combobox`, not `button`
|
|
1594
|
-
|
|
1595
1616
|
No API change, but the DOM and the accessibility tree changed, so **a test or script that
|
|
1596
1617
|
finds a Select by its button role must be updated**:
|
|
1597
1618
|
|
|
@@ -1611,7 +1632,6 @@ Note for `searchable`: `OptionList`'s filter input is a combobox too, so scope s
|
|
|
1611
1632
|
to the trigger (or use `.first()`) rather than assuming one match per Select.
|
|
1612
1633
|
|
|
1613
1634
|
## 27.2.0 — a `LedgerGroup`'s sum moved below its rows
|
|
1614
|
-
|
|
1615
1635
|
No API change; the rendering moved. A summed group used to print `LABEL … sum` as an eyebrow
|
|
1616
1636
|
ABOVE its rows and now closes them: the rows come first, then `Label sum` at `sm/medium`,
|
|
1617
1637
|
with no eyebrow (the label travels with the sum instead of being said twice).
|
|
@@ -1623,7 +1643,6 @@ bare rather than grouping it (a one-row group's sum only restates the row). Omit
|
|
|
1623
1643
|
remains fully supported for a statement whose groups all name categories without summing them.
|
|
1624
1644
|
|
|
1625
1645
|
## 27.0.0 — `TextButton` is REMOVED; an act carries a control surface
|
|
1626
|
-
|
|
1627
1646
|
**`@lotics/ui/text_button` is gone, with no replacement component.** It was the wrong
|
|
1628
1647
|
abstraction, and 25.0.0 had already retreated from it inside `ReferenceField`.
|
|
1629
1648
|
|
|
@@ -1661,7 +1680,6 @@ two rungs — `Button` (40px, a surface) and `InlineButton` (28px, filled, on a
|
|
|
1661
1680
|
on a value whose press opens a peek — were never this component's job and keep working.
|
|
1662
1681
|
|
|
1663
1682
|
## 26.0.0 — a section's ADD moves to its heading row; `EmptyState` loses its verb
|
|
1664
|
-
|
|
1665
1683
|
**`EmptyState.action` is REMOVED — no replacement on that component.** Two different things
|
|
1666
1684
|
were going into it, and neither belonged:
|
|
1667
1685
|
|
|
@@ -1712,7 +1730,6 @@ whose title row carries an inline control. Hand-rolling that row leaves the mark
|
|
|
1712
1730
|
text line while the label centres in the taller row, so every label reads ~10px low.
|
|
1713
1731
|
|
|
1714
1732
|
## 25.0.0 — `ReferenceField` edits in place; `onRemove` becomes `onClear`
|
|
1715
|
-
|
|
1716
1733
|
**`onRemove` is now `onClear` — a pure rename, identical behaviour.** The act was always
|
|
1717
1734
|
"detach and leave it empty"; only the VERB was wrong. Named "Remove" and coloured `danger`, a
|
|
1718
1735
|
recoverable unset wore the ink reserved for destruction. Rename the prop and nothing else
|
|
@@ -1750,7 +1767,6 @@ on the left act on the LINK, Edit and Open on the right act on the RECORD, Edit
|
|
|
1750
1767
|
filled-dark rung and handing it to Save when the draft opens.
|
|
1751
1768
|
|
|
1752
1769
|
## 24.0.0 — `TextLink` navigates, `TextButton` acts
|
|
1753
|
-
|
|
1754
1770
|
```tsx
|
|
1755
1771
|
<TextLink onPress={selectAll}>Select all</TextLink> // BEFORE
|
|
1756
1772
|
<TextButton onPress={selectAll}>Select all</TextButton> // AFTER — same look, role=button
|
|
@@ -1787,7 +1803,6 @@ by construction and keeps a 40px target via `hitSlop`. Do NOT reach for a fill-l
|
|
|
1787
1803
|
padding, so it reads as indented against the labels it should line up with.
|
|
1788
1804
|
|
|
1789
1805
|
## 23.0.0 — the `Inline*` editors are WHITE, and `variant` is renamed
|
|
1790
|
-
|
|
1791
1806
|
```tsx
|
|
1792
1807
|
<InlineSelect variant="cell" … /> // BEFORE
|
|
1793
1808
|
<InlineSelect variant="bare" … /> // AFTER — same axis, named for the LOOK not the use
|
|
@@ -1824,7 +1839,6 @@ Row hover on a dense surface is unaffected: a `TaskItem`/`PressableRow` still wa
|
|
|
1824
1839
|
What changed is only what the editor inside it looks like at rest.
|
|
1825
1840
|
|
|
1826
1841
|
## 23.0.0 — `DetailRow.trailing` and `DetailTable.trailingWidth` are DELETED
|
|
1827
|
-
|
|
1828
1842
|
A row's third column is gone; a `DetailTable` is label + value, and the value fills what the
|
|
1829
1843
|
label leaves. `InlineButton` (`@lotics/ui/inline_button`) is the replacement for the case that
|
|
1830
1844
|
mattered.
|
|
@@ -1872,7 +1886,6 @@ Porting, by what the slot held:
|
|
|
1872
1886
|
(`description` / `warning` / `error`).
|
|
1873
1887
|
|
|
1874
1888
|
## 23.0.0 — `LinkedRecordBox` is DELETED; a reference is a field
|
|
1875
|
-
|
|
1876
1889
|
```tsx
|
|
1877
1890
|
// BEFORE — a bordered card, its own section, three surfaces for one name
|
|
1878
1891
|
<LinkedRecordBox
|
|
@@ -1927,7 +1940,6 @@ Porting, piece by piece:
|
|
|
1927
1940
|
`tpl_record`'s Customer and Handoff sections are the worked examples.
|
|
1928
1941
|
|
|
1929
1942
|
## 22.0.0 — `RangeSlider` is `Slider`, and single-value is a mode on it
|
|
1930
|
-
|
|
1931
1943
|
```ts
|
|
1932
1944
|
import { RangeSlider, rangeSummary } from "@lotics/ui/range_slider"; // BEFORE
|
|
1933
1945
|
import { Slider, rangeSummary } from "@lotics/ui/slider"; // AFTER
|
|
@@ -1958,7 +1970,6 @@ the DOM as a bare `role="slider"` with no value, so a screen reader read "slider
|
|
|
1958
1970
|
`View` in both targets. A test asserting the old (absent) attributes was asserting a bug.
|
|
1959
1971
|
|
|
1960
1972
|
## 21.2.0 — `Stepper` is a list, not a progressbar
|
|
1961
|
-
|
|
1962
1973
|
No API changed, but the RENDERED role did, so a test that queried it breaks:
|
|
1963
1974
|
|
|
1964
1975
|
```ts
|
|
@@ -1974,7 +1985,6 @@ positions is a `list` whose live entry has `aria-current="step"`. `StepProgress`
|
|
|
1974
1985
|
values it was missing.
|
|
1975
1986
|
|
|
1976
1987
|
## v21 from 20.x
|
|
1977
|
-
|
|
1978
1988
|
**`FilesEditor` is a COMPOUND.** It rendered a fixed toolbar — Upload, Select, Download all,
|
|
1979
1989
|
swapping into a select-mode row whose actions hid behind a generic "Menu" — and that shape cost
|
|
1980
1990
|
two things in real screens. A HOST verb had nowhere to go, so a surface that needed one (an AI
|
|
@@ -2031,7 +2041,6 @@ function ReadWithAi() {
|
|
|
2031
2041
|
```
|
|
2032
2042
|
|
|
2033
2043
|
## v20 from 19.x
|
|
2034
|
-
|
|
2035
2044
|
**`@lotics/ui/section` is DELETED.** Two modules exported a `Section` — the layout grammar's
|
|
2036
2045
|
card-less region (`section_heading`) and a standalone titled block with its own `title` string,
|
|
2037
2046
|
`collapsible` flag and imperative `SectionHandlers.expand/collapse`. The second one predated both
|
|
@@ -2065,7 +2074,6 @@ Compose the heading rung exactly as for a static section — `SectionHeadingTitl
|
|
|
2065
2074
|
carries the same slots, so a disclosure header loses no affordance.
|
|
2066
2075
|
|
|
2067
2076
|
## v19 from 18.x
|
|
2068
|
-
|
|
2069
2077
|
**`TaskFields` is DELETED, with `fieldsWidth`.** A task row was carrying a
|
|
2070
2078
|
value COLUMN — a width declared on the list and reserved by every row. It aligned, and it read
|
|
2071
2079
|
badly: a two-word field name sat at the title's origin while its control started a quarter of
|
|
@@ -2131,7 +2139,6 @@ wrap against), and `TaskDetail` now ends on the content edge instead of overhang
|
|
|
2131
2139
|
inset.
|
|
2132
2140
|
|
|
2133
2141
|
## v18 from 17.x
|
|
2134
|
-
|
|
2135
2142
|
**`TimePicker` is a segmented field, not `<input type="time">`.** A native time input takes
|
|
2136
2143
|
its 12- vs 24-hour form from the BROWSER's UI locale and ignores the `lang` attribute
|
|
2137
2144
|
entirely, so a Vietnamese screen on an en-US browser rendered "01:45 PM" beside its own
|
|
@@ -2151,7 +2158,6 @@ The value is unchanged — canonical 24-hour `"HH:mm"` either way. Two prop chan
|
|
|
2151
2158
|
than spreading the locale pack) must add it.
|
|
2152
2159
|
|
|
2153
2160
|
## v17 from 16.x
|
|
2154
|
-
|
|
2155
2161
|
**`Checklist` / `ChecklistRow` are DELETED.** They are replaced by the `Task` compound
|
|
2156
2162
|
(`@lotics/ui/task`), which composes the anatomy instead of configuring it:
|
|
2157
2163
|
|
|
@@ -2198,7 +2204,6 @@ it through (`state={s.status === "done" ? "done" : s.status === "doing" ? "parti
|
|
|
2198
2204
|
rather than leaving the ring binary.
|
|
2199
2205
|
|
|
2200
2206
|
## v16 from 15.x
|
|
2201
|
-
|
|
2202
2207
|
**`Confidence` IS now a callout with a REQUIRED basis** — `children` (what was checked and
|
|
2203
2208
|
what came of it) is mandatory, the meter + level phrase head the block, and the box stays
|
|
2204
2209
|
white with a hairline border at every level (the meter is the only colored element). The
|
|
@@ -2211,7 +2216,6 @@ Additively in v16: `ResultHeader` (`@lotics/ui/result_header`) — the save-dire
|
|
|
2211
2216
|
outcome strip; see ai_patterns §the one law for the receipt composition.
|
|
2212
2217
|
|
|
2213
2218
|
## v15 from 14.x
|
|
2214
|
-
|
|
2215
2219
|
`AgentRun`/`AgentProgress`'s **`labelForTool`** prop was replaced by **`labelForCall`** — the
|
|
2216
2220
|
callback now receives the whole call (`AgentToolCall = { toolName, input, state }`) instead of
|
|
2217
2221
|
just the name, so labels can vary by input and by the new **`awaiting`** step state (ai's
|
|
@@ -2220,7 +2224,6 @@ an expanded step's Output panel), `onRetry` (a retry button under the terminal e
|
|
|
2220
2224
|
the new `ApprovalPrompt` + `MessageActions` components with their locale slices.
|
|
2221
2225
|
|
|
2222
2226
|
## v14 from 13.x
|
|
2223
|
-
|
|
2224
2227
|
The ai-sdk `UIMessage.parts` shape IS the `AgentRun` contract — the bespoke transcript type is
|
|
2225
2228
|
gone. `AgentRun`/`AgentProgress`'s **`items: AgentRunItem[]`** was replaced by **`parts:
|
|
2226
2229
|
readonly AgentUIPart[]`**, and the **`AgentRunItem`** / **`AgentRunStep`** / **`AgentStepStatus`**
|
|
@@ -2232,7 +2235,6 @@ parts. Additively: a run-level **`error`** prop for the BREAKING failure that li
|
|
|
2232
2235
|
— and tool I/O now expands IN PLACE on press instead of opening a `Peek` popover.
|
|
2233
2236
|
|
|
2234
2237
|
## 13.9.0 — a BREAKING type change in a MINOR
|
|
2235
|
-
|
|
2236
2238
|
**`ClarifyOption.description` went optional → REQUIRED** (every answer explains itself). It
|
|
2237
2239
|
shipped in a minor, which is why it surprises an app on `^13`: a `<Clarify options={…}>` whose
|
|
2238
2240
|
options carry only `label` stops typechecking on any 13.9.0+ install. Fix by writing the
|
|
@@ -2241,14 +2243,12 @@ eyebrow was dropped (the question text stays), and `allowCustom` ("Other…" fre
|
|
|
2241
2243
|
`ClarifyWizard` were added.
|
|
2242
2244
|
|
|
2243
2245
|
## v13 from 12.x
|
|
2244
|
-
|
|
2245
2246
|
`RadioPicker`'s **`direction`** prop was removed — the picker is always the stacked column of
|
|
2246
2247
|
full-width choices. A former `direction="row"` usage just drops the prop. Additively, `DetailRow`
|
|
2247
2248
|
and `FormField` gained a **`warning`** field annotation (amber, the third tone between
|
|
2248
2249
|
`description` and `error`).
|
|
2249
2250
|
|
|
2250
2251
|
## v12 from 11.x
|
|
2251
|
-
|
|
2252
2252
|
Two exports were removed: **`CommentComposer`** (compose comments with THE kit `Composer` —
|
|
2253
2253
|
attach via `actionsButton`/`files`; `CommentList` is unchanged) and **`DetailRow.info`** (field
|
|
2254
2254
|
annotations are explicit — use the new **`DetailRow.description`** under the value and
|
|
@@ -2262,7 +2262,6 @@ resting chip gained 6px vertical padding (identical for one-line values; multi-l
|
|
|
2262
2262
|
content now breathes).
|
|
2263
2263
|
|
|
2264
2264
|
## v11 from ≤10.x
|
|
2265
|
-
|
|
2266
2265
|
The type scale was re-slotted — the display sizes gained the missing `##` step: `xl` is now 22/24
|
|
2267
2266
|
(section title), `xxl` is 28/32 (page/record title — the OLD `xl` look), and the new `xxxl` is
|
|
2268
2267
|
32/48 (hero numbers — the OLD `xxl` look). Migrate an app with two renames IN THIS ORDER: first
|
package/docs/ai_patterns.md
CHANGED
|
@@ -607,13 +607,20 @@ fail → low) — never render a fabricated score.
|
|
|
607
607
|
|
|
608
608
|
## Findings — evidence, not writes
|
|
609
609
|
|
|
610
|
-
`Finding` (`@lotics/ui/finding`) is one ranked
|
|
611
|
-
|
|
610
|
+
`Finding` (`@lotics/ui/finding`) is one ranked discrepancy from a cross-check — a contradiction
|
|
611
|
+
between two readings, an audit observation, a briefing item — laid out HORIZONTALLY, in the order a reader
|
|
612
612
|
needs it: a severity dot, the `title`, and the `delta` right-aligned on that same line, then the
|
|
613
613
|
`readings` beneath — ONE PER LINE, each a dim `source` plus its `value`, never joined by a
|
|
614
614
|
separator. `detail` is the CONSEQUENCE and is optional — a second sentence restating the title in
|
|
615
615
|
longer words costs a line and adds nothing.
|
|
616
616
|
|
|
617
|
+
**It is described here because AI produces most of them, NOT because it is an AI component.**
|
|
618
|
+
Nothing in it is AI-specific — the labels are four severity words and "difference" — and a
|
|
619
|
+
rules-derived contradiction (two stored figures disagreeing, a carrier moving an ETA) is exactly
|
|
620
|
+
as in scope as an extraction's. The author who reads "AI" as a fence hand-rolls a `Callout` for a
|
|
621
|
+
deterministic check and loses the ranking, the magnitude and the provenance. The test is the
|
|
622
|
+
SHAPE: two readings that disagree → `Finding`; a state with nothing to contradict it → `Callout`.
|
|
623
|
+
|
|
617
624
|
BOTH readings stay on screen and NEITHER is struck through or marked wrong: a finding reports
|
|
618
625
|
that two sources disagree, and which one is right is the reader's call. Omit `delta` where the
|
|
619
626
|
fields are not commensurable — two spellings of a name have no difference to compute. The
|