@lotics/ui 45.10.0 → 46.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/docs/reviewing.md CHANGED
@@ -2,11 +2,8 @@
2
2
 
3
3
  The other docs say what good looks like. This one says how to find out whether you achieved it.
4
4
 
5
- That gap is the reason this file exists. An agent cannot see the screen it just wrote any better
6
- than it can see a bug it just introduced — "it looks fine" is the same claim as "it should work",
7
- made with the same evidence. Every rule in [composition.md](./composition.md) was written the last
8
- time it was broken, by someone who had read it. So the discipline is not *know the rules*, it is
9
- **render it, measure it, and let the numbers say whether the rules held**.
5
+ The discipline is not *know the rules*, it is **render it, measure it, and let the numbers say
6
+ whether the rules held**.
10
7
 
11
8
  Everything here is about a screen **that already renders**. Building one starts at
12
9
  [catalog.md](./catalog.md) (which component) and [templates.md](./templates.md) (which shape).
@@ -15,15 +12,13 @@ Everything here is about a screen **that already renders**. Building one starts
15
12
 
16
13
  ## The method
17
14
 
18
- **"Looks off" is where a finding starts.** Trust the impression it is the same reaction the
19
- reader will have — and use measurement to say precisely WHAT is off, so the fix can be aimed and
20
- re-checked. Numbers are how a finding is confirmed and communicated, never what makes it real.
15
+ **"Looks off" is where a finding starts.** Trust the impression and use measurement to say
16
+ precisely WHAT is off, so the fix can be aimed and re-checked. Numbers are how a finding is
17
+ confirmed and communicated, never what makes it real.
21
18
 
22
- The failure this doc has caused more than once: a screen passes every probe, the auditor reports
23
- that it measures fine, and the person who called it ugly is still right. Defect-removal converges
24
- on *inoffensive*. When the probes come back clean and the screen is still wrong, the probes are
25
- not the answer — the form, the density, or the fact that nothing on screen belongs to this product
26
- is. Go and look at it.
19
+ When the probes come back clean and the screen is still wrong, the probes are not the answer —
20
+ the form, the density, or the fact that nothing on screen belongs to this product is. Go and look
21
+ at it.
27
22
 
28
23
  1. **Render it** — `lotics app dev` for an app, a preview route for a screen. Drive it with
29
24
  browser automation that can evaluate JS in the page.
@@ -66,18 +61,15 @@ moving through ordered places is a rail. Work assigned to finite resources over
66
61
  A sequence of events is a timeline. A population whose point is its deviant minority is a queue
67
62
  sorted by deviation. A quantity across two dimensions is a matrix.
68
63
 
69
- This gate exists because **every probe below reads a screen that is already a register of fields**
70
- and measures its TREATMENT. So a screen that should have been a board or a rail passes the type
71
- inventory, the ground tally, the gaps, the rules and the alignment all of them — and still reads
72
- as templated. No amount of treatment fixes it, and nothing else here can see it.
64
+ **Every probe below reads a screen that is already a register of fields** and measures its
65
+ TREATMENT. A screen that should have been a board or a rail passes all of them and still reads as
66
+ templated. No amount of treatment fixes it, and nothing else here can see it.
73
67
 
74
68
  *The tell that it was skipped:* every screen in the product is a register with a summary line over
75
- it. That is what reuse-first produces when nothing asks the question the catalog's most reachable
76
- parts are `Table`, `DetailRow`, `SummaryLine` and `Badge`, so a subject whose natural shape is not
77
- a table gets flattened into one and no probe fires. **Reuse-first is about not duplicating
78
- PRIMITIVES, not about the shape of a screen**: a one-off composition needs no new component, so
79
- "the catalog has no journey rail" is an argument for composing one out of `Stepper`, not for
80
- rendering a status column and moving on.
69
+ it. That is what reuse-first produces when nothing asks the question. **Reuse-first is about not
70
+ duplicating PRIMITIVES, not about the shape of a screen**: a one-off composition needs no new
71
+ component, so "the catalog has no journey rail" is an argument for composing one out of `Stepper`,
72
+ not for rendering a status column and moving on.
81
73
 
82
74
  *And check the form against what the data can FILL.* A rail with no stamped stops, a calendar with
