@lotics/ui 47.15.0 → 47.16.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/catalog.md +4 -1
- package/docs/composition.md +17 -7
- package/docs/reviewing.md +23 -0
- package/package.json +1 -1
- package/src/empty_state.tsx +25 -3
package/docs/catalog.md
CHANGED
|
@@ -1147,7 +1147,10 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1147
1147
|
nothing — `message` + `hint` + an optional `icon` anchor, and **no verb at all**. It cannot hold
|
|
1148
1148
|
the section's add (that lives on the heading row, where it does not move — § The add-placement
|
|
1149
1149
|
law in composition.md), a no-results empty is HINT-only since the filters that emptied it carry
|
|
1150
|
-
their own clear, and a FAILED read is `ErrorState`, not this. **`
|
|
1150
|
+
their own clear, and a FAILED read is `ErrorState`, not this. **`link` ({ label, onPress }) is a
|
|
1151
|
+
DESTINATION, not that verb** — reach for it only where what fills the region is made somewhere
|
|
1152
|
+
else, so the hint has an address to end at; it does not move when the first row lands and it
|
|
1153
|
+
asserts nothing about the read. **`compact`** for one BAND of a
|
|
1151
1154
|
record — left-aligned, glyph-less, 56px against the default's 178; the centred default speaks
|
|
1152
1155
|
for a whole region. → composition.md § Empty states.
|
|
1153
1156
|
- **`error_state`** — `ErrorState`: the region-scale FAILED read — `message` + optional `detail`
|
package/docs/composition.md
CHANGED
|
@@ -367,7 +367,7 @@ the add returns to the right edge where the law puts it, and drag/paste keep wor
|
|
|
367
367
|
with row count is the fault, not the cure.
|
|
368
368
|
- **It renders unconditionally**, empty or not. A heading whose CTA appears only once there is
|
|
369
369
|
data cannot be used to create the first row.
|
|
370
|
-
- **The `EmptyState` then
|
|
370
|
+
- **The `EmptyState` then carries no add of its own** — see § Empty states.
|
|
371
371
|
- **Only the ADD.** A verb that acts on a SELECTION (delete, export, run) belongs to the
|
|
372
372
|
selection — `FloatingActionBar` — and a verb about ONE row stays on the row.
|
|
373
373
|
|
|
@@ -1457,8 +1457,8 @@ gate's SCOPE, once** — never prose beside the button, never revealed only on p
|
|
|
1457
1457
|
|
|
1458
1458
|
The ADD is the one verb this law does NOT place next to its effect, and the add-placement law
|
|
1459
1459
|
says why. The heading row therefore carries identity + meta + view controls + the section's ADD,
|
|
1460
|
-
and no other content verb. **An add is `primary` wherever it renders** —
|
|
1461
|
-
|
|
1460
|
+
and no other content verb. **An add is `primary` wherever it renders** — and the heading row is
|
|
1461
|
+
where it renders, since `EmptyState` holds no verb (§ Empty states). It
|
|
1462
1462
|
is the act its section offers, so it carries that section's weight; a lone `secondary` button
|
|
1463
1463
|
reads as though the real action were somewhere else. The rule that matters is that ONE VERB
|
|
1464
1464
|
KEEPS ONE WEIGHT — the same add must not be primary on an empty list and secondary on a full one.
|
|
@@ -2601,11 +2601,21 @@ what's empty, `hint` = what to do about it).
|
|
|
2601
2601
|
duplicating it here would put two buttons for one act in view and make the add jump the moment
|
|
2602
2602
|
the first row lands. A read that FAILED is not an empty one — it does not know whether there is
|
|
2603
2603
|
anything — so it gets `ErrorState` (`message` + `detail` + `onRetry`), never an empty state
|
|
2604
|
-
wearing an alert glyph.
|
|
2604
|
+
wearing an alert glyph.
|
|
2605
2605
|
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2606
|
+
**A DESTINATION is not that verb, and `link` is where it goes.** Where what fills the region is
|
|
2607
|
+
made somewhere else entirely — another surface, a terminal, a page the reader has to open — the
|
|
2608
|
+
hint needs an address to end at, and neither of the two refusals above applies to one: a
|
|
2609
|
+
destination was never this section's add, so it cannot jump when the first row lands, and it
|
|
2610
|
+
asserts nothing about the read, so it cannot dress a failure as an empty. It sits under the hint,
|
|
2611
|
+
as `Link` (underlined, blue, `role="link"`), and stays the last line: the region still says what
|
|
2612
|
+
is empty first. Anything the reader could press to fill the region HERE is the add, and belongs
|
|
2613
|
+
on the heading row.
|
|
2614
|
+
|
|
2615
|
+
The three empties get DIFFERENT copy:
|
|
2616
|
+
|
|
2617
|
+
- **First use** → teach + invite: message names what will live here, and the heading's CTA
|
|
2618
|
+
creates the first one ("Chưa có khoản phí" + "Thêm khoản thu/chi cho lô").
|
|
2609
2619
|
- **User cleared it** → stay quiet: the user knows why it's empty; confirmation only, no tutorial.
|
|
2610
2620
|
- **No search/filter results** → help recover: restate the scope ("Không có lô nào khớp
|
|
2611
2621
|
'ABC'"), hint the fix ("Thử từ khóa khác / xóa bộ lọc"). Never a blank panel or bare "No data".
|
package/docs/reviewing.md
CHANGED
|
@@ -396,6 +396,29 @@ A resting register is the cheapest thing to screenshot and the least likely to h
|
|
|
396
396
|
carries the tags ITS writer chose, so a heading inside a value announces as a peer of the page's
|
|
397
397
|
sections; sizing it down fixes what the screen SHOWS and nothing about what it ANNOUNCES.
|
|
398
398
|
|
|
399
|
+
### 7a. A chart's LINKING marks, against the marks they link
|
|
400
|
+
|
|
401
|
+
**Collect**, for any chart whose meaning lives in the relationship between marks rather than in
|
|
402
|
+
each mark alone — a bridge, a slope, a connected dot plot — the size of the CONNECTOR and the size
|
|
403
|
+
of the thing it connects, in the same axis.
|
|
404
|
+
|
|
405
|
+
- **A connector sized by the GAP between bars disappears as the bars get wider.** In a vertical
|
|
406
|
+
bridge the connector spans column-to-column, so a card wide enough for fat columns leaves a
|
|
407
|
+
linking mark a few pixels long: measured on one, 108px bars with an 8px gap drew 8×1px
|
|
408
|
+
connectors in the lightest grey. Every bar is placed correctly, the arithmetic is exact, and the
|
|
409
|
+
chart reads as unlinked blocks floating at unrelated heights — because the only thing saying
|
|
410
|
+
they are one running total is 7% the width of what it links, at the palette's faintest ink.
|
|
411
|
+
- **The signature is a chart that measures perfectly and cannot be read.** Bar heights
|
|
412
|
+
proportional to a common scale, a baseline present, and a reader who still asks what the
|
|
413
|
+
picture means. So this probe is worth running whenever a chart is reported as confusing and the
|
|
414
|
+
value encoding checks out.
|
|
415
|
+
- **Compare orientations before blaming the data.** The same component's other orientation may
|
|
416
|
+
give the connector the full row gap to run in — one measured 1×24px where the other gave 8×1px
|
|
417
|
+
— which is both the diagnosis and, often, the fix: give the chart the shape whose connectors
|
|
418
|
+
have room, rather than the shape that fills the wider slot.
|
|
419
|
+
|
|
420
|
+
→ [composition.md](./composition.md) §"Charts".
|
|
421
|
+
|
|
399
422
|
### 8. Data probe — count what is really there
|
|
400
423
|
- **Query the table before choosing a surface.** "Show thumbnails" is wrong for a corpus of nine
|
|
401
424
|
files and zero images. Images are identified by CONTENT (a grid), documents by NAME (a list) —
|
package/package.json
CHANGED
package/src/empty_state.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { View, StyleSheet } from "react-native";
|
|
2
2
|
import { Text } from "./text";
|
|
3
3
|
import { Icon, type IconName } from "./icon";
|
|
4
|
+
import { Link } from "./link";
|
|
4
5
|
import { colors } from "./colors";
|
|
5
6
|
|
|
6
7
|
interface EmptyStateBase {
|
|
@@ -8,6 +9,16 @@ interface EmptyStateBase {
|
|
|
8
9
|
message: string;
|
|
9
10
|
/** What the user can do about it ("Thử từ khóa khác"). */
|
|
10
11
|
hint?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Where to go — an address, under the hint. NOT the `action` this refuses
|
|
14
|
+
* below: a destination is a different thing from a verb. It does not move
|
|
15
|
+
* when the first row lands (it was never this section's add), and it asserts
|
|
16
|
+
* nothing about the read (it is not a retry).
|
|
17
|
+
*
|
|
18
|
+
* Reach for it only where what fills the region lives SOMEWHERE ELSE, so the
|
|
19
|
+
* hint has an address to end at.
|
|
20
|
+
*/
|
|
21
|
+
link?: { label: string; onPress: () => void };
|
|
11
22
|
}
|
|
12
23
|
|
|
13
24
|
/** The whole region: centred, generous, with an optional glyph anchoring it. */
|
|
@@ -74,9 +85,10 @@ type EmptyStateProps = EmptyRegionProps | EmptyBandProps;
|
|
|
74
85
|
* is that nothing is known — use `ErrorState`. Retrying a true empty just
|
|
75
86
|
* returns the same nothing.
|
|
76
87
|
*
|
|
77
|
-
* What is left says one thing and
|
|
78
|
-
*
|
|
79
|
-
* filters that emptied it
|
|
88
|
+
* What is left says one thing and points, at most, somewhere else: this region
|
|
89
|
+
* is empty, here is what would live in it, and — `link` — the address where it
|
|
90
|
+
* gets made. A no-results empty is hint-only too — the filters that emptied it
|
|
91
|
+
* carry their own clear.
|
|
80
92
|
*/
|
|
81
93
|
export function EmptyState(props: EmptyStateProps) {
|
|
82
94
|
if (props.compact) {
|
|
@@ -87,6 +99,11 @@ export function EmptyState(props: EmptyStateProps) {
|
|
|
87
99
|
<View style={styles.compactContainer}>
|
|
88
100
|
<Text size="sm" color="muted" leading="tight">{props.message}</Text>
|
|
89
101
|
{props.hint ? <Text size="xs" color="muted" leading="tight">{props.hint}</Text> : null}
|
|
102
|
+
{props.link ? (
|
|
103
|
+
<Link size="xs" onPress={props.link.onPress}>
|
|
104
|
+
{props.link.label}
|
|
105
|
+
</Link>
|
|
106
|
+
) : null}
|
|
90
107
|
</View>
|
|
91
108
|
);
|
|
92
109
|
}
|
|
@@ -105,6 +122,11 @@ export function EmptyState(props: EmptyStateProps) {
|
|
|
105
122
|
{props.hint}
|
|
106
123
|
</Text>
|
|
107
124
|
) : null}
|
|
125
|
+
{props.link ? (
|
|
126
|
+
<Link size="xs" onPress={props.link.onPress}>
|
|
127
|
+
{props.link.label}
|
|
128
|
+
</Link>
|
|
129
|
+
) : null}
|
|
108
130
|
</View>
|
|
109
131
|
);
|
|
110
132
|
}
|