@usableapp/cardds 0.7.59 → 0.7.61
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/css/sheet.css +1 -1
- package/css/stack.css +11 -3
- package/css/tokens.css +1 -0
- package/dist/cardds.css +13 -4
- package/dist/forms/Pin.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.61 — 2026-10-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- **A sheet's grab line is 1px** (Lh 2026-10-06) — it was 2px. On a single `Sheet` (the default mark) and on a stack sheet with `mark="line"`. Same length, same place. The thickness is one root token, `--hairline-w` (1px): set it on `:root` in your `theme.css` to tune it (`2px` gives the old line back). Nothing to change in a screen; a test that measured the handle's height reads 1.
|
|
9
|
+
- **A `paper` stack sheet's head band is slimmer** (Lh 2026-10-06) — the white starts 8px (`--sp-2`) under the head, not a whole `--card-gap` (20px): the coloured band of an open sheet is 77.5px tall at the defaults, it was 89.5. `SheetStack` / `Home` sheets with `paper` only; a single paper `Sheet`, a stack sheet without `paper`, and the peeked heads are unchanged. Nothing to change in a screen; a test that measured where the white body starts under the head must expect 8px.
|
|
10
|
+
|
|
11
|
+
## 0.7.60 — 2026-10-06
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- **A pull on a `paper` stack sheet follows the finger** (since 0.7.57 it did not): in a `SheetStack` / `Home` whose sheets are `paper`, the words came down late behind the finger during a pull to refresh. They move with it now, as on a sheet without `paper`. Nothing to change in a screen.
|
|
15
|
+
- **`Pin`: a cell given the cursor by a script in the page's first moments does not look ready** — on a phone, a script's focus within the first 0.7 s after the page loaded showed the full border and the caret with no keyboard up. It rests until a tap, the keyboard, or a digit, as at any other moment.
|
|
16
|
+
- **`SheetStack mark="line"`: the line is as thin as a single `Sheet`'s** — it was 4px in 0.7.59, the Sheet's is 2px. Same length, same place. Nothing to change in a screen.
|
|
17
|
+
|
|
5
18
|
## 0.7.59 — 2026-10-06
|
|
6
19
|
|
|
7
20
|
### Fixed
|
package/css/sheet.css
CHANGED
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
/* --sheet-peek is declared on the BOX the sheet slides in, not on the sheet: the words behind a peeked sheet
|
|
91
91
|
have to read it too (step.css keeps that much room under them), and a token only flows down. The sheet
|
|
92
92
|
inherits it. A sheet whose head is taller retunes it on the box. */
|
|
93
|
-
:is(.step, .sheet-stage) { --_handle: var(--
|
|
93
|
+
:is(.step, .sheet-stage) { --_handle: var(--hairline-w); --sheet-peek: calc(var(--card-pad-rest) + var(--sheet-head-h) + var(--card-gap-rest) + var(--safe-bottom)); } /* + the gesture bar: the peeked head stands above it. The handle sits IN the card's top padding, so the strip is that padding, the title row and the gap under it */
|
|
94
94
|
/* the head's floor: a tap, or an h2 line with its Thai-mark padding when the type is bigger than that (a large text-size
|
|
95
95
|
setting on a narrow phone) — the strip and the head read the same number, so the title row is always inside the strip */
|
|
96
96
|
:root { --sheet-head-h: max(var(--tap), calc(var(--fs-h2) * 1.25 + var(--sp-2))); }
|
package/css/stack.css
CHANGED
|
@@ -211,15 +211,17 @@
|
|
|
211
211
|
}
|
|
212
212
|
@keyframes stack-grip-dissolve { from { --_grip: 0; } to { --_grip: 1; } }
|
|
213
213
|
/* the grip as ONE LINE (`mark="line"`, Lh 2026-10-06): the single Sheet's line, at the same place and the same length. It reads the
|
|
214
|
-
same --_grip-ink, so while its sheet reloads it changes colour exactly as the dots do.
|
|
214
|
+
same --_grip-ink, so while its sheet reloads it changes colour exactly as the dots do. As thin as the Sheet's (--hairline-w),
|
|
215
|
+
from the dots' top, as the Sheet's line starts there too. A bar and two round ends; the resting
|
|
215
216
|
ink is mixed into the card's own colour (opaque), so the ends do not show darker where they lie on the bar. */
|
|
216
217
|
.stack-card--line {
|
|
217
218
|
--_grip-w: calc(var(--sp-base) * 18);
|
|
218
219
|
--_grip-ink: color-mix(in srgb, currentColor 30%, var(--card-bg));
|
|
219
220
|
--_grip-bar: linear-gradient(var(--_grip-ink), var(--_grip-ink));
|
|
220
|
-
--_grip-
|
|
221
|
+
--_grip-h: var(--hairline-w);
|
|
222
|
+
--_grip-end: calc((var(--_grip-w) - var(--_grip-h)) / 2);
|
|
221
223
|
background-image: var(--_grip-img), var(--_grip-bar), var(--_grip-img);
|
|
222
|
-
background-size: var(--_grip-
|
|
224
|
+
background-size: var(--_grip-h) var(--_grip-h), calc(var(--_grip-w) - var(--_grip-h)) var(--_grip-h), var(--_grip-h) var(--_grip-h);
|
|
223
225
|
background-position: calc(50% - var(--_grip-end)) var(--_grip-y), 50% var(--_grip-y), calc(50% + var(--_grip-end)) var(--_grip-y);
|
|
224
226
|
}
|
|
225
227
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -333,10 +335,16 @@
|
|
|
333
335
|
into the stack the card colour fades in quickly (--motion-quick) and that fade ends with the
|
|
334
336
|
sheet's own slide (--motion-sheet, plus the same stagger), so the corner is the head colour
|
|
335
337
|
at the moment the sheet stops. Rising, the body is white at once. */
|
|
338
|
+
/* the head's band is as slim as it can be (Lh 2026-10-06: 20 over · 48 head · 20 under read as a heavy bar): the white starts
|
|
339
|
+
--sp-2 under the head, not a whole --card-gap. The body is pulled up by the difference — the card's gap is left alone, the
|
|
340
|
+
stack's step and the body's own rows read it. */
|
|
336
341
|
.sheet-stack > .card.sheet--paper > .sheet__body {
|
|
342
|
+
margin-top: calc(var(--sp-2) - var(--card-gap));
|
|
337
343
|
padding-top: calc(var(--sp-6) + var(--_refresh, 0px));
|
|
338
344
|
transition: padding-top var(--motion-sheet) ease, background-color 0s linear;
|
|
339
345
|
}
|
|
346
|
+
/* a pull follows the finger at once, on paper too: the rule above is as strong as the stack's own `is-refreshing` one and comes later */
|
|
347
|
+
.sheet-stack > .card.sheet--paper > .sheet__body.is-refreshing { transition: none; }
|
|
340
348
|
.sheet-stack > .card.sheet--paper:not(.is-open) > .sheet__body {
|
|
341
349
|
background-color: transparent;
|
|
342
350
|
transition:
|
package/css/tokens.css
CHANGED
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
|
|
87
87
|
/* ---- borders / rules / elevation (px on purpose: crisp at any scale) ---- */
|
|
88
88
|
--border-w: 1.5px;
|
|
89
|
+
--hairline-w: 1px; /* the thinnest mark: a sheet's grab line (Lh 2026-10-06) */
|
|
89
90
|
--rule-w: 2px; /* dotted connectors, picker rules */
|
|
90
91
|
--scroll-w: 1px; /* the scrollbar of a .bleed track: a hairline of ink */
|
|
91
92
|
--focus: 2px solid currentColor; /* :focus-visible ring */
|
package/dist/cardds.css
CHANGED
|
@@ -127,6 +127,7 @@
|
|
|
127
127
|
|
|
128
128
|
/* ---- borders / rules / elevation (px on purpose: crisp at any scale) ---- */
|
|
129
129
|
--border-w: 1.5px;
|
|
130
|
+
--hairline-w: 1px; /* the thinnest mark: a sheet's grab line (Lh 2026-10-06) */
|
|
130
131
|
--rule-w: 2px; /* dotted connectors, picker rules */
|
|
131
132
|
--scroll-w: 1px; /* the scrollbar of a .bleed track: a hairline of ink */
|
|
132
133
|
--focus: 2px solid currentColor; /* :focus-visible ring */
|
|
@@ -1212,15 +1213,17 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
1212
1213
|
}
|
|
1213
1214
|
@keyframes stack-grip-dissolve { from { --_grip: 0; } to { --_grip: 1; } }
|
|
1214
1215
|
/* the grip as ONE LINE (`mark="line"`, Lh 2026-10-06): the single Sheet's line, at the same place and the same length. It reads the
|
|
1215
|
-
same --_grip-ink, so while its sheet reloads it changes colour exactly as the dots do.
|
|
1216
|
+
same --_grip-ink, so while its sheet reloads it changes colour exactly as the dots do. As thin as the Sheet's (--hairline-w),
|
|
1217
|
+
from the dots' top, as the Sheet's line starts there too. A bar and two round ends; the resting
|
|
1216
1218
|
ink is mixed into the card's own colour (opaque), so the ends do not show darker where they lie on the bar. */
|
|
1217
1219
|
.stack-card--line {
|
|
1218
1220
|
--_grip-w: calc(var(--sp-base) * 18);
|
|
1219
1221
|
--_grip-ink: color-mix(in srgb, currentColor 30%, var(--card-bg));
|
|
1220
1222
|
--_grip-bar: linear-gradient(var(--_grip-ink), var(--_grip-ink));
|
|
1221
|
-
--_grip-
|
|
1223
|
+
--_grip-h: var(--hairline-w);
|
|
1224
|
+
--_grip-end: calc((var(--_grip-w) - var(--_grip-h)) / 2);
|
|
1222
1225
|
background-image: var(--_grip-img), var(--_grip-bar), var(--_grip-img);
|
|
1223
|
-
background-size: var(--_grip-
|
|
1226
|
+
background-size: var(--_grip-h) var(--_grip-h), calc(var(--_grip-w) - var(--_grip-h)) var(--_grip-h), var(--_grip-h) var(--_grip-h);
|
|
1224
1227
|
background-position: calc(50% - var(--_grip-end)) var(--_grip-y), 50% var(--_grip-y), calc(50% + var(--_grip-end)) var(--_grip-y);
|
|
1225
1228
|
}
|
|
1226
1229
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -1334,10 +1337,16 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
1334
1337
|
into the stack the card colour fades in quickly (--motion-quick) and that fade ends with the
|
|
1335
1338
|
sheet's own slide (--motion-sheet, plus the same stagger), so the corner is the head colour
|
|
1336
1339
|
at the moment the sheet stops. Rising, the body is white at once. */
|
|
1340
|
+
/* the head's band is as slim as it can be (Lh 2026-10-06: 20 over · 48 head · 20 under read as a heavy bar): the white starts
|
|
1341
|
+
--sp-2 under the head, not a whole --card-gap. The body is pulled up by the difference — the card's gap is left alone, the
|
|
1342
|
+
stack's step and the body's own rows read it. */
|
|
1337
1343
|
.sheet-stack > .card.sheet--paper > .sheet__body {
|
|
1344
|
+
margin-top: calc(var(--sp-2) - var(--card-gap));
|
|
1338
1345
|
padding-top: calc(var(--sp-6) + var(--_refresh, 0px));
|
|
1339
1346
|
transition: padding-top var(--motion-sheet) ease, background-color 0s linear;
|
|
1340
1347
|
}
|
|
1348
|
+
/* a pull follows the finger at once, on paper too: the rule above is as strong as the stack's own `is-refreshing` one and comes later */
|
|
1349
|
+
.sheet-stack > .card.sheet--paper > .sheet__body.is-refreshing { transition: none; }
|
|
1341
1350
|
.sheet-stack > .card.sheet--paper:not(.is-open) > .sheet__body {
|
|
1342
1351
|
background-color: transparent;
|
|
1343
1352
|
transition:
|
|
@@ -1536,7 +1545,7 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
1536
1545
|
/* --sheet-peek is declared on the BOX the sheet slides in, not on the sheet: the words behind a peeked sheet
|
|
1537
1546
|
have to read it too (step.css keeps that much room under them), and a token only flows down. The sheet
|
|
1538
1547
|
inherits it. A sheet whose head is taller retunes it on the box. */
|
|
1539
|
-
:is(.step, .sheet-stage) { --_handle: var(--
|
|
1548
|
+
:is(.step, .sheet-stage) { --_handle: var(--hairline-w); --sheet-peek: calc(var(--card-pad-rest) + var(--sheet-head-h) + var(--card-gap-rest) + var(--safe-bottom)); } /* + the gesture bar: the peeked head stands above it. The handle sits IN the card's top padding, so the strip is that padding, the title row and the gap under it */
|
|
1540
1549
|
/* the head's floor: a tap, or an h2 line with its Thai-mark padding when the type is bigger than that (a large text-size
|
|
1541
1550
|
setting on a narrow phone) — the strip and the head read the same number, so the title row is always inside the strip */
|
|
1542
1551
|
:root { --sheet-head-h: max(var(--tap), calc(var(--fs-h2) * 1.25 + var(--sp-2))); }
|
package/dist/forms/Pin.js
CHANGED
|
@@ -79,7 +79,7 @@ export function Pin({ length = 6, value, defaultValue = '', label = word('digit'
|
|
|
79
79
|
opening). A cell that got the cursor that way with no keyboard up cannot be typed into yet — it must not look ready: no full
|
|
80
80
|
border, no caret, until a finger taps a cell, the keyboard is up, or a digit arrives. Never on a desktop (a key is at hand). */
|
|
81
81
|
const [asleep, setAsleep] = useState(false);
|
|
82
|
-
const tapped = useRef(
|
|
82
|
+
const tapped = useRef(-Infinity); // no tap yet: a script's focus in the page's first moments is still a script's
|
|
83
83
|
const keyboardUp = () => { const vv = window.visualViewport; return !!vv && window.innerHeight - vv.height > 120; };
|
|
84
84
|
const wake = () => { tapped.current = performance.now(); setAsleep(false); };
|
|
85
85
|
useEffect(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usableapp/cardds",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.61",
|
|
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.",
|