83
75
  no durations, a map with no coordinates — each renders an empty device that measures perfectly.
@@ -131,13 +123,12 @@ rule behind it lives in the area doc named beside it; this file never restates o
131
123
  join an existing class. Pick the sibling set by STRUCTURAL ROLE, not visual resemblance.
132
124
  - **Count DISTINCT rungs on the surface, then name the role each one carries.** More rungs than
133
125
  roles means a role has been split across two sizes, and that is the defect a reader calls
134
- "inconsistent" without being able to point at which element is wrong because none of them is:
135
- each was chosen defensibly, one at a time. This is the probe to re-run after EVERY fix, and the
136
- reason is procedural rather than visual: a treatment fix aimed at the element someone pointed at
137
- leaves its neighbours unaligned, so the next look finds a new mismatch and the surface never
138
- converges. Fixing the SET is a different act from fixing an element, and only this count tells
139
- the two apart. A small panel wants two or three rungs; if the tally exceeds the number of things
140
- the surface has to SAY, the excess is the finding.
126
+ "inconsistent" without being able to point at which element is wrong. This is the probe to
127
+ re-run after EVERY fix: a treatment fix aimed at the element someone pointed at leaves its
128
+ neighbours unaligned, so the next look finds a new mismatch and the surface never converges.
129
+ Fixing the SET is a different act from fixing an element, and only this count tells the two
130
+ apart. A small panel wants two or three rungs; if the tally exceeds the number of things the
131
+ surface has to SAY, the excess is the finding.
141
132
  - **Pairs.** For every primary+supporting pair, divide. A spread in the RATIOS is the finding, not
142
133
  a spread in the sizes. **A ratio of 1.00 is the loudest version** — a subject and its supporting
143
134
  line on one rung are distinguishable only by ink, and if they also share a weight, only by ink.
@@ -260,9 +251,8 @@ spacing distinguishes them.
260
251
  - **A VARIABLE-width leading slot destroys the column behind it.** A row's lead is sized for an
261
252
  icon; put a chip, a badge or a name in it and every row's title starts at a different x. Collect
262
253
  one repeated cell's `left` down the rows — more than one distinct value and the column does not
263
- exist, however aligned each row looks on its own. The spread is small enough to read as
264
- sloppiness rather than as a defect, which is why it survives review; the fix is a fixed-width
265
- lead, or a register, where columns make it impossible.
254
+ exist, however aligned each row looks on its own. The fix is a fixed-width lead, or a register,
255
+ where columns make it impossible.
266
256
  - **Every numeric column: is its unit named anywhere, and is it ONE unit?** Collect the leaf values
267
257
  sharing a right edge, with their size and weight. Identical treatment across values that are not
268
258
  the same KIND of thing — a count beside a currency — is the signature, and the labels beside them
@@ -299,11 +289,11 @@ A resting register is the cheapest thing to screenshot and the least likely to h
299
289
  a coloured chip in a register and as bare grey text in its own EDITOR.
300
290
  - **TAB through it, then diff what a keyboard reaches against what LOOKS pressable.** A pointer
301
291
  finds anything with an `onPress`; a keyboard finds only what carries a role and a tab stop, and
302
- the two lists come apart silently — the screen looks identical either way, and the author
303
- testing with a mouse never learns. The reliable producer is styled text: underline, a hover
304
- wash, a "verb" colour applied to a plain container, which reads as a control to the eye while
305
- announcing as prose. Anything the eye calls a control and the tab order omits is unreachable,
306
- not merely awkward. Count both lists; a difference is the finding.
292
+ the two lists come apart silently — the screen looks identical either way. The reliable producer
293
+ is styled text: underline, a hover wash, a "verb" colour applied to a plain container, which
294
+ reads as a control to the eye while announcing as prose. Anything the eye calls a control and
295
+ the tab order omits is unreachable, not merely awkward. Count both lists; a difference is the
296
+ finding.
307
297
  - **Diff a promoted field against where it came from.** Promoting means MOVING; a copy left behind
308
298
  gives one field two editors.
309
299
  - **Read every string in its SETTLED state**, not the streaming one.
