@lotics/ui 38.1.0 → 39.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/MIGRATION.md +25 -0
- package/docs/catalog.md +8 -6
- package/package.json +1 -1
- package/src/page_header.tsx +20 -14
package/MIGRATION.md
CHANGED
|
@@ -4,6 +4,31 @@ 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
|
+
## 39.0.0 — `PageHeader.leading` is `trailing`, and it renders AFTER the title
|
|
8
|
+
|
|
9
|
+
38.0.0 shipped `leading`, a slot before the title. It is now **`trailing`**, in the same
|
|
10
|
+
place in the props but rendered on the other side of the title text.
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
// 38.0.0
|
|
14
|
+
<PageHeader title="Members" leading={<IconButton …/>} actions={…} />
|
|
15
|
+
// 39.0.0
|
|
16
|
+
<PageHeader title="Members" trailing={<IconButton …/>} actions={…} />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Why the side changed.** The title is the page's first word. A control ahead of it makes
|
|
20
|
+
the eye parse chrome before it learns where it is, and on a page whose heading is the only
|
|
21
|
+
thing telling you which section you are in, that is the wrong order. After the title the
|
|
22
|
+
control still reads as part of the heading — which is the whole point of not putting it
|
|
23
|
+
with `actions` — without standing in front of it.
|
|
24
|
+
|
|
25
|
+
**Why a rename rather than a second slot.** A slot with no consumer is surface that has to
|
|
26
|
+
be understood by everyone who reads the component and used by no one; the kit's cull rule
|
|
27
|
+
says cut it. One slot for "a control belonging to the title" is the whole contract.
|
|
28
|
+
|
|
29
|
+
The layout law is unchanged and now covers both: the TITLE gives way and wraps, while
|
|
30
|
+
`trailing` and `actions` keep their width.
|
|
31
|
+
|
|
7
32
|
## 38.0.0 — the `lg` avatar is a control (40), not a size (48)
|
|
8
33
|
|
|
9
34
|
`AVATAR_PX.lg` was 48 and `AVATAR_TEXT.lg` was `lg` type. They are now **40** and `md`
|
package/docs/catalog.md
CHANGED
|
@@ -536,13 +536,15 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
536
536
|
- **`container`** — `Container`: centers content at a max width (`ContainerSize` sm|md|lg,
|
|
537
537
|
`CONTAINER_SIZES`).
|
|
538
538
|
- **`page_header`** — `PageHeader`: the page's title band. `actions` puts page-level CTAs on
|
|
539
|
-
the title row (right-aligned) and `
|
|
540
|
-
`left`/`right` form a separate nav row above. Split `
|
|
539
|
+
the title row (right-aligned) and `trailing` puts a control immediately AFTER the title;
|
|
540
|
+
`left`/`right` form a separate nav row above. Split `trailing` from `actions` by what the
|
|
541
541
|
control acts on: `actions` do something to the page's CONTENT (create, sort, export),
|
|
542
|
-
`
|
|
543
|
-
filed under `actions` reads as a peer of "create one of these".
|
|
544
|
-
|
|
545
|
-
|
|
542
|
+
`trailing` changes what is AROUND it (a side-panel toggle, a view switch). A panel toggle
|
|
543
|
+
filed under `actions` reads as a peer of "create one of these". It sits AFTER the title
|
|
544
|
+
because the title is the page's first word and nothing should come between the reader
|
|
545
|
+
and it. Under a title too long for the row the TITLE gives way and wraps while `trailing`
|
|
546
|
+
and `actions` keep their width — a wrapped title is merely taller, a control squeezed
|
|
547
|
+
below its own icon is broken.
|
|
546
548
|
- **`page_content`** — `PageContent` + `PAGE_SIZES`: the page's padded, width-capped content
|
|
547
549
|
region — a centred column with optional `title`/`titleRight`/`description`, `header`/`footer`
|
|
548
550
|
slots and `fullscreen`. **Reach for it before hand-rolling a screen shell**: a scroller, a
|
package/package.json
CHANGED
package/src/page_header.tsx
CHANGED
|
@@ -10,32 +10,36 @@ interface PageHeaderProps {
|
|
|
10
10
|
/** The nav row ABOVE the title, right-aligned. */
|
|
11
11
|
right?: ReactNode;
|
|
12
12
|
/**
|
|
13
|
-
* A control that belongs to the TITLE, rendered immediately
|
|
14
|
-
* title row — a panel toggle, a
|
|
13
|
+
* A control that belongs to the TITLE, rendered immediately AFTER it on the
|
|
14
|
+
* title row — a panel toggle, a view switch, anything that reframes the page
|
|
15
|
+
* rather than acting on it.
|
|
15
16
|
*
|
|
16
17
|
* The distinction from `actions` is what the control acts ON, not where it
|
|
17
18
|
* looks best. `actions` are things you do to the page's CONTENT (create, sort,
|
|
18
|
-
* export) and collect at the right, where a scanning eye reaches them
|
|
19
|
-
* `
|
|
20
|
-
* it
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* export) and collect at the far right, where a scanning eye reaches them
|
|
20
|
+
* last; `trailing` changes what is AROUND the content and stays with the title
|
|
21
|
+
* it qualifies, so it is read as part of the heading rather than as one more
|
|
22
|
+
* thing you can do to your list.
|
|
23
|
+
*
|
|
24
|
+
* It sits AFTER the title, not before, because the title is the page's first
|
|
25
|
+
* word and nothing should come between the reader and it — a control ahead of
|
|
26
|
+
* the heading makes the eye parse chrome before it learns where it is.
|
|
23
27
|
*/
|
|
24
|
-
|
|
28
|
+
trailing?: ReactNode;
|
|
25
29
|
/** Page-level actions (CTAs), rendered on the title row, right-aligned —
|
|
26
30
|
* distinct from `left`/`right`, which form a separate nav row above. */
|
|
27
31
|
actions?: ReactNode;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
export function PageHeader(props: PageHeaderProps) {
|
|
31
|
-
const { title, description, left, right,
|
|
35
|
+
const { title, description, left, right, trailing, actions } = props;
|
|
32
36
|
|
|
33
37
|
const hasNav = !!left || !!right;
|
|
34
38
|
|
|
35
|
-
// ONE shape, whichever slots are filled. Branching the row on
|
|
36
|
-
// the title two different behaviours under a long string — shrinking
|
|
37
|
-
// panel toggle happened to be present and overflowing when it was not —
|
|
38
|
-
// is a layout law decided by an unrelated prop.
|
|
39
|
+
// ONE shape, whichever slots are filled. Branching the row on the title's own
|
|
40
|
+
// slot gave the title two different behaviours under a long string — shrinking
|
|
41
|
+
// when a panel toggle happened to be present and overflowing when it was not —
|
|
42
|
+
// which is a layout law decided by an unrelated prop.
|
|
39
43
|
//
|
|
40
44
|
// The title is what gives way; `actions` keep their width, because a CTA
|
|
41
45
|
// pushed off the row is unreachable while a wrapped title is merely taller.
|
|
@@ -62,10 +66,12 @@ export function PageHeader(props: PageHeaderProps) {
|
|
|
62
66
|
minWidth: 0,
|
|
63
67
|
}}
|
|
64
68
|
>
|
|
65
|
-
{leading}
|
|
66
69
|
<Text size="xxl" weight="semibold" style={{ flexShrink: 1, minWidth: 0 }}>
|
|
67
70
|
{title}
|
|
68
71
|
</Text>
|
|
72
|
+
{/* Never shrinks: the title is what gives way, and a control squeezed
|
|
73
|
+
below its own icon is not a smaller control, it is a broken one. */}
|
|
74
|
+
{trailing !== undefined && <View style={{ flexShrink: 0 }}>{trailing}</View>}
|
|
69
75
|
</View>
|
|
70
76
|
{actions}
|
|
71
77
|
</View>
|