@usableapp/cardds 0.7.56 → 0.7.58
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/CHANGELOG.md +13 -0
- package/README.md +6 -2
- package/css/sheet.css +7 -4
- package/css/stack.css +39 -1
- package/dist/cardds.css +46 -5
- package/dist/cards/Card.d.ts +3 -1
- package/dist/cards/Card.js +2 -2
- package/dist/sheets/Sheet.d.ts +1 -1
- package/dist/sheets/StackSheet.d.ts +4 -2
- package/dist/sheets/StackSheet.js +2 -2
- package/dist/templates/Home.d.ts +3 -1
- package/dist/templates/Home.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
> For: a project that consumes `@usableapp/cardds` and its AI — what changed between versions, written as before → after, so a screen can be brought up to date without reading the source. Newest first. A consumer never edits cardds; if something here leaves you without a way to do what you did before, report the gap.
|
|
4
4
|
|
|
5
|
+
## 0.7.58 — 2026-10-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- **A closed paper sheet in a stack shows the card's colour where the next sheet's round top does not cover it.** The white body used to show in those corners. While the sheet is closed that body is clear. On the way back into the stack the card colour fades in over `--motion-quick`, and the fade ends as the sheet stops. Open, the body is white at once. The first row still sits `--sp-6` down. Nothing to change in a screen.
|
|
9
|
+
|
|
10
|
+
## 0.7.57 — 2026-10-06
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **`paper` on a sheet in a stack.** The same prop as the single sheet, on `StackSheet`, on a `Card` in a `SheetStack`, and on each sheet of `Home`. The head keeps `tone`. The body and the foot are white. The gap under the head stays the sheet's colour. The first row sits `--sp-6` (24px at the default spacing) down into the white. A pull to refresh adds its own room on top of that inset. Pass `paper` on the sheets that should look this way. A sheet without it is unchanged.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- **A dark `paper` head no longer paints its light ink onto the white body.** The words on the white use the page's ink (`--color-ink`, or the wireframe dark when that is unset). A theme that already sets `--color-ink` is unchanged.
|
|
17
|
+
|
|
5
18
|
## 0.7.56 — 2026-10-06
|
|
6
19
|
|
|
7
20
|
### Changed
|
package/README.md
CHANGED
|
@@ -275,8 +275,12 @@ whose markup has rules, because the sheet's box is the step itself:
|
|
|
275
275
|
pinned; the body is the one thing that scrolls, to the card's own edges. The
|
|
276
276
|
handle is a line, or four dots (`mark="dots"`): both sit in the card's top
|
|
277
277
|
padding, the same distance from the edge, so the title stays put. `paper` makes
|
|
278
|
-
the content white while the head keeps the sheet's colour (`tone`, as a card).
|
|
279
|
-
|
|
278
|
+
the content white while the head keeps the sheet's colour (`tone`, as a card).
|
|
279
|
+
The same prop on a `StackSheet`, or on a `Card` in a stack: the head keeps the
|
|
280
|
+
tone, the body and the foot are white, and the gap under the head stays the tone.
|
|
281
|
+
While that sheet is closed, the corners the next sheet does not cover show the
|
|
282
|
+
card's colour. That colour fades in as the sheet returns, and is done when it stops.
|
|
283
|
+
A sheet with no head (the dim page sheet) is a body alone.
|
|
280
284
|
- **The step follows its top bar directly, and touches it.** `full` means
|
|
281
285
|
the sheet's top edge at the bar's bottom edge — nothing above it but the
|
|
282
286
|
bar. So the room the screen would have left between the bar and the step
|
package/css/sheet.css
CHANGED
|
@@ -203,16 +203,19 @@
|
|
|
203
203
|
The flex gap under the head is outside the body, so it stays the sheet's tint.
|
|
204
204
|
The first field would sit on that colour seam. The white inset is --sp-6 (24px at
|
|
205
205
|
the default spacing), the body's own top padding, and only when the sheet is paper.
|
|
206
|
-
A plain sheet keeps padding-top 0.
|
|
206
|
+
A plain sheet keeps padding-top 0. A sheet in a stack wears the same class and the same
|
|
207
|
+
inset: the stack's own gap under the head is the card's colour, so the row still needs this white.
|
|
208
|
+
The ink falls back to the wireframe word colour: an unset --color-ink would otherwise
|
|
209
|
+
inherit a dark card's light ink, and the words would vanish on the white. */
|
|
207
210
|
.sheet--paper > .sheet__body {
|
|
208
211
|
--card-bg: var(--color-paper, #fff);
|
|
209
|
-
--card-ink: var(--color-ink);
|
|
210
|
-
--card-muted: var(--_muted-on-paper);
|
|
212
|
+
--card-ink: var(--color-ink, #141414);
|
|
213
|
+
--card-muted: var(--_muted-on-paper, #555555);
|
|
211
214
|
background: var(--card-bg);
|
|
212
215
|
color: var(--card-ink);
|
|
213
216
|
padding-top: var(--sp-6);
|
|
214
217
|
}
|
|
215
|
-
.sheet--paper > .card__foot { --card-bg: var(--color-paper, #fff); color: var(--color-ink); }
|
|
218
|
+
.sheet--paper > .card__foot { --card-bg: var(--color-paper, #fff); color: var(--color-ink, #141414); }
|
|
216
219
|
.sheet__handle--dots {
|
|
217
220
|
--_dot: var(--sp-1);
|
|
218
221
|
--_step: calc(var(--_dot) * 2.5);
|
package/css/stack.css
CHANGED
|
@@ -175,7 +175,9 @@
|
|
|
175
175
|
}
|
|
176
176
|
.sheet-stack--tap > .card.is-open.is-dragging { transition: none; }
|
|
177
177
|
.sheet-stack--tap > .card > .card__head { touch-action: none; }
|
|
178
|
-
/* a pull in the content, already at the top: the words move down, the card stays. --_refresh is the finger, private.
|
|
178
|
+
/* a pull in the content, already at the top: the words move down, the card stays. --_refresh is the finger, private.
|
|
179
|
+
A paper body adds its own --sp-6 on top of this (the rule below): the stack's gap under the head is the
|
|
180
|
+
card's colour, so without the white inset the first row sits on that seam. */
|
|
179
181
|
.sheet-stack > .card > .sheet__body { padding-top: var(--_refresh, 0px); transition: padding-top var(--motion-sheet) ease; }
|
|
180
182
|
.sheet-stack--tap > .card.is-open:not(:has(> .sheet__body)) {
|
|
181
183
|
padding-top: calc(var(--card-pad) + var(--_refresh, 0px));
|
|
@@ -311,6 +313,42 @@
|
|
|
311
313
|
.sheet-stack--tap > .card:has(> .sheet__body).is-open { overflow: clip; }
|
|
312
314
|
.sheet-stack > .card:has(> .sheet__body) > :not(.sheet__body) { flex-shrink: 0; }
|
|
313
315
|
.sheet-stack > .card > .sheet__body { --_cover: 0rem; } /* nothing slid under here: the stack's sheet is always whole */
|
|
316
|
+
/* a closed paper sheet's body stays clear (Lh 2026-10-06). The next sheet's round top does not
|
|
317
|
+
cover the corners, and a white body showed there beside the head. Clear, the card's own colour
|
|
318
|
+
shows in that pocket. Open, the body is white, and the first row sits --sp-6 down, the same white
|
|
319
|
+
inset a single paper sheet keeps: the flex gap under the head is the card's colour, so the row
|
|
320
|
+
would otherwise sit on that seam. A pull adds --_refresh on top of the inset. On the way back
|
|
321
|
+
into the stack the card colour fades in quickly (--motion-quick) and that fade ends with the
|
|
322
|
+
sheet's own slide (--motion-sheet, plus the same stagger), so the corner is the head colour
|
|
323
|
+
at the moment the sheet stops. Rising, the body is white at once. */
|
|
324
|
+
.sheet-stack > .card.sheet--paper > .sheet__body {
|
|
325
|
+
padding-top: calc(var(--sp-6) + var(--_refresh, 0px));
|
|
326
|
+
transition: padding-top var(--motion-sheet) ease, background-color 0s linear;
|
|
327
|
+
}
|
|
328
|
+
.sheet-stack > .card.sheet--paper:not(.is-open) > .sheet__body {
|
|
329
|
+
background-color: transparent;
|
|
330
|
+
transition:
|
|
331
|
+
padding-top var(--motion-sheet) ease,
|
|
332
|
+
background-color var(--motion-quick) ease calc(var(--stagger, 0) * 70ms + var(--motion-sheet) - var(--motion-quick));
|
|
333
|
+
}
|
|
334
|
+
@media (prefers-reduced-motion: reduce) {
|
|
335
|
+
.sheet-stack > .card.sheet--paper:not(.is-open) > .sheet__body {
|
|
336
|
+
transition: padding-top var(--motion-sheet) ease, background-color 0s linear;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/* a paper stack's foot is white to the card's edges, and it covers the tinted flex gap above it so the
|
|
340
|
+
button does not sit on a colour stripe. The head's gap stays: it is outside this foot. The button stays
|
|
341
|
+
where it was — the padding gives back what the bleed takes. */
|
|
342
|
+
.sheet-stack > .card.sheet--paper > .card__foot {
|
|
343
|
+
background: var(--color-paper, #fff);
|
|
344
|
+
color: var(--color-ink, #141414);
|
|
345
|
+
margin-top: calc(-1 * var(--card-gap));
|
|
346
|
+
margin-inline: calc(-1 * var(--card-pad));
|
|
347
|
+
margin-bottom: calc(-1 * var(--card-pad));
|
|
348
|
+
padding-top: var(--card-gap);
|
|
349
|
+
padding-inline: var(--card-pad);
|
|
350
|
+
padding-bottom: var(--card-pad);
|
|
351
|
+
}
|
|
314
352
|
|
|
315
353
|
/* ---- StackSheet's tabs (Lh 2026-09-23): the head's end is a row of small icon buttons, the sheet's pages — the chosen one
|
|
316
354
|
filled (.icon-btn--invert) only while the sheet is open; a count is a small circle over the icon's top right corner ---- */
|
package/dist/cardds.css
CHANGED
|
@@ -1176,7 +1176,9 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
1176
1176
|
}
|
|
1177
1177
|
.sheet-stack--tap > .card.is-open.is-dragging { transition: none; }
|
|
1178
1178
|
.sheet-stack--tap > .card > .card__head { touch-action: none; }
|
|
1179
|
-
/* a pull in the content, already at the top: the words move down, the card stays. --_refresh is the finger, private.
|
|
1179
|
+
/* a pull in the content, already at the top: the words move down, the card stays. --_refresh is the finger, private.
|
|
1180
|
+
A paper body adds its own --sp-6 on top of this (the rule below): the stack's gap under the head is the
|
|
1181
|
+
card's colour, so without the white inset the first row sits on that seam. */
|
|
1180
1182
|
.sheet-stack > .card > .sheet__body { padding-top: var(--_refresh, 0px); transition: padding-top var(--motion-sheet) ease; }
|
|
1181
1183
|
.sheet-stack--tap > .card.is-open:not(:has(> .sheet__body)) {
|
|
1182
1184
|
padding-top: calc(var(--card-pad) + var(--_refresh, 0px));
|
|
@@ -1312,6 +1314,42 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
1312
1314
|
.sheet-stack--tap > .card:has(> .sheet__body).is-open { overflow: clip; }
|
|
1313
1315
|
.sheet-stack > .card:has(> .sheet__body) > :not(.sheet__body) { flex-shrink: 0; }
|
|
1314
1316
|
.sheet-stack > .card > .sheet__body { --_cover: 0rem; } /* nothing slid under here: the stack's sheet is always whole */
|
|
1317
|
+
/* a closed paper sheet's body stays clear (Lh 2026-10-06). The next sheet's round top does not
|
|
1318
|
+
cover the corners, and a white body showed there beside the head. Clear, the card's own colour
|
|
1319
|
+
shows in that pocket. Open, the body is white, and the first row sits --sp-6 down, the same white
|
|
1320
|
+
inset a single paper sheet keeps: the flex gap under the head is the card's colour, so the row
|
|
1321
|
+
would otherwise sit on that seam. A pull adds --_refresh on top of the inset. On the way back
|
|
1322
|
+
into the stack the card colour fades in quickly (--motion-quick) and that fade ends with the
|
|
1323
|
+
sheet's own slide (--motion-sheet, plus the same stagger), so the corner is the head colour
|
|
1324
|
+
at the moment the sheet stops. Rising, the body is white at once. */
|
|
1325
|
+
.sheet-stack > .card.sheet--paper > .sheet__body {
|
|
1326
|
+
padding-top: calc(var(--sp-6) + var(--_refresh, 0px));
|
|
1327
|
+
transition: padding-top var(--motion-sheet) ease, background-color 0s linear;
|
|
1328
|
+
}
|
|
1329
|
+
.sheet-stack > .card.sheet--paper:not(.is-open) > .sheet__body {
|
|
1330
|
+
background-color: transparent;
|
|
1331
|
+
transition:
|
|
1332
|
+
padding-top var(--motion-sheet) ease,
|
|
1333
|
+
background-color var(--motion-quick) ease calc(var(--stagger, 0) * 70ms + var(--motion-sheet) - var(--motion-quick));
|
|
1334
|
+
}
|
|
1335
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1336
|
+
.sheet-stack > .card.sheet--paper:not(.is-open) > .sheet__body {
|
|
1337
|
+
transition: padding-top var(--motion-sheet) ease, background-color 0s linear;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
/* a paper stack's foot is white to the card's edges, and it covers the tinted flex gap above it so the
|
|
1341
|
+
button does not sit on a colour stripe. The head's gap stays: it is outside this foot. The button stays
|
|
1342
|
+
where it was — the padding gives back what the bleed takes. */
|
|
1343
|
+
.sheet-stack > .card.sheet--paper > .card__foot {
|
|
1344
|
+
background: var(--color-paper, #fff);
|
|
1345
|
+
color: var(--color-ink, #141414);
|
|
1346
|
+
margin-top: calc(-1 * var(--card-gap));
|
|
1347
|
+
margin-inline: calc(-1 * var(--card-pad));
|
|
1348
|
+
margin-bottom: calc(-1 * var(--card-pad));
|
|
1349
|
+
padding-top: var(--card-gap);
|
|
1350
|
+
padding-inline: var(--card-pad);
|
|
1351
|
+
padding-bottom: var(--card-pad);
|
|
1352
|
+
}
|
|
1315
1353
|
|
|
1316
1354
|
/* ---- StackSheet's tabs (Lh 2026-09-23): the head's end is a row of small icon buttons, the sheet's pages — the chosen one
|
|
1317
1355
|
filled (.icon-btn--invert) only while the sheet is open; a count is a small circle over the icon's top right corner ---- */
|
|
@@ -1599,16 +1637,19 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
1599
1637
|
The flex gap under the head is outside the body, so it stays the sheet's tint.
|
|
1600
1638
|
The first field would sit on that colour seam. The white inset is --sp-6 (24px at
|
|
1601
1639
|
the default spacing), the body's own top padding, and only when the sheet is paper.
|
|
1602
|
-
A plain sheet keeps padding-top 0.
|
|
1640
|
+
A plain sheet keeps padding-top 0. A sheet in a stack wears the same class and the same
|
|
1641
|
+
inset: the stack's own gap under the head is the card's colour, so the row still needs this white.
|
|
1642
|
+
The ink falls back to the wireframe word colour: an unset --color-ink would otherwise
|
|
1643
|
+
inherit a dark card's light ink, and the words would vanish on the white. */
|
|
1603
1644
|
.sheet--paper > .sheet__body {
|
|
1604
1645
|
--card-bg: var(--color-paper, #fff);
|
|
1605
|
-
--card-ink: var(--color-ink);
|
|
1606
|
-
--card-muted: var(--_muted-on-paper);
|
|
1646
|
+
--card-ink: var(--color-ink, #141414);
|
|
1647
|
+
--card-muted: var(--_muted-on-paper, #555555);
|
|
1607
1648
|
background: var(--card-bg);
|
|
1608
1649
|
color: var(--card-ink);
|
|
1609
1650
|
padding-top: var(--sp-6);
|
|
1610
1651
|
}
|
|
1611
|
-
.sheet--paper > .card__foot { --card-bg: var(--color-paper, #fff); color: var(--color-ink); }
|
|
1652
|
+
.sheet--paper > .card__foot { --card-bg: var(--color-paper, #fff); color: var(--color-ink, #141414); }
|
|
1612
1653
|
.sheet__handle--dots {
|
|
1613
1654
|
--_dot: var(--sp-1);
|
|
1614
1655
|
--_step: calc(var(--_dot) * 2.5);
|
package/dist/cards/Card.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export type Tone = 1 | 2 | 3 | 4 | 5;
|
|
|
7
7
|
export interface CardProps extends ComponentProps<'article'> {
|
|
8
8
|
/** the tone slot — see `Tone` */
|
|
9
9
|
tone?: Tone;
|
|
10
|
+
/** the content is white paper and the head keeps the card's colour. The same look as `Sheet paper`. Omit it and the content matches the head */
|
|
11
|
+
paper?: boolean;
|
|
10
12
|
/** compact: a small card inside a card or a sheet body (a note, a promo) */
|
|
11
13
|
sm?: boolean;
|
|
12
14
|
/** a list row that is its own card: thumb · body · end, in a CardList */
|
|
@@ -45,7 +47,7 @@ export interface CardProps extends ComponentProps<'article'> {
|
|
|
45
47
|
* boundary). The order is the card's, never the writer's. A head of its own shape: write `<CardHead>` as the first child instead.
|
|
46
48
|
* A page with one feature and one CTA may be a single card. Keep everything big.
|
|
47
49
|
*/
|
|
48
|
-
export declare function Card({ tone, sm, row, cover, fold, centre, band, as, heading, caption, end, level, foot, footLink, stack, className, style, children, onClick, ref, ...rest }: CardProps): import("react").DetailedReactHTMLElement<{
|
|
50
|
+
export declare function Card({ tone, paper, sm, row, cover, fold, centre, band, as, heading, caption, end, level, foot, footLink, stack, className, style, children, onClick, ref, ...rest }: CardProps): import("react").DetailedReactHTMLElement<{
|
|
49
51
|
onClick: import("react").MouseEventHandler<HTMLElement> | undefined;
|
|
50
52
|
"aria-busy"?: (boolean | "true" | "false") | undefined;
|
|
51
53
|
ref: (node: HTMLElement | null) => void;
|
package/dist/cards/Card.js
CHANGED
|
@@ -12,7 +12,7 @@ import { StackHeadCtx, StackPullCtx, stackPaint, useStackCard } from '../sheets/
|
|
|
12
12
|
* boundary). The order is the card's, never the writer's. A head of its own shape: write `<CardHead>` as the first child instead.
|
|
13
13
|
* A page with one feature and one CTA may be a single card. Keep everything big.
|
|
14
14
|
*/
|
|
15
|
-
export function Card({ tone, sm, row, cover, fold, centre, band, as = 'article', heading, caption, end, level, foot, footLink, stack, className, style, children, onClick, ref, ...rest }) {
|
|
15
|
+
export function Card({ tone, paper, sm, row, cover, fold, centre, band, as = 'article', heading, caption, end, level, foot, footLink, stack, className, style, children, onClick, ref, ...rest }) {
|
|
16
16
|
const head = heading != null || caption != null || end != null;
|
|
17
17
|
const tail = foot != null || footLink != null;
|
|
18
18
|
if (head || tail) {
|
|
@@ -54,7 +54,7 @@ export function Card({ tone, sm, row, cover, fold, centre, band, as = 'article',
|
|
|
54
54
|
const props = {
|
|
55
55
|
...rest,
|
|
56
56
|
ref: setRef,
|
|
57
|
-
className: cx('card', tone && tone !== 1 && `card--${tone}`, sm && 'card--sm', row && 'card--row', cover && 'card--cover', fold && 'card--fold', centre && 'card--centre', band && 'card--band', painted.className, className),
|
|
57
|
+
className: cx('card', tone && tone !== 1 && `card--${tone}`, paper && 'sheet--paper', sm && 'card--sm', row && 'card--row', cover && 'card--cover', fold && 'card--fold', centre && 'card--centre', band && 'card--band', painted.className, className),
|
|
58
58
|
style: painted.style || style ? { ...painted.style, ...style } : undefined,
|
|
59
59
|
...(stack ? { 'aria-busy': painted.busy } : {}),
|
|
60
60
|
onClick: stack ? click : onClick,
|
package/dist/sheets/Sheet.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export interface SheetProps extends Omit<ComponentProps<'article'>, 'onChange'>
|
|
|
25
25
|
mark?: 'line' | 'dots';
|
|
26
26
|
/** the card tone slot, as `Card tone` — 2 and up add `card--N`. The head shows it; with `paper` the content does not */
|
|
27
27
|
tone?: 1 | 2 | 3 | 4 | 5;
|
|
28
|
-
/** the content is white paper and the head keeps the sheet's colour. Omit it and the content is the same colour as the head */
|
|
28
|
+
/** the content is white paper and the head keeps the sheet's colour. The same prop on a `StackSheet` or a `Card` in a stack. Omit it and the content is the same colour as the head */
|
|
29
29
|
paper?: boolean;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
@@ -13,8 +13,10 @@ export interface StackSheetTab {
|
|
|
13
13
|
export interface StackSheetProps extends Omit<ComponentProps<'article'>, 'title'> {
|
|
14
14
|
/** the SHEET HEAD's title — an h2 (the page's h1 is its own) */
|
|
15
15
|
title: ReactNode;
|
|
16
|
-
/** the
|
|
16
|
+
/** the tone slot — see `Tone`. The head shows it */
|
|
17
17
|
tone?: Tone;
|
|
18
|
+
/** the content is white paper and the head keeps the sheet's colour. The same look as `Sheet paper`. Omit it and the content matches the head */
|
|
19
|
+
paper?: boolean;
|
|
18
20
|
/** the head's end when the sheet has no tabs: an Icon, an IconRow */
|
|
19
21
|
icon?: ReactNode;
|
|
20
22
|
/** TABS in the head: icon buttons at the end — the sheet's pages. A tap on one in a peeked head opens the sheet on it */
|
|
@@ -40,4 +42,4 @@ export interface StackSheetProps extends Omit<ComponentProps<'article'>, 'title'
|
|
|
40
42
|
* A count shows as a small circle over its icon. The body is the app's: render the page of the chosen tab (and nothing while the sheet
|
|
41
43
|
* is closed — see `Home`). A direct child of `SheetStack`.
|
|
42
44
|
*/
|
|
43
|
-
export declare function StackSheet({ title, tone, icon, tabs, tab: tabProp, defaultTab, onTabChange, foot, backLabel, backAt, stack, className, children, ...rest }: StackSheetProps): import("react").JSX.Element;
|
|
45
|
+
export declare function StackSheet({ title, tone, paper, icon, tabs, tab: tabProp, defaultTab, onTabChange, foot, backLabel, backAt, stack, className, children, ...rest }: StackSheetProps): import("react").JSX.Element;
|
|
@@ -19,7 +19,7 @@ import { word } from '../words.js';
|
|
|
19
19
|
* A count shows as a small circle over its icon. The body is the app's: render the page of the chosen tab (and nothing while the sheet
|
|
20
20
|
* is closed — see `Home`). A direct child of `SheetStack`.
|
|
21
21
|
*/
|
|
22
|
-
export function StackSheet({ title, tone, icon, tabs, tab: tabProp, defaultTab, onTabChange, foot, backLabel = word('back'), backAt = 'none', stack, className, children, ...rest }) {
|
|
22
|
+
export function StackSheet({ title, tone, paper, icon, tabs, tab: tabProp, defaultTab, onTabChange, foot, backLabel = word('back'), backAt = 'none', stack, className, children, ...rest }) {
|
|
23
23
|
const [tab, pick] = useControlled(tabProp, defaultTab ?? tabs?.[0]?.id, onTabChange);
|
|
24
24
|
// a title longer than its room does not wrap: it runs sideways, like a song title in a short slot — the room it overflows by
|
|
25
25
|
// is measured here (the tabs may grow with the text size) and handed to the CSS as --_over
|
|
@@ -38,5 +38,5 @@ export function StackSheet({ title, tone, icon, tabs, tab: tabProp, defaultTab,
|
|
|
38
38
|
measure();
|
|
39
39
|
return watchSize([h, run], measure);
|
|
40
40
|
}, [title]);
|
|
41
|
-
return (_jsxs(Card, { stack: stack, tone: tone, className: cx('stack-sheet', className), ...rest, children: [_jsxs(CardHead, { children: [backAt === 'start' && _jsx(StackBack, { label: backLabel }), _jsx(Text, { level: "h2", ref: titleRef, className: cx('stack-sheet__title', long && 'is-long'), children: _jsx("span", { className: "stack-sheet__run", children: title }) }), tabs?.length ? (_jsx("span", { className: "stack-sheet__tabs", role: "tablist", children: tabs.map((t) => (_jsxs(IconBtn, { sm: true, invert: t.id === tab, role: "tab", "aria-selected": t.id === tab, label: t.label, className: "stack-sheet__tab", onClick: () => pick(t.id), children: [_jsx(Icon, { name: t.icon }), t.count ? _jsx(Badge, { className: "stack-sheet__count", children: t.count > 99 ? '99+' : t.count }) : null] }, t.id))) })) : icon, backAt === 'end' && _jsx(StackBack, { end: true, label: backLabel })] }), _jsx(SheetBody, { role: tabs?.length ? 'tabpanel' : undefined, children: children }), foot != null && _jsx(CardFoot, { children: foot })] }));
|
|
41
|
+
return (_jsxs(Card, { stack: stack, tone: tone, paper: paper, className: cx('stack-sheet', className), ...rest, children: [_jsxs(CardHead, { children: [backAt === 'start' && _jsx(StackBack, { label: backLabel }), _jsx(Text, { level: "h2", ref: titleRef, className: cx('stack-sheet__title', long && 'is-long'), children: _jsx("span", { className: "stack-sheet__run", children: title }) }), tabs?.length ? (_jsx("span", { className: "stack-sheet__tabs", role: "tablist", children: tabs.map((t) => (_jsxs(IconBtn, { sm: true, invert: t.id === tab, role: "tab", "aria-selected": t.id === tab, label: t.label, className: "stack-sheet__tab", onClick: () => pick(t.id), children: [_jsx(Icon, { name: t.icon }), t.count ? _jsx(Badge, { className: "stack-sheet__count", children: t.count > 99 ? '99+' : t.count }) : null] }, t.id))) })) : icon, backAt === 'end' && _jsx(StackBack, { end: true, label: backLabel })] }), _jsx(SheetBody, { role: tabs?.length ? 'tabpanel' : undefined, children: children }), foot != null && _jsx(CardFoot, { children: foot })] }));
|
|
42
42
|
}
|
package/dist/templates/Home.d.ts
CHANGED
|
@@ -7,8 +7,10 @@ export interface HomeSheet {
|
|
|
7
7
|
title: ReactNode;
|
|
8
8
|
/** the sheet head's end when it has no tabs: an Icon, an IconRow */
|
|
9
9
|
icon?: ReactNode;
|
|
10
|
-
/** the
|
|
10
|
+
/** the tone slot — see `Tone` (default: 2, 3, 1, 2, 3 by place). The head shows it */
|
|
11
11
|
tone?: Tone;
|
|
12
|
+
/** white content, the head keeps `tone`. The same look as `Sheet paper` */
|
|
13
|
+
paper?: boolean;
|
|
12
14
|
/** the sheet's pages as icon tabs in its head (a count shows as a small circle over the icon) — see `StackSheet` */
|
|
13
15
|
tabs?: StackSheetTab[];
|
|
14
16
|
/** the tab shown first (default: the first) */
|
package/dist/templates/Home.js
CHANGED
|
@@ -50,5 +50,5 @@ export function Home({ top, title, sheets, open: openProp, defaultOpen = null, o
|
|
|
50
50
|
}, [leaving]);
|
|
51
51
|
const [tabs, setTabs] = useState(() => Object.fromEntries(sheets.map((x, i) => [i, x.defaultTab ?? x.tabs?.[0]?.id])));
|
|
52
52
|
const shows = (i) => i === shown || i === leaving || (keep && seen.has(i));
|
|
53
|
-
return (_jsxs(Screen, { fill: true, top: top, ...rest, children: [_jsx(Text, { level: "h1", as: "h1", sr: true, children: title }), _jsx(SheetStack, { closed: true, open: shown, onOpenChange: request, onRefresh: onRefresh, refreshing: refreshing, base: base, children: sheets.map((s, i) => (_jsx(StackSheet, { tone: s.tone ?? TONES[i], title: s.title, icon: s.icon, tabs: s.tabs, tab: tabs[i], onTabChange: (t) => setTabs((v) => ({ ...v, [i]: t })), backLabel: backLabel, backAt: backAt, foot: typeof s.foot === 'function' ? s.foot(tabs[i]) : s.foot, children: shows(i) ? (typeof s.body === 'function' ? s.body(tabs[i]) : s.body) : null }, i))) }), children] }));
|
|
53
|
+
return (_jsxs(Screen, { fill: true, top: top, ...rest, children: [_jsx(Text, { level: "h1", as: "h1", sr: true, children: title }), _jsx(SheetStack, { closed: true, open: shown, onOpenChange: request, onRefresh: onRefresh, refreshing: refreshing, base: base, children: sheets.map((s, i) => (_jsx(StackSheet, { tone: s.tone ?? TONES[i], paper: s.paper, title: s.title, icon: s.icon, tabs: s.tabs, tab: tabs[i], onTabChange: (t) => setTabs((v) => ({ ...v, [i]: t })), backLabel: backLabel, backAt: backAt, foot: typeof s.foot === 'function' ? s.foot(tabs[i]) : s.foot, children: shows(i) ? (typeof s.body === 'function' ? s.body(tabs[i]) : s.body) : null }, i))) }), children] }));
|
|
54
54
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usableapp/cardds",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.58",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "card-first mobile design system, React-first: the components in src/ are thin wrappers over the CSS contract (css/*.css stays the only truth); gallery/ shows every story live (npm run dev), tests/ measures the geometry.",
|