@usableapp/cardds 0.7.105 → 0.7.107
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 +134 -0
- package/bin/cardds.mjs +6 -2
- package/cardds.css +1 -0
- package/css/actions.css +16 -9
- package/css/base.css +6 -9
- package/css/card.css +21 -173
- package/css/finish.css +4 -4
- package/css/journey.css +4 -1
- package/css/layover.css +4 -14
- package/css/lists.css +3 -18
- package/css/media.css +1 -7
- package/css/parts.css +380 -0
- package/css/sheet.css +21 -140
- package/css/stack.css +15 -26
- package/css/stamp.css +1 -1
- package/css/step.css +3 -3
- package/css/theme.template.css +1 -1
- package/css/tokens.css +5 -4
- package/dist/actions/BarNote.d.ts +2 -2
- package/dist/actions/BarNote.js +2 -2
- package/dist/actions/Btn.d.ts +2 -2
- package/dist/actions/Btn.js +1 -1
- package/dist/actions/BtnRow.d.ts +1 -1
- package/dist/actions/BtnRow.js +1 -1
- package/dist/actions/Chip.d.ts +7 -3
- package/dist/actions/Chip.js +5 -5
- package/dist/actions/IconBtn.d.ts +1 -1
- package/dist/actions/IconBtn.js +1 -1
- package/dist/actions/IconBtnGroup.d.ts +1 -1
- package/dist/cardds.css +486 -410
- package/dist/cards/Card.d.ts +6 -22
- package/dist/cards/Card.js +11 -22
- package/dist/cards/CardFeed.d.ts +1 -1
- package/dist/cards/CardFeed.js +5 -5
- package/dist/cards/CardParts.d.ts +0 -12
- package/dist/cards/CardParts.js +0 -12
- package/dist/cards/cardGo.js +1 -1
- package/dist/cards/cardGrounds.js +2 -2
- package/dist/catalog.json +1 -1
- package/dist/forms/Field.d.ts +1 -1
- package/dist/forms/Field.js +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +6 -5
- package/dist/lists/Row.d.ts +7 -22
- package/dist/lists/Row.js +6 -4
- package/dist/media/MapArea.d.ts +7 -3
- package/dist/media/MapArea.js +4 -3
- package/dist/media/Tile.d.ts +3 -7
- package/dist/media/Tile.js +5 -5
- package/dist/numbers/Spinner.d.ts +1 -1
- package/dist/numbers/Spinner.js +1 -1
- package/dist/parts/Body.d.ts +7 -0
- package/dist/parts/Body.js +11 -0
- package/dist/parts/End.d.ts +10 -0
- package/dist/parts/End.js +7 -0
- package/dist/parts/Foot.d.ts +17 -0
- package/dist/parts/Foot.js +11 -0
- package/dist/parts/Head.d.ts +15 -0
- package/dist/parts/Head.js +34 -0
- package/dist/parts/Lead.d.ts +10 -0
- package/dist/parts/Lead.js +9 -0
- package/dist/parts/Words.d.ts +13 -0
- package/dist/parts/Words.js +20 -0
- package/dist/parts/headCtx.d.ts +7 -0
- package/dist/parts/headCtx.js +9 -0
- package/dist/scaffold/EmptyState.d.ts +1 -1
- package/dist/scaffold/EmptyState.js +1 -1
- package/dist/scaffold/Screen.js +1 -1
- package/dist/sheets/Modal.d.ts +3 -7
- package/dist/sheets/Modal.js +3 -7
- package/dist/sheets/Sheet.d.ts +2 -2
- package/dist/sheets/Sheet.js +8 -9
- package/dist/sheets/SheetStack.d.ts +3 -3
- package/dist/sheets/SheetStack.js +4 -4
- package/dist/sheets/SheetSteps.d.ts +1 -1
- package/dist/sheets/SheetSteps.js +2 -2
- package/dist/sheets/StackBack.d.ts +1 -1
- package/dist/sheets/StackBack.js +1 -1
- package/dist/sheets/StackSheet.js +7 -7
- package/dist/sheets/sheetMeasure.js +3 -3
- package/dist/sheets/sheetStepsPile.js +2 -2
- package/dist/sheets/stackCard.js +6 -6
- package/dist/templates/CallSheet.js +6 -5
- package/dist/templates/Walkthrough.js +3 -2
- package/docs/reference.md +75 -36
- package/lib/catalog.mjs +2 -0
- package/lib/mcp.mjs +1 -1
- package/lint/rules.mjs +22 -8
- package/package.json +2 -1
- package/scripts/codemod-parts.mjs +324 -0
- package/dist/cards/CardFoot.d.ts +0 -15
- package/dist/cards/CardFoot.js +0 -9
- package/dist/cards/CardHead.d.ts +0 -21
- package/dist/cards/CardHead.js +0 -39
- package/dist/cards/Stat.d.ts +0 -19
- package/dist/cards/Stat.js +0 -14
- package/dist/sheets/SheetBody.d.ts +0 -5
- package/dist/sheets/SheetBody.js +0 -9
- package/dist/sheets/SheetHead.d.ts +0 -15
- package/dist/sheets/SheetHead.js +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,140 @@
|
|
|
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. Each release section after 0.7.97 carries one `Components:` line, written by `node scripts/components-changed.mjs <previous tag>`: the components the release changed, or `all` when a file changed that any component can read (a token, the build), or `none`; check only the screens that import those.
|
|
4
4
|
|
|
5
|
+
## 0.7.107 — 2026-10-21
|
|
6
|
+
|
|
7
|
+
Every outer holds the same rows (Lh 2026-10-21): a `Card`, a `Sheet`, a stack sheet and a `Modal` are the paper and its behaviour, and inside each stand a `Head`, a `Body` and a `Foot`; a line is `Lead` · `Words` · `End`, the parts a `Row` and a `Card row` are both made of. Eleven parts and seven `Card` props are gone with no alias; `npx cardds codemod-parts <files>` moves a screen. Also: `Stat`, `StatRow`, `Delta` and `Tile stat` removed (a number is a `NumberBand` or a `KvCell`); the gallery's nav is one grouping by `src/` folder in a derived order; a scoped playwright run takes ports of its own.
|
|
8
|
+
|
|
9
|
+
Components: all (`css/tokens.css` lost `.delta` from its surface list; a new css file, `css/parts.css`, holds the parts and every outer's rule over them; any screen that imported a retired name fails the typecheck, see the table)
|
|
10
|
+
|
|
11
|
+
**Moving a screen.** Run the first row; it rewrites the rest. `--check` exits 1 naming each tag, prop, import or story it would still rewrite. It reads the TypeScript compiler from the project.
|
|
12
|
+
|
|
13
|
+
| before | after |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| a screen on the retired names | `npx cardds codemod-parts <files…>` (`--check` to list what is left) |
|
|
16
|
+
| `CardHead` · `SheetHead` · `Card heading caption end level` | `<Head><Words title meta level />{end}</Head>`, the first child (`SheetHead` → `Head centre`) |
|
|
17
|
+
| `SheetBody` · `ModalBody` | `<Body>` |
|
|
18
|
+
| `CardFoot` · `Card foot footLink footRound` | `<Foot link round>…</Foot>`, the last child |
|
|
19
|
+
| `RowLead` · `CardThumb` | `<Lead>` |
|
|
20
|
+
| `RowBody` · `CardBody` (in a `Card row`) | `<Words>` |
|
|
21
|
+
| `RowEnd` · `CardEnd` | `<End>` |
|
|
22
|
+
| `--card-head-*` · `--sheet-title-font` · `--sheet-sub-*` | `--head-*` · `--words-title-font` · `--words-meta-*` |
|
|
23
|
+
| `--card-foot-*` | `--foot-*` |
|
|
24
|
+
| `--row-lead-*` · `--card-thumb-*` · `--row-body-gap` · `--row-title-font` · `--row-meta-*` · `--row-end-gap` · `--card-end-gap` | `--lead-*` · `--words-gap` · `--words-title-font` · `--words-meta-*` · `--end-gap` |
|
|
25
|
+
| `.card__head` · `.sheet__head` · `.sheet__body` · `.modal__lift` · `.card__foot` · `.row__lead` · `.row__body` · `.row__end` | `.head` · `.body` · `.foot` · `.lead` · `.words` · `.end` |
|
|
26
|
+
|
|
27
|
+
The four entries on the parts under Changed below say each move in full: what it was, what governs it now, the stories that moved page, and the counts.
|
|
28
|
+
|
|
29
|
+
### Removed
|
|
30
|
+
- **`Stat`, `StatRow`, `Delta` and `Tile stat` are gone: a number is a `NumberBand` or a `KvCell`** (ruled Lh 2026-10-20, carried in 0.7.104 as "no new caller"; removed now). Before → after: a label, a big number and a caption stood in a `Stat` (a `StatRow` put a `Delta` "+7.5%" beside the label), and a value with its icon and label in a cell was a `Tile stat` → the number that is a card of its own is a `NumberBand` (`label` · `num` · `foot`); a number in a cell, alone or beside others, is a `KvCell` in a `KvGrid` (`icon` · `value` · `label`); a change beside it is words in the cell's label, not a pill. `Tile` loses `stat` and `value` (`.tile--stat`, `.tile__value`); `.stat`, `.stat--centre`, `.stat__row`, `.delta`, `.delta--neg` and the knobs `--stat-gap`, `--stat-row-gap`, `--tile-stat-gap`, `--tile-stat-min-h`, `--tile-value-font` and the eight `--delta-*` are gone (738 → 725 knobs). The root token `--neg-dark` stays (a theme may set it; nothing in cardds reads it now). A screen on the old names fails the typecheck (`Stat`, `StatRow`, `Delta` are not exported; `stat` and `value` are no props of `Tile`). Migration:
|
|
31
|
+
|
|
32
|
+
| before | after |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| `<Stat><Text level="label" muted>Today</Text><Text level="stat">6.5 h</Text></Stat>` in a card or a sheet | `<KvGrid><KvCell value="6.5 h" label="Today" /></KvGrid>` |
|
|
35
|
+
| a `Stat` that was the whole card | `<NumberBand label={<>Hours<br />given</>} num="18" foot="…" />` |
|
|
36
|
+
| `<StatRow><Text level="label">Gross revenue</Text><Delta>+7.5%</Delta></StatRow>` | `label="Gross revenue · +7.5% vs last week"` on the `KvCell` |
|
|
37
|
+
| `<Tile stat icon="droplet" value="38 %" sub="Humidity" />` | `<KvCell icon="droplet" value="38 %" label="Humidity" />` |
|
|
38
|
+
| `Stat grow` (the room beside a `Ring`) · `Stat centre` (the one number centred under an avatar) | nothing on `KvCell` or `NumberBand` does this; a screen that needs it reports the gap |
|
|
39
|
+
|
|
40
|
+
Stories gone: `Stat/*` (four) and `Tile/StatOnEachTone` (the ink check reads `Kv/KvGridKami` on every tone). Migrated to a `KvCell`: `Avatar/WithIconXL`, `BtnGroup/Week`, `Home`'s wallet tabs, `Kv/Wallet`, `Ring/Default`, `Ring/InAHead`, `Tile/Dashboard`, `Track/OnADarkCard`.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
- **One thing on a turning card's face may take the whole middle** (Lh 2026-10-21, the QR on timebank's request card: bigger, centred, the whole room). Before → after: the middle of a `Card back` face was a grid whose one row hugged its content, so a child given `height: 100%` (a QR with its caption, a code) stood at the top of an empty band, and nothing an app wrote could centre it or fill the room → the middle is a flex column of the same gap, so a child's `height: 100%` is the middle's height and it may centre or fill. Nothing for a consumer to change; a face whose middle is words stands as before (style snapshot: only the five `Card · Turns*` stories moved, and only by this). The story's back now draws the QR as a square as big as the room above its caption (`min(100%, 100cqh)` in a size container), centred. Components: Card. Stories `Card/Turns*`.
|
|
44
|
+
- **A line is made of one set of parts, `Lead` · `Words` · `End`, whether it is a `Row` or a `Card row`; the six parts each whole had of its own are gone** (Lh 2026-10-21, option A of three: the inner set is one, named without an outer prefix; the outer governs an inner's look only through the inner's knobs or a selector naming both, in the inner's file). Before → after: a row's parts were `RowLead`, `RowBody`, `RowEnd` (`.row__lead`, `.row__body` > `.row__title` · `.row__meta`, `.row__end`, lists.css) and a row card's were `CardThumb`, `CardBody`, `CardEnd` (`.card__thumb`, `.card__body`, `.card__end`, card.css), two names and two sets of knobs for one shape → the three parts live in `src/parts/` and draw `.lead`, `.words` > `.words__title` · `.words__meta`, `.end` (css/parts.css, after lists.css), the same props as before (`Lead icon`; `Words title meta`, and `level` reserved for a head's words; `End value caption`), and both wholes take them as direct children in that order: `<Row><Lead icon="gift" /><Words title="…" meta="…" /><End value="+1.0 h" caption="Tue" /></Row>`, `<Card row><Lead>01</Lead><Words><Text level="title">…</Text></Words><End>…</End></Card>`. A row card's lead keeps its 44 box in the card's ink and label type (`.card--row > .lead`, and a `FeedCard`'s icon lead the same), a row's its 48 box; the row's words keep `min-width: 0` and its end `flex: none` (`.row > .words`, `.row > .end`). No story's look moved: the style snapshot compares the computed look only now, so an element renamed (or a div that became a span) with the same values is no move, and a story shown on another page is named as a move of page. The catalog's `parts` is the folder rule, an export of `src/parts/`, and a part's `partOf` became `fits`, the wholes the stories stand it in, read from the previews (`cardds get Row` → `parts: Lead · Words · End`, `get Lead` → `fits: Card · Row`, `get End` → `Card · CardHead · Row`); `CardHead`, `CardFoot`, `SheetBody` are no parts until their PRs. The gallery has a `parts` group (End, Lead, Words, their row-card stories lifted from the Card page), and the `CardBody` page became `CardList` and `CardMedia`. Migration, run `npx cardds codemod-parts <files…>` on a screen (`--check` exits 1 naming what is left), or by hand:
|
|
45
|
+
|
|
46
|
+
| before | after |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `<RowLead icon="gift" />` | `<Lead icon="gift" />` |
|
|
49
|
+
| `<RowBody title="…" meta="…" />` · `<RowBody><Wave /></RowBody>` | `<Words title="…" meta="…" />` · `<Words><Wave /></Words>` |
|
|
50
|
+
| `<RowEnd value="+1.0 h" caption="Tue" />` | `<End value="+1.0 h" caption="Tue" />` |
|
|
51
|
+
| `<CardThumb>01</CardThumb>` in a `Card row` (or a `FeedCard`'s `icon`) | `<Lead>01</Lead>` |
|
|
52
|
+
| `<CardBody>…</CardBody>` in a `Card row` | `<Words>…</Words>` (a `CardBody` outside a `Card row` the codemod leaves and names: it was never one) |
|
|
53
|
+
| `<CardEnd>…</CardEnd>` in a row card or a head's `end` | `<End>…</End>` |
|
|
54
|
+
| `--row-lead-size` · `--row-lead-radius` · `--row-lead-border` | `--lead-size` · `--lead-radius` · `--lead-border` (and `--lead-font`, the row card's label type) |
|
|
55
|
+
| `--card-thumb-size` · `--card-thumb-radius` · `--card-thumb-font` | the `.card--row > .lead` defaults of `--lead-size` · `--lead-radius` · `--lead-font` (set the `--lead-*` knob on the list or the card) |
|
|
56
|
+
| `--row-body-gap` · `--row-title-font` | `--words-gap` · `--words-title-font` |
|
|
57
|
+
| `--row-meta-font` · `--row-meta-ink` · `--row-meta-gap` | `--words-meta-font` · `--words-meta-ink` · `--words-meta-gap` |
|
|
58
|
+
| `--row-end-gap` · `--card-end-gap` | `--end-gap` |
|
|
59
|
+
|
|
60
|
+
A screen on the old names fails the typecheck (the six are not exported). 725 → 722 knobs; 545 → 542 classes. Stories moved page, the same look: `Card/CardBodyTitleOnly` → `Words/WordsTitleOnly`, `Card/CardThumbInitialAndIcon` → `Lead/LeadInitialAndIcon`, `Card/CardEndInHead` → `End/EndInHead`, `CardListLinks` · `CardListPick` · `CardListWindow` → the `CardList` page, `CardMediaRated` · `CardMediaStrip` → the `CardMedia` page.
|
|
61
|
+
- **`Head` is the one head of a card, a sheet and a stack sheet** (Lh 2026-10-21, option A: every outer holds the same rows, a consumer changes the outer and keeps what is inside; the second of the inner parts). Before → after: a card's head was a `CardHead` (`heading` · `caption` · `end` · `level` · `top`, or children), written for you by `Card heading caption end level`, a stack sheet's head was a `CardHead` with children, and the stage sheet's was a `SheetHead` (`lead` · `title` · `sub` · `trail`), three heads for one row → one `Head` in `src/parts/` (`top`, `centre`, `long`, children): a lead (`Lead`, `StackBack`, `JourneyBadge`), the `Words` (`title`, `meta`, `level`), chips, an end (an `IconBtn`, a `Chip`, an `End`). `<Card foot={…}><Head><Words title="Sunday market" meta="Saturday" /><IconBtn sm icon="ellipsis" label="More" /></Head>…</Card>`. `Words` in a `Head` writes its title and its meta as the head's own children, flat: `h2.words__title.t-h2` (`h1` with `level="h1"`) then `span.words__meta.t-caption.t-muted`, so the caption still takes a row of its own under the title and the end. The stack's keyboard way in is kept: on the open sheet the title is a tab stop (`tabIndex` 0) and Enter or Space folds it; a title wider than its line still runs sideways once (`.is-long`, the Sheet's `text-indent`, the StackSheet's `translate`). `Card` no longer has `heading`, `caption`, `end`, `level`; it finds its `Head` child by type (a component of your own that wraps a `Head` is not found, as it was not with `CardHead`). `CardHead` and `SheetHead` are gone, no alias. `npx cardds codemod-parts <files…>` rewrites a screen (`--check` lists what still writes the old forms), and a story named `CardHeadX` or `SheetHeadX` is `HeadX`.
|
|
62
|
+
|
|
63
|
+
| before | after |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `<CardHead heading="Recent" caption={date} end={<Chip on>3 new</Chip>} />` | `<Head><Words title="Recent" meta={date} /><Chip on>3 new</Chip></Head>` |
|
|
66
|
+
| `<CardHead level="h1" heading="Welcome" top />` | `<Head top><Words title="Welcome" level="h1" /></Head>` |
|
|
67
|
+
| `<CardHead><StackBack /><Text level="h2" caps>Shopping</Text><IconRow>…</IconRow></CardHead>` | `<Head>` and `</Head>` round the same children |
|
|
68
|
+
| `<Card heading="Alone" caption="…" end={<Chip>1</Chip>} foot={…}>` | `<Card foot={…}><Head><Words title="Alone" meta="…" /><Chip>1</Chip></Head>…</Card>` |
|
|
69
|
+
| `<SheetHead lead={a} title="Create a room" sub="Settings" trail={b} />` | `<Head centre>{a}<Words title="Create a room" meta="Settings" />{b}</Head>` |
|
|
70
|
+
| `--card-head-col-gap` · `--card-head-row-gap` · `--card-head-lead-gap` · `--card-head-title-lines` | `--head-col-gap` · `--head-row-gap` · `--head-lead-gap` · `--head-title-lines` |
|
|
71
|
+
| `--sheet-title-font` · `--sheet-sub-font` · `--sheet-sub-ink` | `--words-title-font` · `--words-meta-font` · `--words-meta-ink` |
|
|
72
|
+
| `--card-head-min-h` · `--card-head-wrap` (a sheet set them on its head) | the sheet still sets them, now private to `parts.css` (`--head-min-h`, `--head-wrap`) |
|
|
73
|
+
| `.card__head`, `.card__head--top`, `.sheet__head`, `.sheet__title`, `.sheet__sub`, `.feed-card__head`, `.stack-sheet__title` | `.head`, `.head--top`, `.head--centre`, `.words__title`, `.words__meta`, `.feed-card > .head`, `.stack-sheet > .head > .words__title` |
|
|
74
|
+
|
|
75
|
+
The title's type is one knob, `--words-title-font`, which a head reads (default the level's own face) and three outers set: the stack for its one-line peek (`--fs-h1` over `--lh-solid`, or `--type-display`), a `Page` for its one `h1` (the card heading's size), and a theme anywhere; a sheet's title is the default, so a theme that set `--sheet-title-font` sets `--words-title-font` on the sheet. Every rule that names a head moved into `css/parts.css` under its outer (`.sheet-stack > .card > .head`, `.sheet > .head`, `.stack-sheet > .head`, `.card--bands > .head`, `.feed-card > .head`), so the rule-15 gate lists no override. The stack sheet's title keeps the overflow it computed (`hidden`, from the head's three-line clamp, which outranked the `overflow-x: clip` of `.stack-sheet__title` on every sheet); those two dead declarations are gone. 722 → 717 knobs and 542 → 538 classes, both re-pinned. Gallery: the pages `CardHead`, `SheetHead` and `StackHead` are one `Head` page in `parts` (the page says it fits a Card, a Sheet, a SheetStack, a Modal and a Page; `cardds get Head` prints the elements the stories stand it in directly, `fits: Card · Page · Sheet` once a modal's head stands in its Body, and a whole's `parts` list its rows first, then a line's parts); stories `CardHeadCustom`, `CardHeadTop` are `HeadCustom`, `HeadTop` (Card), `SheetHeadLeadTrail`, `SheetHeadTitleOnly` are `HeadLeadTrail`, `HeadTitleOnly` (Sheet), `LongTitle` and `StackBackRevealed` and `IconRowInRow` stand on the page unchanged, and `Picker · Words` is `Picker · WordValues` (a story named `Words` shadowed the part).
|
|
76
|
+
|
|
77
|
+
The style snapshot of the 499 stories: no element of a card, a sheet or a stack head moved (a box-for-box comparison of every element's x, y, width and height names none, and the snapshot reports no style). Six stories stand on another page with the same look (`CardHead · CardHeadCustom`, `CardHeadTop`, `IconRowInRow` and `SheetHead · LongTitle`, `StackHead · StackBackRevealed` are on `Head`; `Picker · Words` is `WordValues`). Three stories changed shape with the stage sheet's head, whose title and sub were wrapped in a `div` that `Head` does not draw: `SheetStage · Map` 36 → 35 elements, `SheetHead · SheetHeadLeadTrail` and `SheetHeadTitleOnly` are `Head · HeadLeadTrail` and `HeadTitleOnly`. In them the head is the same height (60.5 with a sub, 48 without), the buttons and the title's text do not move; the title's own box is 4.4px taller (the head's room for Thai marks, `padding-block-start` 0.2em given back by a negative margin), the sub's box is the column wide and as tall as the body's line (219 × 33 at y 484.5, against 55 × 22 at y 491.5) with its text centred on the same middle, about 1.5px higher.
|
|
78
|
+
- **`Body` is the one content row of a sheet, a stack sheet and a modal** (Lh 2026-10-21, option A: every outer holds the same rows; the third of the inner parts). Before → after: a sheet's content stood in a `SheetBody` (`.sheet__body`, the scroller) and a modal's in a `ModalBody` (`.modal__lift`), two pieces with the same job → one `Body` (`.body`, `src/parts/Body.tsx`): a grid column from the top that scrolls, governed by each outer in `css/parts.css` with the outer in the selector (`.sheet > .body` stops above the foot's strip and keeps a focused control above the cut, `.sheet-stack > .card > .body` follows the pull to refresh, `.modal > .body` is padded and shrinks under the modal's height). A `Modal` with no `Body` is still the confirm; `ModalAsk` stays one piece. Run `npx cardds codemod-parts <files>`: it renames both tags, folds their imports into one `Body`, and renames a story named `SheetBody…`.
|
|
79
|
+
|
|
80
|
+
| before | after |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| `<Sheet><Head>…</Head><SheetBody>…</SheetBody></Sheet>` | `<Sheet><Head>…</Head><Body>…</Body></Sheet>` |
|
|
83
|
+
| `<Modal open><ModalBody>…</ModalBody><ModalAsk …/></Modal>` | `<Modal open><Body>…</Body><ModalAsk …/></Modal>` |
|
|
84
|
+
| `.sheet__body`, `.modal__lift` (a theme or a test that named them) | `.body`; in one outer only: `.sheet > .body`, `.modal > .body` |
|
|
85
|
+
| (none) | `--body-gap` (the card's gap) · `--body-pad-top` (none; a paper sheet's `--sp-6`) |
|
|
86
|
+
|
|
87
|
+
A screen on the old names fails the typecheck. `cardds check` now names a control written straight in a `Sheet` or a `Modal`, outside its `Body` (`field-off-sheet`: a sheet's children are its rows); a control in its `Head` (a `Dropdown` at the head's end) stays legal, and a `Body` in a `Card` is the card's (`field-in-card`). `cardds get Sheet` lists `parts: Head · Body` and `get Modal` `Body`; `get Body` prints `fits: Modal · Sheet` and `get Head` `Card · Page · Sheet` (a modal's head stands in its Body now), the elements the stories stand each in directly, so a stack sheet's parts are its `Card`'s and `get SheetStack` lists none. 717 → 719 knobs; 538 → 537 classes (the two retired become one). The style snapshot of the 499 stories names no story that moved; one stands on another page with the same look, `SheetBody · SheetBodyScrolls` → `Body · BodyScrolls`.
|
|
88
|
+
- **`Foot` is the one foot of a card, a sheet and a stack sheet, and `Card` has no foot props** (Lh 2026-10-21, option A: every outer holds the same rows; the fourth of the inner parts). Before → after: a card's buttons stood in a `CardFoot` (`.card__foot`, `link`, `round`), or `Card foot footLink footRound` wrote one for you as its last child → one `Foot` (`.foot`, `src/parts/Foot.tsx`, the same `link` and `round`), written as the card's or the sheet's last child; `Card`'s `foot`, `footLink` and `footRound` are gone. A turning card finds its `Foot` child by type and draws it on both faces, as it did its `CardFoot`. Each outer governs the foot in `css/parts.css` under its name: `.sheet > .foot` (the layer that stands on the box's bottom edge at every state), `.sheet-stack > .card.sheet--paper > .foot` (the paper band), and `.card--bands` (one rule with the head's band now, so the twin allowance went). The data props of the templates stay: `StackSheet foot`, `Home sheets[].foot`, `CallSheet` `foot` and `footLink`, `FeedCard foot` render a `Foot`. Run `npx cardds codemod-parts <files>`: it renames `CardFoot`, writes a `Card`'s foot props as a `<Foot>` last child (a fragment's children unwrapped), drops a `footRound` that drew no foot, and renames a `CardFoot…` story.
|
|
89
|
+
|
|
90
|
+
| before | after |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| `<CardFoot><Btn>Later</Btn><Btn primary>Join</Btn></CardFoot>` | `<Foot><Btn>Later</Btn><Btn primary>Join</Btn></Foot>` |
|
|
93
|
+
| `<Card foot={<Btn primary>Offer help</Btn>} footLink={<Link sm>see all</Link>}>…</Card>` | `<Card>…<Foot link={<Link sm>see all</Link>}><Btn primary>Offer help</Btn></Foot></Card>` |
|
|
94
|
+
| `<Card footRound foot={<><IconBtn size="xl" …/><IconBtn size="xl" …/></>}>` | `<Card>…<Foot round><IconBtn size="xl" …/><IconBtn size="xl" …/></Foot></Card>` |
|
|
95
|
+
| `--card-foot-gap` · `--card-foot-ink` · `--card-foot-link-gap` | `--foot-gap` · `--foot-ink` · `--foot-link-gap` |
|
|
96
|
+
| `.card__foot`, `.card__foot--link`, `.card__foot--round`, `.card__foot-link` | `.foot`, `.foot--link`, `.foot--round`, `.foot__link` |
|
|
97
|
+
|
|
98
|
+
A screen on the old names fails the typecheck. `cardds get Card` lists `parts: Head · Foot · Lead · Words · End` and `get Sheet` `Head · Body · Foot`; `get Foot` prints `fits: Card · Sheet` (a stack sheet's foot stands in its `Card`). A `Words` in a stack sheet's head now calls a consumer's own `onKeyDown` before the fold. 719 knobs (three renamed). The style snapshot of the 499 stories names no story that moved; four stand on another page with the same look, `CardFoot · CardFootTwo`, `CardFootRound`, `CardFootWordsWide`, `CardFootFourAnswers` → `Foot · FootTwo`, `FootRound`, `FootWordsWide`, `FootFourAnswers`; one story is renamed with the same look, `IconBtnGroup · InACardFoot` → `IconBtnGroup · InAFoot`.
|
|
99
|
+
- **The migrated stories' numbers are a cell's size.** Before → after: the wallet's balance was `Text stat xl` and the others `Text stat`, each with its label above → a `KvCell` value (`--kv-cell-val-font`, h2) with its label under it. The style snapshot names the seven stories above as moved and nothing else (501 → 496 stories).
|
|
100
|
+
- **The gallery's nav: one grouping, by `src/` folder, in a derived order** (Lh 2026-10-21, chosen from a picture of three options). Before → after: the nav had three groupings behind a `catalog · frame · role` switch (kept in `localStorage`), a hand-written `NAV` of 18 groups and 107 names, and inside every group the pages stood in the `NAV` order, so the folder view interleaved a folder's pages by another grouping's index (scaffold read ActionBar, LayerHistory, TopBar, AppBar, Page, Pager, …) → the switch is gone and the nav draws Foundations, then one group a `src/` folder in alphabetical order, then `screens` last (Splash, Walkthrough, Home, Install, SignIn, SignUp, Requests in the app's order of first use, the one list left in `gallery/src/entries.ts`, then PostScreens, StampScreens, StickyScreens, StickyWelcome). Inside a folder the order is derived (`gallery/src/rank.mjs`): a part follows its whole (Card, then CardBody, CardFeed, CardFoot, CardHead; SheetStack, then StackHead, before SheetStage), everything else alphabetical. `Screen` (src/scaffold) has a page of its own under `scaffold`, so its three stories (Scrolling, Fill, Lead) are shown; its four palette stories are gone (the Foundations panel shows every palette, and a palette nested in a story failed the ink gate in dark mode); `Palette` is a link under Foundations, where its tokens are read; the `not a component` group is gone. The search matches the folder name where it matched the `NAV` group. No story's style moved (the style snapshot of 0.7.106 holds; the three Screen stories are added).
|
|
101
|
+
|
|
102
|
+
## 0.7.106 — 2026-10-21
|
|
103
|
+
|
|
104
|
+
The map edge to edge under a step's controls (`MapArea bleed`, and a step whose bleeding child reaches the sheet's edges); `Chip soft`; a card's head led by its date; `Row` in parts (`RowLead`, `RowBody`, `RowEnd`, and the props that drew them are gone); a turning two-tone card no longer cut at its edges; the catalog names a whole's parts.
|
|
105
|
+
|
|
106
|
+
Components: all (a new root token, `--accent-wash`; the gallery, the catalog build and the lint rules changed. The components a screen sees change are MapArea, SheetStep, Chip, ChipRow, CardHead, JourneyBadge, Card, Row and its parts; `Row`'s old props fail the typecheck, see its migration table)
|
|
107
|
+
|
|
108
|
+
### Added
|
|
109
|
+
- **`MapArea bleed`: with `inline`, the map edge to edge of what holds it, no corner** (Lh 2026-10-19, timebank's ask sheet, the จุดนัด step: the map under แถวบ้าน / แถวนี้ must touch the sheet's left and right edges). Before → after: a `MapArea inline` in a `SheetStep` was a rounded box inside the step's inset, and no knob could take it to the sheet's edge (`--sheet-step-inner-pad-x: 0` and `--map-radius: 0` left it inside the sheet's own 20px, cut by the fold's clip) → `<MapArea inline bleed>` gives the sheet's or the card's inset back (the same edge declaration as `.bleed`, read from `--card-pad`) and drops its corner; a card clips its corner for a first or last one as it does for a `ChipRow bleed`. Ignored without `inline`; `cardds check` warns (`map-bleed-without-inline`). Gallery `MapArea/InStep`.
|
|
110
|
+
|
|
111
|
+
- **`Chip soft`: a status to see, quieter than `on`** (Lh 2026-10-21: keep what we used, add the other style). Before → after: a status in a card's head was a plain `Chip` (an edge) or `Chip on` (the full accent); the inbox's `Ribbon` drew a third look, the accent washed in, as a separate piece → that look is `Chip soft` (`.chip--soft`: `--chip-soft-bg`, default the new token `--accent-wash`, the accent washed into the paper of fields and buttons, opaque, so its words read on every tone; `--chip-soft-ink`), and `inbox/Ribbon` is gone. `on` wins when both are set. Gallery `Chip/Soft`.
|
|
112
|
+
|
|
113
|
+
- **A card's head that leads with a date; words that lead a ChipRow** (Lh 2026-10-21, timebank's request card re-laid). Before → after: a `CardHead` put its `ChipRow` on a line of its own under the heading, and the date beside the heading → a `CardHead` whose first child is a `JourneyBadge stretch` and second a `ChipRow` stands the date at the left and the chips beside it, the date always as tall as the chips (its three-line cap lifted there; the chips are not cut at two lines there), and the heading with its caption takes the whole width under them (`--card-head-lead-gap`, `--sp-3`). `ChipRow lead` sets words before the chips ("นัดที่") in the chips' own type, at their middle (`.chip-row__lead`, `--chip-row-lead-ink`). Gallery `Card/Turns*`, `Card/PaperBands`.
|
|
114
|
+
- **The catalog names a whole's parts** (Lh 2026-10-21, modular parts). Before → after: `cardds get Row` listed what Row's source renders (`composes`) but not the exports it is built of, so a session learned of `RowLead`, `RowBody` and `RowEnd` only by reading the description → `get` prints `parts: RowBody · RowEnd · RowLead` on a whole and `part of: Row` on a part (JSON `parts`, `partOf`; MCP `get_component` the same). A part is an export named `<Whole><Part>` that draws `.whole__part`.
|
|
115
|
+
|
|
116
|
+
### Changed
|
|
117
|
+
- **`Card paper="bands"`: the heading and the words under it read as one paragraph** (Lh 2026-10-21). Before → after: the head band's lower edge had the card's padding above it and the card's gap below (20 + 16 at 375) → `--sp-2` each side (`--card-band-seam`), so only the colour divides the heading from what follows. Every `paper="bands"` card moves up by the difference.
|
|
118
|
+
- **`Chip sm`: one height wherever it stands** (Lh 2026-10-21: a foot's chip beside a head's chip read smaller). Before → after: a small chip in a card's head took the body's line height (32.6 at 375) and everywhere else the label's (27.5) → every `Chip sm` takes the body's line (`--chip-sm-line`). Every screen with a small chip outside a head grows by 5px a chip.
|
|
119
|
+
- **`Row` is composed of parts: `RowLead`, `RowBody`, `RowEnd` are children, and the props that drew them are gone** (Lh 2026-10-21: every component is broken into small parts, each its own export; the whole's single-part props are retired, not kept as shorthand). Before → after: a row was one tag whose props drew its pieces (`<Row leadIcon="gift" title="Promotions" meta="See what's available" end={<IconBtn … />} />`) → the row renders its children in order, lead · body · end (`<Row><RowLead icon="gift" /><RowBody title="Promotions" meta="See what's available" /><IconBtn … /></Row>`). The markup is the same: `.row__lead`, `.row__body`, `.row__end` and every `--row-*` knob stand as they were, and the style snapshot of the stories did not move. `lg`, `done`, `as`, `htmlFor`, `href`, `more`, `open`, `defaultOpen` and `onOpenChange` stay on `Row`. Migration, old prop → new child:
|
|
120
|
+
|
|
121
|
+
| before | after |
|
|
122
|
+
| --- | --- |
|
|
123
|
+
| `lead={<Avatar>DI</Avatar>}` | `<Avatar>DI</Avatar>` as the first child, unwrapped |
|
|
124
|
+
| `leadIcon="gift"` | `<RowLead icon="gift" />` first |
|
|
125
|
+
| `title="…" meta="…"` | `<RowBody title="…" meta="…" />` |
|
|
126
|
+
| `body={<Wave />}` | `<RowBody><Wave /></RowBody>` (with the title and meta, if any) |
|
|
127
|
+
| `endValue="+1.0 h" endCaption="Tue"` | `<RowEnd value="+1.0 h" caption="Tue" />` after the body |
|
|
128
|
+
| `end={<IconBtn … />}` | `<IconBtn … />` after the body, unwrapped; `end={<>a b</>}` gives `a b` |
|
|
129
|
+
| `children` | stay between the body and the end |
|
|
130
|
+
|
|
131
|
+
A row left on the old props fails the typecheck (`title`, `lead`, `end`… are no props of `Row`). The lint rule `row-label-button` reads the row's children now, so a button before a label row's `Check` is still caught.
|
|
132
|
+
|
|
133
|
+
### Fixed
|
|
134
|
+
- **A date at the corner of a turning card's head kept the plain badge corner.** Before → after: the concentric corner (the card's corner less its padding) reached a head that is the card's first child only, and a `Card back` face starts with its unseen turn button → the face's head is read too (21.6 at 375, was 13).
|
|
135
|
+
- **A bleeding strip inside a `SheetStep` stopped inside the sheet's inset.** Before → after: the step's body clips at its own box (the fold mechanic), and that box sat inside the sheet's padding, so a `ChipRow bleed` in a step reached the step's edge and the fold's clip cut it there → the step's body takes the sheet's inset back and pads by it again (as `.sheet__body` does), and the step's inner publishes the whole inset (the sheet's plus `--sheet-step-inner-pad-x`, which is the step's own inset beyond the sheet's) as `--card-pad`, so any child that bleeds reaches the sheet's edges; the step's head bar and its content keep their place. The knob is a length: a theme's unitless `0` still insets the step, but the sum a bleed reads is then invalid and the child stays in the inset. `Home/AskSheet`'s past-asks strip follows (the style snapshot names it).
|
|
136
|
+
|
|
137
|
+
- **A two-tone card that turns is no longer cut off at its edges while it turns** (`Card paper="bands"` with `back`; seen on `Card · TurnsRoundFoot`, and on a phone the same way). Before → after: the two-tone rule matched the turning card itself as well as its faces, so the card clipped (`overflow: hidden`) and painted the tinted middle behind the faces; as a face turned, its near edge (nearer the eye than the card, up to about 60px past the card's top and bottom at 375) was cut in a straight line at the card's box, and a pale rounded box showed behind it → the look and the clip are on the faces only, the turning box paints nothing and clips nothing. A clipping box around the card (a scrolling screen, a gallery cell) still cuts the near edge when the card is within that reach of its edge. Components: Card. Nothing for a consumer to change. tests/card-turns.spec.js.
|
|
138
|
+
|
|
5
139
|
## 0.7.105 — 2026-10-21
|
|
6
140
|
|
|
7
141
|
A card foot of big round buttons, and a card drawn as the gallery draws it.
|
package/bin/cardds.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// `npx cardds init` — set a project up the ONE way (Lh 2026-09-29): the project's theme.css, the check script, the ESLint rules.
|
|
3
3
|
// `npx cardds check [dir…]` — the rules of lint/rules.mjs over the project's source; exit 1 on an error.
|
|
4
4
|
// `npx cardds guide` — the few rules no checker sees, as text (the MCP server hands the same text over as its instructions).
|
|
5
|
+
// `npx cardds codemod-parts [--check] <files…>` — rewrite a screen from the retired parts (CardHead, SheetBody, CardFoot…) to Head · Body · Foot · Lead · Words · End.
|
|
5
6
|
// `npx cardds list | get <Name> | find [words…] [--represents a,b] [--shape s] [--interact k|none] | scaffold [id]` — the component catalog (lib/catalog.mjs) for an AI session; `npx cardds mcp` serves the same over MCP.
|
|
6
7
|
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, mkdirSync, copyFileSync } from 'node:fs';
|
|
7
8
|
import { dirname, join, relative, resolve } from 'node:path';
|
|
@@ -106,6 +107,8 @@ const asText = {
|
|
|
106
107
|
...(c.role ? [`role: represents ${[c.role.represents, c.role.count, c.role.density, c.role.job].flat().join(' · ')}${c.role.standsInFor.length ? `; stands in for: ${c.role.standsInFor.map((s) => (s.condition ? `${s.name} (${s.condition})` : s.name)).join('; ')}` : ''}`] : []),
|
|
107
108
|
...(c.composes.length ? [`composes: ${c.composes.join(' · ')}`] : []),
|
|
108
109
|
...(c.composedBy.length ? [`composed by: ${c.composedBy.join(' · ')}`] : []),
|
|
110
|
+
...(c.parts?.length ? [`parts: ${c.parts.join(' · ')} — its children, each its own export`] : []),
|
|
111
|
+
...(c.fits?.length ? [`fits: ${c.fits.join(' · ')} — the wholes it is a child of`] : []),
|
|
109
112
|
...(c.params ? ['\nparameters', ...(c.params.length ? [] : [' (none)']), ...c.params.map((p) => ` ${p.name}${p.optional && !p.default ? '?' : ''}: ${p.type}${p.default ? ` = ${p.default}` : ''}`)] : [
|
|
110
113
|
'\nprops',
|
|
111
114
|
...c.props.map((p) => ` ${p.name}${p.optional ? '?' : ''}: ${p.type}${p.slot ? ' [slot]' : ''}${p.description ? ` — ${one(p.description)}` : ''}`)]),
|
|
@@ -142,6 +145,7 @@ function ask(cmd, argv) {
|
|
|
142
145
|
return 0;
|
|
143
146
|
}
|
|
144
147
|
|
|
145
|
-
const
|
|
146
|
-
|
|
148
|
+
const codemod = (a) => import('../scripts/codemod-parts.mjs').then((m) => m.main(a), (e) => { console.error(`cardds codemod-parts: ${e.code === 'ERR_MODULE_NOT_FOUND' ? 'it reads the TypeScript compiler: install `typescript` in the project' : e.message}`); return 2; });
|
|
149
|
+
const code = cmd === 'check' ? check(args) : cmd === 'codemod-parts' ? await codemod(args) : cmd === 'init' ? init() : cmd === 'guide' ? (process.stdout.write(GUIDE), 0) : ['list', 'get', 'find', 'scaffold', 'mcp'].includes(cmd) ? await ask(cmd, args)
|
|
150
|
+
: (console.log('usage: cardds init | guide | check [dir…] | codemod-parts [--check] <files…> | list | get <Name> [--html] | find [words…] [--represents a,b] [--shape s] [--interact k|none] | scaffold [id] [--html [--css <href>]] | mcp (list get find scaffold mcp: --root <path> --json)'), cmd ? 2 : 0);
|
|
147
151
|
process.exitCode = code; // not process.exit: a big answer piped to a reader is cut off by an exit before it is flushed
|
package/cardds.css
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
@import url("css/people.css"); /* avatar, avatar stack, chooser row */
|
|
15
15
|
@import url("css/choice.css"); /* check, toggle, chip grid, days, calendar, mood, pin, composer */
|
|
16
16
|
@import url("css/lists.css"); /* row, rows, key-value, kv grid, timeline, legend, link */
|
|
17
|
+
@import url("css/parts.css"); /* the parts of a line: lead, words, end — a Row's and a row card's children */
|
|
17
18
|
@import url("css/sticky.css"); /* sticky note, its field, tone chooser, thread of posts, pile */
|
|
18
19
|
@import url("css/stamp.css"); /* stamp, empty place, album page, a stamp stuck on a surface */
|
|
19
20
|
@import url("css/post.css"); /* the post: postmark, a postcard read (letter), written (desk), kept (box) */
|
package/css/actions.css
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
/* a button may carry a WORD beside (or instead of) its icon — two named sides, ชาย · หญิง (Lh 2026-10-02): the label's look, one line */
|
|
107
107
|
.icon-btn-group > .icon-btn { display: flex; align-items: center; justify-content: center; gap: var(--sp-2); padding-inline: var(--sp-2); font: var(--type-label); font-size: var(--fs-sm); white-space: nowrap; }
|
|
108
108
|
.icon-btn-group > .icon-btn + .icon-btn { border-inline-start: var(--border-w) solid var(--icon-btn-group-rule, var(--icon-btn-group-border, var(--outline))); }
|
|
109
|
-
.
|
|
109
|
+
.foot > .icon-btn-group { flex: 1 1 0; }
|
|
110
110
|
/* --vertical: the buttons one over the other, ONE button wide — at a row's end, where a panel across would take the words' room */
|
|
111
111
|
.icon-btn-group--vertical { flex-direction: column; flex: none; width: var(--tap); }
|
|
112
112
|
.icon-btn-group--vertical > .icon-btn { flex: 1 0 auto; min-height: var(--tap); }
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
does not stretch it: a foot's `flex: 1 1 0` is undone for it below, as the foot undoes it for `.btn--form` (card.css). */
|
|
117
117
|
.icon-btn-group--form { flex: 0 1 auto; justify-self: center; margin-inline: auto; } /* no align-self: a sheet's foot stands its buttons on the bottom edge by `align-items: end` */
|
|
118
118
|
.icon-btn-group--form > .icon-btn { flex: 0 1 auto; width: auto; min-width: var(--icon-btn-group-form-min-w, var(--tap)); }
|
|
119
|
-
.
|
|
119
|
+
.foot > :is(.icon-btn-group--form, .icon-btn-line) { flex: 0 1 auto; }
|
|
120
120
|
/* --labelled: the label's words, then the panel, ONE line in the middle (the words are read, not pressed: no frame, plain ink); too narrow → the words wrap
|
|
121
121
|
above the panel, both centred */
|
|
122
122
|
.icon-btn-line { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--icon-btn-group-gap, var(--sp-3)); min-width: 0; justify-self: center; margin-inline: auto; }
|
|
@@ -196,12 +196,17 @@
|
|
|
196
196
|
.dot--error { background: var(--signal-error); }
|
|
197
197
|
.dot--info { background: var(--signal-info); }
|
|
198
198
|
/* --sm: a small LABEL (a name on a note, a tag in a tight head) — low and tight; never a tap target */
|
|
199
|
-
|
|
199
|
+
/* one height wherever it stands (Lh 2026-10-21): the body's line, so a head that cuts its words with an ellipsis keeps the Thai marks over them, and a foot's or a middle's chip reads the same */
|
|
200
|
+
.chip--sm { min-height: 0; gap: var(--chip-sm-gap, var(--sp-1)); padding: var(--chip-sm-pad-y, var(--sp-0)) var(--chip-sm-pad-x, var(--sp-2)); line-height: var(--chip-sm-line, var(--lh-body)); }
|
|
201
|
+
/* soft: the accent washed into the chip's ground, no edge — a status to see, quieter than on (was the inbox Ribbon, Lh 2026-10-21) */
|
|
202
|
+
.chip--soft { background: var(--chip-soft-bg, var(--accent-wash)); color: var(--chip-soft-ink, var(--card-ink)); border-color: transparent; } /* the wash on the chip's own paper, opaque (--accent-wash): see-through, a dark tone came through under the light side's ink (ink.spec) */
|
|
200
203
|
.chip--on { background: var(--chip-on-bg, var(--accent)); --dark: var(--accent-dark); color: var(--chip-on-ink, var(--card-ink)); border-color: transparent; }
|
|
201
204
|
/* muted: an untouched default — the words wash out, the edge stays; emphasis is the difference from the neighbours (docs/reference.md 13) */
|
|
202
205
|
.chip--muted { color: var(--chip-muted-ink, var(--card-muted)); } /* the chip's own fill's muted words: a muted chip on the dark card is still a light chip */
|
|
203
206
|
|
|
204
207
|
.chip-row { display: flex; gap: var(--sp-2); }
|
|
208
|
+
/* the words that lead the chips (ChipRow `lead`, "นัดที่" before a place, Lh 2026-10-21): the chips' own type and size, at the middle of their height */
|
|
209
|
+
.chip-row__lead { align-self: center; font: var(--type-label); font-size: var(--chip-font-size, var(--fs-sm)); color: var(--chip-row-lead-ink, inherit); }
|
|
205
210
|
.chip-row:not(.bleed) { flex-wrap: wrap; } /* a strip (.bleed, card.css) stays one line */
|
|
206
211
|
.chip-row.bleed > .chip { flex: none; white-space: nowrap; } /* a chip of the strip keeps its words on one line at its own width: the strip scrolls, a chip never shrinks to fit it */
|
|
207
212
|
|
|
@@ -362,7 +367,7 @@
|
|
|
362
367
|
|
|
363
368
|
|
|
364
369
|
/* ---- action note (Lh 2026-09-24): the main button's place, the main button's size, but ON the ground — no fill, no border, no
|
|
365
|
-
rounding — one line of muted words, an inline icon allowed; nothing to press. In a
|
|
370
|
+
rounding — one line of muted words, an inline icon allowed; nothing to press. In a Foot or an ActionBar row it takes the
|
|
366
371
|
button's share (the whole width), so a foot or a bar keeps its height whether it holds a button or the note. ---- */
|
|
367
372
|
.action-note {
|
|
368
373
|
flex: 1 1 0;
|
|
@@ -432,7 +437,7 @@
|
|
|
432
437
|
.float-bar__item, .avatar-pick__item, .add-row, .picker__item, .dropdown__btn, .appbar__who, .check, .toggle, .mood__opt, .sheet__handle,
|
|
433
438
|
a.avatar, button.avatar, .menu__item, button.snackbar__body, .stamp--tap, button.stamp-cell, button.stamp-place, .post-letter__turn, .post-desk__slot, .post-desk__pick, .post-desk__reach, .stamp-on__remove):not(.link):is(:disabled, [aria-disabled="true"]),
|
|
434
439
|
:where(.chip--pick, .tile--pick, .mood__opt, .toggle-field, label.btn):has(:disabled) { opacity: var(--off); }
|
|
435
|
-
.sheet-stack--tap > .card > .
|
|
440
|
+
.sheet-stack--tap > .card > .head > :is(h1, h2, h3):focus-visible { outline: var(--focus); outline-offset: var(--sp-1); } /* the keyboard's way into a stack sheet */
|
|
436
441
|
@media (prefers-reduced-motion: reduce) { :root { --press-scale: 1; } } /* the give goes; the dim, the shade and the focus ring stay */
|
|
437
442
|
|
|
438
443
|
/* ==== the chip a choice draws: picked (choice.css drives it with its input), and --sign (#62: a block is written in its own file) ==== */
|
|
@@ -454,12 +459,14 @@
|
|
|
454
459
|
|
|
455
460
|
/* ---- where it sits in what card.css draws (docs/reference.md rule 15) ---- */
|
|
456
461
|
/* a head's ChipRow takes a line of its own under the title: at most two lines of chips, a chip's words cut with an ellipsis */
|
|
457
|
-
.
|
|
458
|
-
.
|
|
459
|
-
.
|
|
462
|
+
.head > .chip-row { flex: 1 1 100%; order: 2; max-height: calc(2 * (var(--fs-sm) * var(--chip-sm-line, var(--lh-body)) + 2 * var(--chip-sm-pad-y, var(--sp-0)) + 2 * var(--border-w)) + var(--sp-2)); overflow: hidden; }
|
|
463
|
+
/* …beside a date that leads the head (card.css) they stand in the date's row, every chip in sight: the meeting place may take a line of its own */
|
|
464
|
+
.head:has(> .tile-badge:first-child + .chip-row) > .chip-row { grid-column: 2; grid-row: 1; max-height: none; }
|
|
465
|
+
.head > .chip-row > .chip { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
466
|
+
.foot > .btn { flex: 1 1 0; min-width: 0; }
|
|
460
467
|
/* …unless the button says its own size: `Btn form` is as wide as its words in a foot too, centred (Lh 2026-10-10: one button filling
|
|
461
468
|
a card's foot read too big — which button a card wears is the project's choice, so the foot must not undo it) */
|
|
462
|
-
.
|
|
469
|
+
.foot > .btn--form { flex: 0 1 auto; }
|
|
463
470
|
/* the page dots under the card sit centred under it — the indicator belongs
|
|
464
471
|
with the page that changes, never in the bar (Lh, 2026-09-12) */
|
|
465
472
|
.screen__centre > .pager__at { justify-self: center; }
|
package/css/base.css
CHANGED
|
@@ -133,8 +133,8 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
133
133
|
|
|
134
134
|
/* ---- typography levels ---- */
|
|
135
135
|
/* --fs-self: each level publishes its own size, for a consumer that scales a level without knowing which */
|
|
136
|
-
.t-display { font: var(--type-display); letter-spacing: var(--track-display); margin: 0; text-wrap: balance; --fs-self: var(--fs-display); }
|
|
137
|
-
.t-h1 { font: var(--type-h1); letter-spacing: var(--track-h1); margin: 0; --fs-self: var(--fs-h1); }
|
|
136
|
+
.t-display { --_type: var(--type-display); font: var(--type-display); letter-spacing: var(--track-display); margin: 0; text-wrap: balance; --fs-self: var(--fs-display); }
|
|
137
|
+
.t-h1 { --_type: var(--type-h1); font: var(--type-h1); letter-spacing: var(--track-h1); margin: 0; --fs-self: var(--fs-h1); }
|
|
138
138
|
.t-h2 { font: var(--type-h2); letter-spacing: var(--track-h2); margin: 0; --fs-self: var(--fs-h2); }
|
|
139
139
|
.t-title { font: var(--type-title); margin: 0; --fs-self: var(--fs-title); }
|
|
140
140
|
.t-body { font: var(--type-body); margin: 0; }
|
|
@@ -188,9 +188,6 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
188
188
|
.page > .t-body { color: var(--page-body-ink, var(--on-surface)); max-width: 34ch; } /* full ink: a sentence is read, muted is for meta (Lh 2026-09-22 — the words on the base were grey and hard to read) */
|
|
189
189
|
/* an illustration among the words (Lh 2026-09-22): capped, so a tall picture never pushes the words under the bar;
|
|
190
190
|
(the walk's dots are NOT here — they are the Step's, after its Pages: step.css, Lh 2026-09-22) */
|
|
191
|
-
/* the page's ONE heading on the base (a screen with no TopBar: CardHead level="h1") reads at the card heading's size —
|
|
192
|
-
h1 is the semantic level, not a bigger face; --fs-h1 is the bar title's size (Lh 2026-09-22) */
|
|
193
|
-
.page > .card__head > .t-h1 { font-size: var(--fs-h2); }
|
|
194
191
|
.page .cta-pack {
|
|
195
192
|
display: flex;
|
|
196
193
|
align-items: start; /* buttons keep their own height, never the row's */
|
|
@@ -283,12 +280,12 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
283
280
|
|
|
284
281
|
/* ---- where it sits in what card.css draws (docs/reference.md rule 15) ---- */
|
|
285
282
|
/* flat head markup (Lh 2026-09-16 — no <p>, no wrapper, only padding and gap tokens):
|
|
286
|
-
<div class="
|
|
283
|
+
<div class="head"><h2 class="words__title t-h2">…</h2><span class="words__meta t-caption t-muted">…</span><button class="icon-btn icon-btn--sm">…</button></div>
|
|
287
284
|
The heading and the far-right thing share the first row; a caption sits on
|
|
288
285
|
a row below (order 1), whatever the DOM order — so an author writes the
|
|
289
286
|
words in reading order. */
|
|
290
|
-
.
|
|
291
|
-
.
|
|
287
|
+
.head > :is(.t-caption, .t-body) { flex: 1 1 100%; order: 1; margin: 0; }
|
|
288
|
+
.head:has(> .stamp) > :is(.t-caption, .t-body) { grid-column: 1; grid-row: 2; align-self: start; }
|
|
292
289
|
/* ---- where it sits in what stack.css draws (docs/reference.md rule 15) ---- */
|
|
293
290
|
.sheet-stack__base > .screen__centre { padding-inline: 0; }
|
|
294
291
|
/* ---- where it sits in what sheet.css draws (docs/reference.md rule 15) ---- */
|
|
@@ -326,7 +323,7 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
326
323
|
the lead + the picture's own height (--page-media-h), square — so the words start where they always did */
|
|
327
324
|
.step > .pages > .page:has(> :is(img, .ph):first-child) { margin-top: 0; }
|
|
328
325
|
.step > .empty-state { flex: none; }
|
|
329
|
-
.
|
|
326
|
+
.body > .empty-state:only-child { flex: none; }
|
|
330
327
|
/* ---- where it sits in what actions.css draws (docs/reference.md rule 15) ---- */
|
|
331
328
|
/* ---- top bar: back + screen title ---- */
|
|
332
329
|
.topbar .t-h1 {
|