@usableapp/cardds 0.6.6 → 0.6.7
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 +12 -0
- package/css/step.css +9 -9
- package/dist/cardds.css +9 -9
- package/dist/scaffold/Screen.js +12 -0
- package/dist/templates/Walkthrough.d.ts +2 -2
- package/dist/templates/Walkthrough.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
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.6.7 — 2026-09-23
|
|
6
|
+
|
|
7
|
+
### A walk scrolls as one run (Lh 2026-09-23 — answers timebank #138)
|
|
8
|
+
- **`Walkthrough` has no top.** Its `Pages` start at the top edge of the step; each `Page` starts `--screen-lead` (15%) down, as
|
|
9
|
+
a **margin**. The words begin near the middle of the screen and, when they run long, scroll up to the top edge.
|
|
10
|
+
- **The picture is no longer pinned.** The picture, the heading and the words scroll up together as one run; the sticky picture
|
|
11
|
+
from 0.6.2 is gone.
|
|
12
|
+
- **Every last word can scroll clear of the bottom layer.** Each walk page ends with the lead + the bottom layer's height as
|
|
13
|
+
padding. `Screen` measures its bottom layer and publishes the height as `--bottom-h` on the screen.
|
|
14
|
+
- A walk shows no scrollbar.
|
|
15
|
+
- In a Step under a bar, the page's top margin is the screen's gap, not the 15% (it reads `--_lead`, as before).
|
|
16
|
+
|
|
5
17
|
## 0.6.6 — 2026-09-23
|
|
6
18
|
|
|
7
19
|
### BOTTOM is a layer (Lh 2026-09-23, replaces 0.6.5's "the bar is a row")
|
package/css/step.css
CHANGED
|
@@ -103,15 +103,15 @@
|
|
|
103
103
|
overscroll-behavior: contain;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
/* a
|
|
107
|
-
the picture
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
.step > .pages
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
106
|
+
/* a WALK (Pages of Page) — Lh 2026-09-23, third call: no top; the picture and the words are ONE run that scrolls up together
|
|
107
|
+
(the picture is never pinned). Each page starts at the screen's lead and ends with the same room under it — the lead as
|
|
108
|
+
padding above AND below — so the words begin near the middle and, when a big text size runs them long, scroll up clear.
|
|
109
|
+
The walk shows no scrollbar. */
|
|
110
|
+
.step > .pages { margin-top: 0; scrollbar-width: none; } /* the scrolling box starts at the step's top edge (Lh 2026-09-23) */
|
|
111
|
+
.step > .pages > .page { margin-top: var(--_lead, 0rem); } /* the lead is each PAGE's margin (15% with no top, the screen's gap under a bar): the words start there and scroll up to the box's edge */
|
|
112
|
+
.step > .pages::-webkit-scrollbar { display: none; }
|
|
113
|
+
.step > .pages > .page {
|
|
114
|
+
padding-bottom: calc(var(--screen-lead, 15cqh) + var(--bottom-h, 0rem)); /* + the bottom layer, measured by Screen: the last word scrolls clear of it */
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
/* ============================================================
|
package/dist/cardds.css
CHANGED
|
@@ -1629,15 +1629,15 @@ button { font: inherit; cursor: pointer; }
|
|
|
1629
1629
|
overscroll-behavior: contain;
|
|
1630
1630
|
}
|
|
1631
1631
|
|
|
1632
|
-
/* a
|
|
1633
|
-
the picture
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
.step > .pages
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1632
|
+
/* a WALK (Pages of Page) — Lh 2026-09-23, third call: no top; the picture and the words are ONE run that scrolls up together
|
|
1633
|
+
(the picture is never pinned). Each page starts at the screen's lead and ends with the same room under it — the lead as
|
|
1634
|
+
padding above AND below — so the words begin near the middle and, when a big text size runs them long, scroll up clear.
|
|
1635
|
+
The walk shows no scrollbar. */
|
|
1636
|
+
.step > .pages { margin-top: 0; scrollbar-width: none; } /* the scrolling box starts at the step's top edge (Lh 2026-09-23) */
|
|
1637
|
+
.step > .pages > .page { margin-top: var(--_lead, 0rem); } /* the lead is each PAGE's margin (15% with no top, the screen's gap under a bar): the words start there and scroll up to the box's edge */
|
|
1638
|
+
.step > .pages::-webkit-scrollbar { display: none; }
|
|
1639
|
+
.step > .pages > .page {
|
|
1640
|
+
padding-bottom: calc(var(--screen-lead, 15cqh) + var(--bottom-h, 0rem)); /* + the bottom layer, measured by Screen: the last word scrolls clear of it */
|
|
1641
1641
|
}
|
|
1642
1642
|
|
|
1643
1643
|
/* ============================================================
|
package/dist/scaffold/Screen.js
CHANGED
|
@@ -17,6 +17,18 @@ export function Screen({ fill, palette, as = 'div', top, bottom, className, chil
|
|
|
17
17
|
warnedSheetBar = true;
|
|
18
18
|
console.warn('cardds Screen: a bottom bar on a screen with a Sheet — the sheet finishes on its own foot (CardFoot); drop the bar.');
|
|
19
19
|
});
|
|
20
|
+
/* the BOTTOM layer's height, published on the screen as --bottom-h (Lh 2026-09-23): the walk's pages end with that much room
|
|
21
|
+
more, so every last word scrolls up clear of the layer. Measured, because the layer is as tall as its rows and the text size. */
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const el = own.current, bar = el?.querySelector(':scope > .action-bar');
|
|
24
|
+
if (!el || !bar) {
|
|
25
|
+
el?.style.removeProperty('--bottom-h');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const ro = new ResizeObserver(() => el.style.setProperty('--bottom-h', `${bar.offsetHeight}px`));
|
|
29
|
+
ro.observe(bar);
|
|
30
|
+
return () => ro.disconnect();
|
|
31
|
+
}, [bottom]);
|
|
20
32
|
const setRef = (node) => {
|
|
21
33
|
own.current = node;
|
|
22
34
|
if (typeof ref === 'function')
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
2
|
import { Screen } from '../scaffold/Screen.js';
|
|
3
3
|
export interface WalkthroughPage {
|
|
4
|
-
/** the picture that opens the page —
|
|
4
|
+
/** the picture that opens the page — it scrolls up with the words (one run) */
|
|
5
5
|
media: ReactNode;
|
|
6
6
|
/** the page's one heading (h1, no top bar on this screen) */
|
|
7
7
|
heading: ReactNode;
|
|
@@ -34,7 +34,7 @@ export interface WalkthroughProps extends Omit<ComponentProps<typeof Screen>, 'c
|
|
|
34
34
|
nextLabel?: string;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
* Walkthrough — TEMPLATE, a `Screen` with its three parts filled — top
|
|
37
|
+
* Walkthrough — TEMPLATE, a `Screen` with its three parts filled — no top · content: `Pages` (down to the screen's foot; each Page padded by the lead above and below, the whole run scrolls) · bottom: a LAYER over it — the dots, then the `ActionBar` rows.
|
|
38
38
|
* A walk of pages that tell (onboarding, an introduction). Each page = a picture, a heading,
|
|
39
39
|
* the words; the dots at the foot; one row of calls to action at the bottom. No top bar. Fixed: the order, the picture
|
|
40
40
|
* first and fixed while the words scroll, one CTA row. Yours: the pages, the row, the state.
|
|
@@ -10,7 +10,7 @@ import { CardHead } from '../cards/CardHead.js';
|
|
|
10
10
|
import { Text } from '../type/Text.js';
|
|
11
11
|
import { IconBtn } from '../actions/IconBtn.js';
|
|
12
12
|
/**
|
|
13
|
-
* Walkthrough — TEMPLATE, a `Screen` with its three parts filled — top
|
|
13
|
+
* Walkthrough — TEMPLATE, a `Screen` with its three parts filled — no top · content: `Pages` (down to the screen's foot; each Page padded by the lead above and below, the whole run scrolls) · bottom: a LAYER over it — the dots, then the `ActionBar` rows.
|
|
14
14
|
* A walk of pages that tell (onboarding, an introduction). Each page = a picture, a heading,
|
|
15
15
|
* the words; the dots at the foot; one row of calls to action at the bottom. No top bar. Fixed: the order, the picture
|
|
16
16
|
* first and fixed while the words scroll, one CTA row. Yours: the pages, the row, the state.
|
|
@@ -31,5 +31,5 @@ export function Walkthrough({ pages, at: atProp, defaultAt = 0, onAtChange, cta,
|
|
|
31
31
|
const pager = (_jsxs(_Fragment, { children: [_jsx(IconBtn, { icon: "arrow-left", label: backLabel, disabled: at === 0, onClick: () => go(at - 1) }), _jsx(IconBtn, { invert: true, icon: "arrow-right", label: nextLabel, disabled: at === count - 1, onClick: () => go(at + 1) })] }));
|
|
32
32
|
const dots = count > 1 ? _jsx(PagerAt, { at: at + 1, of: count }) : null;
|
|
33
33
|
const bottom = dots || controls.length || ctaLink != null ? (_jsxs(ActionBar, { variant: "tiers", children: [dots, controls.map((c, i) => _jsx(ActionBarTier, { children: c }, i)), _jsx(ActionBarTier, { pager: true, children: custom ? row : pager }), ctaLink != null && _jsx(ActionBarTier, { className: "action-bar__tier--link", children: ctaLink })] })) : (_jsx(ActionBar, { variant: "pager", children: custom ? row : pager }));
|
|
34
|
-
return (_jsxs(Screen, { fill: true,
|
|
34
|
+
return (_jsxs(Screen, { fill: true, bottom: bottom, ...rest, children: [_jsx(Step, { ref: step, children: _jsx(Pages, { children: pages.map((p, i) => (_jsxs(Page, { "aria-current": i === at ? 'step' : undefined, inert: i !== at || undefined, children: [p.media, _jsx(CardHead, { level: "h1", heading: p.heading }), typeof p.body === 'string' ? _jsx(Text, { level: "body", children: p.body }) : p.body] }, i))) }) }), children] }));
|
|
35
35
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usableapp/cardds",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
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.",
|