@lotics/ui 28.0.0 → 28.2.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/MIGRATION.md +34 -0
- package/docs/catalog.md +15 -6
- package/docs/composition.md +5 -2
- package/package.json +1 -1
- package/src/checklist.tsx +15 -1
- package/src/section_heading.tsx +28 -6
package/MIGRATION.md
CHANGED
|
@@ -4,6 +4,40 @@ 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.2.0 — `SubsectionHeadingTitle` takes a `description`
|
|
8
|
+
|
|
9
|
+
Additive; nothing to change. The heading ramp's three rungs are meant to carry the SAME slots
|
|
10
|
+
and differ only in type size — `description` was missing from the middle one, so a group that
|
|
11
|
+
needed a muted line under its title had to borrow the section rung above it or hand-roll a
|
|
12
|
+
`Text` off the ramp.
|
|
13
|
+
|
|
14
|
+
It matters most where a GROUP receives something. A `FileDropTarget`-wrapped region shows no
|
|
15
|
+
dropzone, so `AGENTS.md` requires the heading to name the drag and paste paths — and a surface
|
|
16
|
+
with several PEER file regions (per-kind photo buckets, each its own target, because nothing in
|
|
17
|
+
a dropped file says which bucket it belongs to) carries those regions at subsection rung:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
<SubsectionHeading>
|
|
21
|
+
<SubsectionHeadingTitle description="Kéo, dán hoặc bấm để thêm ảnh">Ảnh hạ</SubsectionHeadingTitle>
|
|
22
|
+
</SubsectionHeading>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The rung is unchanged (`###`, lg semibold, level 3) — only the slot is new.
|
|
26
|
+
|
|
27
|
+
## 28.1.0 — `ChecklistItem` can announce more than its title
|
|
28
|
+
|
|
29
|
+
Additive; nothing to change. `accessibilityLabel` overrides the row's accessible name, which
|
|
30
|
+
still defaults to `title`. It exists for a surface carrying one checklist PER person, party or
|
|
31
|
+
period, where the same row labels repeat and only the headings between them tell the copies
|
|
32
|
+
apart — a reader moving control to control does not get those headings. Put the distinguishing
|
|
33
|
+
noun in the accessible name, not in `title`, so the visible rows stay free of what the heading
|
|
34
|
+
above already says.
|
|
35
|
+
|
|
36
|
+
Also fixed here: **`TASK_TEXT_INSET` was cut in 28.0.0 without a replacement named.** It is
|
|
37
|
+
`CONTROL_TEXT_INSET` from `@lotics/ui/control_surface` — the same 9 (1px border + 8px padding),
|
|
38
|
+
and always about a CONTROL's text rather than a step's, which is why it did not follow the rest
|
|
39
|
+
of `task` into `checklist`.
|
|
40
|
+
|
|
7
41
|
## 28.0.0 — `task` and `pipeline` merge into `checklist`
|
|
8
42
|
|
|
9
43
|
Two families had converged on one anatomy: a ring, a title, a value beside it, a muted note, a
|
package/docs/catalog.md
CHANGED
|
@@ -399,7 +399,8 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
399
399
|
- **`spacing`** — the `SPACE` scale + `SpaceToken`.
|
|
400
400
|
- **`control_surface`** — `CONTROL_HEIGHT` (40), `CONTROL_RADIUS` (10), `CONTROL_TEXT_INSET`
|
|
401
401
|
(9 — how far a control insets its OWN text: 1px border + 8px padding; anything that must line
|
|
402
|
-
up with a control's WORDS rather than its box carries it
|
|
402
|
+
up with a control's WORDS rather than its box carries it — a caption under an inline editor,
|
|
403
|
+
a note under a figure — rather than a hand-measured 8),
|
|
403
404
|
`FOCUS_RING` (a 2px OUTSET ring, so a container that CLIPS — any `ScrollView` — has to
|
|
404
405
|
keep padding on an edge a focusable child sits against, or the ring shears off on the
|
|
405
406
|
one interaction it signals; the padding still comes off the 8-grid, the ring is only
|
|
@@ -450,13 +451,17 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
450
451
|
(16, fixed), no body component. `SectionHeadingTitle` is ALWAYS `##` (xl semibold;
|
|
451
452
|
`weight="medium"` opt-down only) + `info` for an ⓘ provenance popover after the title,
|
|
452
453
|
same as `CardHeaderTitle.info`. `SubsectionHeadingTitle` is the `###` lg-semibold level-3
|
|
453
|
-
title of a named group inside a section (same `info` ⓘ
|
|
454
|
-
heading-row siblings ride its right edge.
|
|
454
|
+
title of a named group inside a section (same `info` ⓘ AND `description` slots as the section
|
|
455
|
+
title) — heading-row siblings ride its right edge. Its `description` is what a files
|
|
456
|
+
SUBSECTION uses to name its drag/paste paths: a `FileDropTarget`-wrapped region shows no
|
|
457
|
+
dropzone, and a surface with several peer file regions (per-kind photo buckets, each its own
|
|
458
|
+
target) carries that line at THIS rung, not the section above it. **A section's ADD is one of those siblings** — a
|
|
455
459
|
`primary` `Button` beside the title, rendered whether the collection is empty or full, never
|
|
456
460
|
under the rows it extends and never repeated in the `EmptyState`
|
|
457
461
|
(composition.md § The add-placement law). `DialogSectionHeadingTitle` is the `####`
|
|
458
462
|
md-semibold rung with the SAME `icon`/`description`/`info` slots as the section title, so a
|
|
459
|
-
dialog surface loses only the type size, never an affordance.
|
|
463
|
+
dialog surface loses only the type size, never an affordance. **`description` is on every
|
|
464
|
+
rung** — the ramp's slots do not vary by level; only the type size does. The heading ramp is FIXED:
|
|
460
465
|
`#` xxl / `##` xl / `###` lg / `####` md, no size props.
|
|
461
466
|
- **`section_stack`** — `SectionStack`, `SubsectionStack` — stacks that own the
|
|
462
467
|
between-block law, skipping null children: `SectionStack` = a fixed 56px beat + a hairline
|
|
@@ -1295,8 +1300,12 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1295
1300
|
today, so a run filled in after the fact needs the correction in reach — and `ChecklistField`
|
|
1296
1301
|
for a value with NO other home (a portal login created at that step, unreachable otherwise).
|
|
1297
1302
|
`ChecklistItem.meta` is two words on the title's row; prose that grows is a `ChecklistNote`,
|
|
1298
|
-
which owns its line.
|
|
1299
|
-
|
|
1303
|
+
which owns its line. A row ANNOUNCES its `title`; `ChecklistItem.accessibilityLabel` overrides
|
|
1304
|
+
that for the one case the title cannot carry alone — a surface with one checklist PER person,
|
|
1305
|
+
party or period, where the same labels repeat and only the headings between them separate the
|
|
1306
|
+
copies, which a reader moving control to control never hears. The distinguishing noun goes in
|
|
1307
|
+
the accessible name, never the title, or every visible row repeats its own heading. Worked
|
|
1308
|
+
screens: `tpl_record` § Progress (connected, grouped) and its document desk (unconnected set).
|
|
1300
1309
|
- **`stepper`** — `Stepper` + `Step` — done/current/upcoming/warning/complete progress on a
|
|
1301
1310
|
track (horizontal) or spine (vertical); compound `<Step status>children` OR data
|
|
1302
1311
|
`steps[]`+`current`; **navigable** via `Step.onPress` (both orientations — the whole step
|
package/docs/composition.md
CHANGED
|
@@ -64,8 +64,11 @@ restyle a heading level per-page.
|
|
|
64
64
|
stays ABSOLUTE — this is one more fixed size, never a `size`/`compact` knob on a rung above.
|
|
65
65
|
- **Subsection title** — the level BELOW a section on a long record surface: `Subsection` ›
|
|
66
66
|
`SubsectionHeading` › `SubsectionHeadingTitle` (`###` — lg semibold, with the same `info` ⓘ
|
|
67
|
-
|
|
68
|
-
`SectionHeadingMeta`, an action — ride the heading row's right edge).
|
|
67
|
+
and `description` slots as `SectionHeadingTitle`; siblings — a `Badge`, a
|
|
68
|
+
`SectionHeadingMeta`, an action — ride the heading row's right edge). Reach for its
|
|
69
|
+
`description` when the GROUP is what receives something — a files subsection wrapped in its
|
|
70
|
+
own `FileDropTarget` has to name drag and paste itself, since a wrapped region shows no zone
|
|
71
|
+
and the section above it may hold several such groups. Sibling subsections stack
|
|
69
72
|
in a **`SubsectionStack`** (a fixed 32px beat; no margins, no hand-rolled dividers).
|
|
70
73
|
It is SPACE-ONLY while the groups are SHORT — the titles carry the grouping and hairlines
|
|
71
74
|
belong to the SECTION level, one rule per altitude — and takes `divided` once the groups run
|
package/package.json
CHANGED
package/src/checklist.tsx
CHANGED
|
@@ -190,6 +190,19 @@ export interface ChecklistItemProps extends StepPositional {
|
|
|
190
190
|
/** The row's name. Doubles as the ring's accessible name — the ring carries no
|
|
191
191
|
* visible label of its own, so the text rides beside it. */
|
|
192
192
|
title: string;
|
|
193
|
+
/**
|
|
194
|
+
* Override that accessible name. Defaults to `title`, which is right whenever
|
|
195
|
+
* the title identifies the row on its own.
|
|
196
|
+
*
|
|
197
|
+
* Reach for it when the SAME titles repeat down a surface and only their
|
|
198
|
+
* surroundings tell them apart — one checklist per person, per party, per
|
|
199
|
+
* period, each listing the same rows. A reader moving control to control gets
|
|
200
|
+
* the names without the headings between them, so three rows all announcing
|
|
201
|
+
* "Đơn đăng ký" are three controls they cannot tell apart. Put the
|
|
202
|
+
* distinguishing noun in here, NOT in `title`: the heading above already says
|
|
203
|
+
* it, and repeating it in every visible row is noise for everyone else.
|
|
204
|
+
*/
|
|
205
|
+
accessibilityLabel?: string;
|
|
193
206
|
/** Ticked. */
|
|
194
207
|
done?: boolean;
|
|
195
208
|
/** The row the reader is waiting on — medium weight, so a run full of ticks
|
|
@@ -222,6 +235,7 @@ export interface ChecklistItemProps extends StepPositional {
|
|
|
222
235
|
/** ONE ROW — the level that carries the ticks. */
|
|
223
236
|
export function ChecklistItem({
|
|
224
237
|
title,
|
|
238
|
+
accessibilityLabel,
|
|
225
239
|
done,
|
|
226
240
|
current,
|
|
227
241
|
onToggle,
|
|
@@ -235,7 +249,7 @@ export function ChecklistItem({
|
|
|
235
249
|
<Step
|
|
236
250
|
status={done ? "done" : current ? "current" : "upcoming"}
|
|
237
251
|
onToggle={onToggle}
|
|
238
|
-
accessibilityLabel={title}
|
|
252
|
+
accessibilityLabel={accessibilityLabel ?? title}
|
|
239
253
|
{...positional}
|
|
240
254
|
>
|
|
241
255
|
<View style={{ gap: 6 }}>
|
package/src/section_heading.tsx
CHANGED
|
@@ -87,6 +87,17 @@ export function SubsectionHeading(props: SubsectionHeadingProps) {
|
|
|
87
87
|
|
|
88
88
|
export interface SubsectionHeadingTitleProps {
|
|
89
89
|
children: React.ReactNode;
|
|
90
|
+
/**
|
|
91
|
+
* Muted line under the title, as on the rungs either side of this one.
|
|
92
|
+
*
|
|
93
|
+
* The ramp carries the same slots at every rung, and this was the one gap in
|
|
94
|
+
* it. It matters most for a group that RECEIVES something: a files region
|
|
95
|
+
* wrapped in a `FileDropTarget` shows no dropzone, so drag and paste are
|
|
96
|
+
* invisible unless the heading names them — and a surface with several peer
|
|
97
|
+
* file regions (per-kind photo buckets, each its own drop target) puts them at
|
|
98
|
+
* THIS rung, where the prescribed line previously had nowhere to sit.
|
|
99
|
+
*/
|
|
100
|
+
description?: string;
|
|
90
101
|
/** Heading rank. Defaults to 3 — one level under `SectionHeadingTitle`'s 2. */
|
|
91
102
|
level?: HeadingLevel;
|
|
92
103
|
/** An ⓘ popover after the title — a short "what this is / where it came from"
|
|
@@ -98,14 +109,25 @@ export interface SubsectionHeadingTitleProps {
|
|
|
98
109
|
* xl section title and above the md/sm body. Grows to push siblings (a
|
|
99
110
|
* `SectionHeadingMeta`, a `Badge`, an action) to the right edge. */
|
|
100
111
|
export function SubsectionHeadingTitle(props: SubsectionHeadingTitleProps) {
|
|
101
|
-
const { children, level = 3, info } = props;
|
|
112
|
+
const { children, description, level = 3, info } = props;
|
|
102
113
|
const words = useLoticsLocale();
|
|
114
|
+
// Same anatomy as `SectionHeadingTitle` one rung down: the title row keeps its
|
|
115
|
+
// own `flexDirection: "row"` so `info` sits beside the text, and the column
|
|
116
|
+
// wrapper carries the `flex: 1` that lets a heading row push meta to its right
|
|
117
|
+
// edge. Without the wrapper the description would land on the title's LINE.
|
|
103
118
|
return (
|
|
104
|
-
<View style={{ flex: 1,
|
|
105
|
-
<
|
|
106
|
-
{
|
|
107
|
-
|
|
108
|
-
|
|
119
|
+
<View style={{ flex: 1, gap: 2 }}>
|
|
120
|
+
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
|
|
121
|
+
<Text level={level} size="lg" weight="semibold">
|
|
122
|
+
{children}
|
|
123
|
+
</Text>
|
|
124
|
+
{info ? <InfoPopover text={info} accessibilityLabel={words.sectionHeading.info} /> : null}
|
|
125
|
+
</View>
|
|
126
|
+
{description ? (
|
|
127
|
+
<Text color="zinc-500" size="sm">
|
|
128
|
+
{description}
|
|
129
|
+
</Text>
|
|
130
|
+
) : null}
|
|
109
131
|
</View>
|
|
110
132
|
);
|
|
111
133
|
}
|