@usableapp/cardds 0.7.97 → 0.7.99
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 +23 -1
- package/bin/cardds.mjs +2 -2
- package/css/finish.css +3 -4
- package/css/palette.css +6 -8
- package/css/theme.template.css +1 -1
- package/css/tokens.css +1 -1
- package/dist/cardds.css +10 -13
- package/dist/cards/cardGrounds.js +1 -1
- package/dist/catalog.json +1 -1
- package/docs/reference.md +14 -10
- package/lint/rules.mjs +13 -1
- package/package.json +1 -1
package/docs/reference.md
CHANGED
|
@@ -575,6 +575,12 @@ between at 40% down the screen (see *Anatomy*, "Where the centre is"):
|
|
|
575
575
|
them. Seen in timebank's help-ask prototype: a Composer, a Dropdown and a
|
|
576
576
|
map on white cards inside the help sheet, the cards the colour of the
|
|
577
577
|
ground.
|
|
578
|
+
`field-off-sheet` (error) flags the same controls when their nearest
|
|
579
|
+
container in the file is a `Page`, `Pages`, `Step` or `Screen`: a form is
|
|
580
|
+
never on the ground. A form over a screen is a `Sheet` in a
|
|
581
|
+
`SheetStage over dim` (gallery `Home/AskSheet`). A bar's control is not a
|
|
582
|
+
form on the ground: a `Slider` in an `ActionBarTier`, a `Dropdown` in a
|
|
583
|
+
`FilterRow` or a `TopBar`'s actions, a `Toggle` in an `AppBar`.
|
|
578
584
|
- **Two sheet systems, one material.** *Sheet single* (`.sheet`, `sheet.css`)
|
|
579
585
|
is ONE sheet the member acts in, whatever it holds: a short entry in front
|
|
580
586
|
of a step's card, a place on a map, a payment on a dim page — in a `.step`
|
|
@@ -957,8 +963,8 @@ Rules:
|
|
|
957
963
|
- **cardds does not pick the colours; it measures two things about them.** A theme's
|
|
958
964
|
values are the project's call and the derivations are only starting points; any
|
|
959
965
|
role can be set outright. What cardds checks is that the member can see each card
|
|
960
|
-
([`cardGrounds()`](#can-the-member-see-the-card) names a tone whose fill
|
|
961
|
-
|
|
966
|
+
([`cardGrounds()`](#can-the-member-see-the-card) names a tone whose fill
|
|
967
|
+
sits under 3:1 on its ground)
|
|
962
968
|
([`inkGrounds()`](#ink-follows-its-ground) names a word or icon under 4.5:1 or 3:1).
|
|
963
969
|
Both name the tokens to move.
|
|
964
970
|
- The member's text-size setting is the same `--fs-base`, written on `<html>`
|
|
@@ -1024,10 +1030,9 @@ and with every card turned to each tone 1–5, about 27,000 pieces a pass, in `n
|
|
|
1024
1030
|
## Can the member see the card?
|
|
1025
1031
|
|
|
1026
1032
|
A card is one boundary, and a boundary the member cannot see is no boundary (WCAG 2.2 SC 1.4.11, non-text contrast: 3:1 against what is
|
|
1027
|
-
next to it). A card
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
carries it.
|
|
1033
|
+
next to it). A card stands apart from the ground it stands on by its FILL. In coloured mode and under every finish a card has no edge
|
|
1034
|
+
(`--card-border: transparent`; print and ink draw their own line as part of the finish); the wireframe keeps its black line. A card the
|
|
1035
|
+
member cannot see is answered by its fill or its ground, never by a border (Lh 2026-10-18).
|
|
1031
1036
|
|
|
1032
1037
|
Your theme decides the colours, so run the check on your theme. `cardGrounds()` builds a card of each tone (1–5) on each ground a card
|
|
1033
1038
|
stands on (the screen, a sheet's body, a `paper` sheet's body) where your theme is loaded, reads what the browser draws and returns one
|
|
@@ -1043,10 +1048,9 @@ expect(rows.filter((r) => !r.pass).map((r) => r.problem)).toEqual([]);
|
|
|
1043
1048
|
```
|
|
1044
1049
|
|
|
1045
1050
|
A failing row names the tokens and the shortfall, for example
|
|
1046
|
-
`tone 1 card on the screen: fill 1:1 (--card-1-bg #ffffff on --surface #ffffff)
|
|
1051
|
+
`tone 1 card on the screen: fill 1:1 (--card-1-bg #ffffff on --surface #ffffff); the fill needs 3:1 and is short by 2 — move --card-1-bg or --surface, never an edge`.
|
|
1047
1052
|
It reports and changes nothing: which knob you move is your call. It runs in a browser on purpose: your theme's `var()` aliases,
|
|
1048
|
-
`[data-palette]` blocks, finish and `color-mix()` are resolved by the same engine that draws the screen.
|
|
1049
|
-
same check in every finish (`tests/card-grounds.spec.js`).
|
|
1053
|
+
`[data-palette]` blocks, finish and `color-mix()` are resolved by the same engine that draws the screen.
|
|
1050
1054
|
|
|
1051
1055
|
## New palette
|
|
1052
1056
|
|
|
@@ -1080,7 +1084,7 @@ Four values, one attribute (`css/finish.css`; the header names each and its knob
|
|
|
1080
1084
|
| `sticker` | a die-cut sticker: a white cut line, a short hard drop, a lone card leans (never one in a stack, a list or a feed), buttons with a bottom edge that press down | `--sticker-cut` (5px) · `--sticker-tilt` (0.8deg; `0deg` = straight) |
|
|
1081
1085
|
| `ink` | a poster / comic print: a thick line in the surface's ink round every boundary and control, a hard offset in the same ink | `--ink-w` (2.5px) · `--ink-off` (5px) |
|
|
1082
1086
|
|
|
1083
|
-
Under every finish the
|
|
1087
|
+
Under every finish the wireframe's two borders step back (`--card-border`, `--action-border`; ink puts its own line there), a card in a closed stack's base stays flat, and the information inside a card stays flat — only a container or a control gets an edge. Colours are mixes of the roles, so a finish sits in any palette. The gallery's nav has a finish switch (key `f`); `Card · Finishes` shows the four side by side, `Home · Finish` a home under `print`.
|
|
1084
1088
|
|
|
1085
1089
|
## Scale: everything is rem
|
|
1086
1090
|
|
package/lint/rules.mjs
CHANGED
|
@@ -233,11 +233,23 @@ export function checkSource(source, file, { classes = carddsClasses() } = {}) {
|
|
|
233
233
|
const stacks = span(/<SheetStack\b(?![\w.])/g), cards = span(/<Card\b(?![\w.])/g);
|
|
234
234
|
const within = (at, el) => at > el.at && at < el.end;
|
|
235
235
|
const innermost = (at) => cards.filter((c) => within(at, c)).at(-1);
|
|
236
|
+
// a form is never on the ground (Lh 2026-10-18, timebank's ask steps on a bare Page): the control's nearest container written in this file decides.
|
|
237
|
+
// None in the file (a step component's fragment) is not judged here — the file that places it is
|
|
238
|
+
const places = [
|
|
239
|
+
...span(/<(?:Sheet|SheetBody|SheetStep|StackSheet|SheetStack)\b(?![\w.])/g).map((p) => ({ ...p, ground: false })),
|
|
240
|
+
...span(/<(?:ActionBarTier|FilterRow|TopBar|AppBar)\b(?![\w.])/g).map((p) => ({ ...p, ground: false })), // a bar's control: a Slider in a control tier, a Dropdown in a filter row or a top bar's actions, a Toggle in an app bar
|
|
241
|
+
...span(/<(?:Page|Pages|Step|Screen)\b(?![\w.])/g).map((p) => ({ ...p, ground: true })),
|
|
242
|
+
...cards.map((p) => ({ ...p, ground: false })), // a card round it is field-in-card's finding
|
|
243
|
+
].sort((a, b) => a.at - b.at);
|
|
244
|
+
const onGround = (at) => places.filter((p) => within(at, p)).at(-1)?.ground;
|
|
236
245
|
for (const c of text.matchAll(/<(Field|Composer|ComposerArea|Pin|Dropdown|Slider|Toggle|Check|ChipPick|Calendar|DayStrip|Day|Picker|Mood|AvatarPick|FileBtn|AddRow|MapPick|Tile)\b(?![\w.])/g)) {
|
|
237
246
|
const kind = c[1] === 'Tile' ? tagAt(text, c.index).match(/\s(pick|upload)\b(?!\s*=\s*\{\s*false)/)?.[1] : null;
|
|
238
247
|
if (c[1] === 'Tile' && !kind) continue; // a plain or stat Tile is read, not filled
|
|
239
248
|
const card = innermost(c.index);
|
|
240
|
-
if (!card)
|
|
249
|
+
if (!card) {
|
|
250
|
+
if (onGround(c.index)) add('field-off-sheet', 'error', c.index, `<${kind ? `Tile ${kind}` : c[1]}> on the ground: a form is never on the ground, it sits only on a sheet (Lh 2026-10-18). A Page, Pages, Step or Screen is the base, not a sheet. Put the control on a Sheet's <SheetBody>, in a <SheetStep>, or on a stack sheet — a form over a screen is a <Sheet> in a <SheetStage over dim> (Home/AskSheet).`);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
241
253
|
const stack = stacks.filter((s) => card.at >= s.body && card.at < s.end).at(-1);
|
|
242
254
|
if (stack && !cards.some((o) => o !== card && within(card.at, o) && o.at >= stack.body)) continue;
|
|
243
255
|
const name = kind ? `Tile ${kind}` : c[1];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usableapp/cardds",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.99",
|
|
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.",
|