@@ -333,7 +323,7 @@ A resting register is the cheapest thing to screenshot and the least likely to h
333
323
  it. Pull the field list from the write path (a workflow's `set`, a mutation's payload), not
334
324
  from the screen, then confirm each one against the record's own DetailRow/Text tree; where one
335
325
  is missing, query the record directly to prove the value is really sitting there unseen before
336
- calling it a fix. A screenshot cannot catch this — it only shows what already renders.
326
+ calling it a fix. A screenshot cannot catch this.
337
327
  - **A fixture can fail in the generous direction too**: an image tile pointed at a dead URL renders
338
328
  nothing, so the chip designed to survive a photo was never tested against one.
339
329
  - **Grep rendered text for internal identifiers — first probe, every audit** —
@@ -476,10 +466,7 @@ that has none, or a clean tally on a screen with an untracked component still on
476
466
 
477
467
  **A rule is a painted LINE, and it is drawn two ways.** Selecting "thin and wide" alone gets both
478
468
  halves wrong, and both wrongs are silent: a transparent zero-height flex spacer matches it and is
479
- counted, while a border on a box of ordinary height does not and is missed. The second is the one
480
- that bites — a component that draws its column band as a `borderBottom` on a full-height header row
481
- then reports **zero rules on a surface that visibly has one**, and a count of `0` reads as a clean
482
- result rather than a blind probe.
469
+ counted, while a border on a box of ordinary height does not and is missed.
483
470
 
484
471
  ```js
485
472
  () => {
@@ -519,14 +506,13 @@ result rather than a blind probe.
519
506
  }
520
507
  ```
521
508
 
522
- Read `separates` first — probe 3 asks what each rule DIVIDES, and a rule whose two neighbours are
523
- the same kind of thing is the one to delete however important the break feels.
509
+ Read `separates` first — probe 3 asks what each rule DIVIDES.
524
510
 
525
511
  Unequal `above`/`below` on one rule, or a rule with a visibly tighter beat than its neighbours, is
526
- the other finding. A hand-rolled `Divider` sitting in a parent's uniform `gap` next to a
527
- `SectionStack` is the usual cause. Asymmetry is not automatically wrong: a rule that BELONGS to
528
- the element above it sits tight under it and loose before the next, and that gap is what says
529
- which side owns it — the finding is asymmetry nobody chose.
512
+ the other finding. A hand-rolled `Divider` in a parent's uniform `gap` is the usual cause.
513
+ Asymmetry is not automatically wrong: a rule that BELONGS to the element above it sits tight under
514
+ it and loose before the next, and that gap is what says which side owns it — the finding is
515
+ asymmetry nobody chose.
530
516
 
531
517
  ### Clipping, overflow, collision
532
518
 
@@ -637,8 +623,7 @@ has three gotchas of its own: [testing.md](./testing.md).
637
623
 
638
624
  Most of what makes a screen good, which is why the probes are a floor and not a target. They will
639
625
  not tell you the density is wrong for the job, that the register has no point of view, or that
640
- nothing on the page belongs to this product rather than to any product. Those are judgements, and
641
- they are the ones that decide whether the work reads as considered.
626
+ nothing on the page belongs to this product rather than to any product. Those are judgements.
642
627
 
643
628
  Nor will they show a disclosure you did not expand, copy that only lies in its terminal state (a
644
629
  settled row still saying "Loading…" measures perfectly), or a flattering fixture — compare the
@@ -662,7 +647,6 @@ preview data's SHAPE against what the real source emits before trusting any of i
662
647
  `docs/<area>.md`, the `AGENTS.md` index line, and a version bump — docs reach apps only on
663
648
  publish.
664
649
  - **Never resolve a finding with "the docs say X."** Resolve it with what makes the screen better,
665
- then push the answer back into the docs. A written rule cannot report that it produces a bad
666
- screen, so a person has to. Where the docs ARE load-bearing is IDENTITY: the fonts, the type
667
- ramp, the `Icon` set, one accent per screen — inventing a palette or a typeface is the defect,
668
- not the craft.
650
+ then push the answer back into the docs. Where the docs ARE load-bearing is IDENTITY: the
651
+ fonts, the type ramp, the `Icon` set, one accent per screen inventing a palette or a typeface
652
+ is the defect, not the craft.