@usableapp/cardds 0.7.51 → 0.7.52

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 CHANGED
@@ -2,6 +2,11 @@
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.52 — 2026-10-05
6
+
7
+ ### Changed
8
+ - **A `StackSheet` tab's disc shows only while its sheet is open** (Lh 2026-10-04). On the home, every peeked sheet's tabs are the icon alone — none is filled. The chosen tab fills as the sheet rises (the one that was pressed, or the page the sheet opens on) and the fill leaves as the sheet folds. Which page is current is unchanged; only the paint waits. Nothing to change in a screen.
9
+
5
10
  ## 0.7.51 — 2026-10-04
6
11
 
7
12
  ### Added
package/css/finish.css CHANGED
@@ -65,6 +65,11 @@
65
65
  0 1px 2px color-mix(in srgb, var(--_shade) 20%, transparent),
66
66
  0 0.5rem 1rem -0.25rem color-mix(in srgb, var(--accent) 45%, transparent);
67
67
  }
68
+ /* a peeked stack tab is the icon alone: no sheen and no shadow until its sheet is open (the fill fades with the sheet) */
69
+ [data-finish="lit"] .sheet-stack--tap > .card:not(.is-open) > .card__head .stack-sheet__tab {
70
+ background-image: none;
71
+ box-shadow: none;
72
+ }
68
73
  [data-finish="lit"] :is(.btn:not(.btn--quiet), .icon-btn:not(.icon-btn-group > *, .stack-sheet__tab:not(.icon-btn--invert))):active:not(:disabled) {
69
74
  background-image: none;
70
75
  box-shadow: var(--finish-control-down);
package/css/stack.css CHANGED
@@ -285,7 +285,7 @@
285
285
  .sheet-stack > .card > .sheet__body { --_cover: 0rem; } /* nothing slid under here: the stack's sheet is always whole */
286
286
 
287
287
  /* ---- 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
288
- filled (.icon-btn--invert); a count is a small circle over the icon's top right corner ---- */
288
+ filled (.icon-btn--invert) only while the sheet is open; a count is a small circle over the icon's top right corner ---- */
289
289
  .stack-sheet__tabs { display: flex; gap: var(--stack-sheet-tabs-gap, var(--sp-2)); flex: none; } /* room between the tabs: with none, the chosen tab's disc touched its neighbour's (Lh 2026-09-24) */
290
290
  /* the head is ONE line, always (Lh 2026-09-24): the tabs keep their size, the TITLE gives — it never wraps, it runs sideways
291
291
  (StackSheet measures --_over, the width it overflows by, and sets .is-long), one way: it waits, runs to the end, waits, and starts again from the first letter — like a song title */
@@ -304,8 +304,19 @@
304
304
  @media (prefers-reduced-motion: reduce) {
305
305
  .stack-sheet__title.is-long .stack-sheet__run { animation: none; display: inline; } /* inline: an ellipsis cannot cut an inline-block */
306
306
  .stack-sheet__title.is-long { text-overflow: ellipsis; }
307
+ .stack-sheet__tab { transition: none; } /* the disc is simply there while open, and gone while closed */
308
+ }
309
+ .stack-sheet__tab {
310
+ position: relative;
311
+ /* the disc fades with the sheet: in as it rises, out as it folds, and across when another tab is pressed.
312
+ scale stays on the press (actions.css) so the give under a finger stays quick */
313
+ transition:
314
+ scale var(--motion-press) ease-out,
315
+ background-color var(--motion-sheet) ease,
316
+ color var(--motion-sheet) ease,
317
+ border-color var(--motion-sheet) ease,
318
+ box-shadow var(--motion-sheet) ease;
307
319
  }
308
- .stack-sheet__tab { position: relative; }
309
320
  .stack-sheet__tab > .stack-sheet__count { /* outranks .badge (numbers.css loads after this file) */
310
321
  position: absolute;
311
322
  top: calc(-1 * var(--stack-sheet-count-out, var(--sp-2))); /* how far it stands OUT of the tab's corner, up and to the right: at sp-1 it
@@ -323,6 +334,12 @@
323
334
  /* a tab not chosen is the icon alone — no ring, no ground (Lh 2026-09-23: "the circle around is not pretty"); the chosen one turns
324
335
  to the opposite colour (.icon-btn--invert). */
325
336
  .stack-sheet__tab:not(.icon-btn--invert) { border-color: transparent; background: transparent; box-shadow: none; color: inherit; } /* the sheet's own ink, on any paper */
337
+ /* a CLOSED sheet shows no chosen disc either (Lh 2026-10-04): arriving on the home, every tab of every sheet is the icon
338
+ alone. The fill fades in with the rise — the tab that was pressed, or the one the sheet opens on — and fades out as the
339
+ sheet folds. The class stays (which page it is); only the paint waits for .is-open. */
340
+ .sheet-stack--tap > .card:not(.is-open) > .card__head .stack-sheet__tab.icon-btn--invert {
341
+ border-color: transparent; background-color: transparent; box-shadow: none; color: inherit;
342
+ }
326
343
  /* the last tab's ICON lines up with the inset, not its button's edge: an unchosen tab shows the glyph only, so the button's own
327
344
  margin around it reaches into the card's padding — and an open head (back · title · three tabs) keeps one line (Lh 2026-09-23) */
328
345
  .card__head > .stack-sheet__tabs { margin-right: calc(-1 * var(--sp-2)); }
package/dist/cardds.css CHANGED
@@ -1286,7 +1286,7 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
1286
1286
  .sheet-stack > .card > .sheet__body { --_cover: 0rem; } /* nothing slid under here: the stack's sheet is always whole */
1287
1287
 
1288
1288
  /* ---- 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
1289
- filled (.icon-btn--invert); a count is a small circle over the icon's top right corner ---- */
1289
+ filled (.icon-btn--invert) only while the sheet is open; a count is a small circle over the icon's top right corner ---- */
1290
1290
  .stack-sheet__tabs { display: flex; gap: var(--stack-sheet-tabs-gap, var(--sp-2)); flex: none; } /* room between the tabs: with none, the chosen tab's disc touched its neighbour's (Lh 2026-09-24) */
1291
1291
  /* the head is ONE line, always (Lh 2026-09-24): the tabs keep their size, the TITLE gives — it never wraps, it runs sideways
1292
1292
  (StackSheet measures --_over, the width it overflows by, and sets .is-long), one way: it waits, runs to the end, waits, and starts again from the first letter — like a song title */
@@ -1305,8 +1305,19 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
1305
1305
  @media (prefers-reduced-motion: reduce) {
1306
1306
  .stack-sheet__title.is-long .stack-sheet__run { animation: none; display: inline; } /* inline: an ellipsis cannot cut an inline-block */
1307
1307
  .stack-sheet__title.is-long { text-overflow: ellipsis; }
1308
+ .stack-sheet__tab { transition: none; } /* the disc is simply there while open, and gone while closed */
1309
+ }
1310
+ .stack-sheet__tab {
1311
+ position: relative;
1312
+ /* the disc fades with the sheet: in as it rises, out as it folds, and across when another tab is pressed.
1313
+ scale stays on the press (actions.css) so the give under a finger stays quick */
1314
+ transition:
1315
+ scale var(--motion-press) ease-out,
1316
+ background-color var(--motion-sheet) ease,
1317
+ color var(--motion-sheet) ease,
1318
+ border-color var(--motion-sheet) ease,
1319
+ box-shadow var(--motion-sheet) ease;
1308
1320
  }
1309
- .stack-sheet__tab { position: relative; }
1310
1321
  .stack-sheet__tab > .stack-sheet__count { /* outranks .badge (numbers.css loads after this file) */
1311
1322
  position: absolute;
1312
1323
  top: calc(-1 * var(--stack-sheet-count-out, var(--sp-2))); /* how far it stands OUT of the tab's corner, up and to the right: at sp-1 it
@@ -1324,6 +1335,12 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
1324
1335
  /* a tab not chosen is the icon alone — no ring, no ground (Lh 2026-09-23: "the circle around is not pretty"); the chosen one turns
1325
1336
  to the opposite colour (.icon-btn--invert). */
1326
1337
  .stack-sheet__tab:not(.icon-btn--invert) { border-color: transparent; background: transparent; box-shadow: none; color: inherit; } /* the sheet's own ink, on any paper */
1338
+ /* a CLOSED sheet shows no chosen disc either (Lh 2026-10-04): arriving on the home, every tab of every sheet is the icon
1339
+ alone. The fill fades in with the rise — the tab that was pressed, or the one the sheet opens on — and fades out as the
1340
+ sheet folds. The class stays (which page it is); only the paint waits for .is-open. */
1341
+ .sheet-stack--tap > .card:not(.is-open) > .card__head .stack-sheet__tab.icon-btn--invert {
1342
+ border-color: transparent; background-color: transparent; box-shadow: none; color: inherit;
1343
+ }
1327
1344
  /* the last tab's ICON lines up with the inset, not its button's edge: an unchosen tab shows the glyph only, so the button's own
1328
1345
  margin around it reaches into the card's padding — and an open head (back · title · three tabs) keeps one line (Lh 2026-09-23) */
1329
1346
  .card__head > .stack-sheet__tabs { margin-right: calc(-1 * var(--sp-2)); }
@@ -4136,6 +4153,11 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
4136
4153
  0 1px 2px color-mix(in srgb, var(--_shade) 20%, transparent),
4137
4154
  0 0.5rem 1rem -0.25rem color-mix(in srgb, var(--accent) 45%, transparent);
4138
4155
  }
4156
+ /* a peeked stack tab is the icon alone: no sheen and no shadow until its sheet is open (the fill fades with the sheet) */
4157
+ [data-finish="lit"] .sheet-stack--tap > .card:not(.is-open) > .card__head .stack-sheet__tab {
4158
+ background-image: none;
4159
+ box-shadow: none;
4160
+ }
4139
4161
  [data-finish="lit"] :is(.btn:not(.btn--quiet), .icon-btn:not(.icon-btn-group > *, .stack-sheet__tab:not(.icon-btn--invert))):active:not(:disabled) {
4140
4162
  background-image: none;
4141
4163
  box-shadow: var(--finish-control-down);
@@ -32,8 +32,9 @@ export interface StackSheetProps extends Omit<ComponentProps<'article'>, 'title'
32
32
  }
33
33
  /**
34
34
  * StackSheet — ONE sheet of a `SheetStack`, in the one sheet shape: SHEET HEAD (back · title · tabs or an icon) pinned at the top ·
35
- * SHEET BODY (the children; scrolls) · SHEET FOOT (`foot`, the CTA) at the bottom. Its tabs are icon buttons, the chosen one filled;
36
- * 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
35
+ * SHEET BODY (the children; scrolls) · SHEET FOOT (`foot`, the CTA) at the bottom. Its tabs are icon buttons. The chosen one is filled
36
+ * only while this sheet is open — a closed home shows every icon plain; the disc fades in with the rise and out with the fold.
37
+ * 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
37
38
  * is closed — see `Home`). A direct child of `SheetStack`.
38
39
  */
39
40
  export declare function StackSheet({ title, tone, icon, tabs, tab: tabProp, defaultTab, onTabChange, foot, backLabel, backAt, className, children, ...rest }: StackSheetProps): import("react").JSX.Element;
@@ -14,8 +14,9 @@ import { Badge } from '../numbers/Badge.js';
14
14
  import { word } from '../words.js';
15
15
  /**
16
16
  * StackSheet — ONE sheet of a `SheetStack`, in the one sheet shape: SHEET HEAD (back · title · tabs or an icon) pinned at the top ·
17
- * SHEET BODY (the children; scrolls) · SHEET FOOT (`foot`, the CTA) at the bottom. Its tabs are icon buttons, the chosen one filled;
18
- * 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
17
+ * SHEET BODY (the children; scrolls) · SHEET FOOT (`foot`, the CTA) at the bottom. Its tabs are icon buttons. The chosen one is filled
18
+ * only while this sheet is open — a closed home shows every icon plain; the disc fades in with the rise and out with the fold.
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
19
20
  * is closed — see `Home`). A direct child of `SheetStack`.
20
21
  */
21
22
  export function StackSheet({ title, tone, icon, tabs, tab: tabProp, defaultTab, onTabChange, foot, backLabel = word('back'), backAt = 'none', className, children, ...rest }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usableapp/cardds",
3
- "version": "0.7.51",
3
+ "version": "0.7.52",
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.",