@usableapp/cardds 0.7.95 → 0.7.97

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/css/tokens.css CHANGED
@@ -103,9 +103,6 @@
103
103
  --motion-quick: 0.2s; /* a small state flip that isn't a press: a chevron turning, a popover/banner opening */
104
104
  --motion-slide: 0.22s; /* a centred card sliding out and the next in (card.css) — quick, a page turn (Lh, 2026-09-12) */
105
105
  --motion-flip: 0.45s; /* a postcard turning over (media.css) — slow enough to read as a card in the hand */
106
- --dim: 0.7; /* secondary words dimmed on a ground whose muted ink does not fit (the dark card --3, a drawer, a tile's sub line): ONE share for all */
107
- --rest: 0.6; /* an unpicked choice at rest: .day, .segment__item, .float-bar__item */
108
- --faint: 0.3; /* further still: rails, far dots, unselected picker items */
109
106
  --motion-press: 0.12s; /* a control giving under the finger and springing back (actions.css PRESS) */
110
107
  --press-scale: 0.96; /* how far a finger-sized control gives — a share of its size */
111
108
  --press-dim: 0.6; /* how far a card-wide one (a row, a summary line, a card) fades under the finger */
@@ -174,40 +171,45 @@
174
171
  value. That is what the fallbacks are for — a private mix (--_*) that
175
172
  reads an unset base is invalid, so var(--_x, #grey) lands on the grey.
176
173
  Set, the roles derive: tone 2 = the brand washed into the surface, the
177
- muted inks = the ink washed into their ground. A role set directly
174
+ muted inks = the ink washed into its ground. A role set directly
178
175
  (a palette, or a project's theme.css) always wins over its derivation.
179
176
  ============================================================ */
180
- --_muted-on-surface: color-mix(in srgb, var(--color-ink) 66%, var(--color-surface, #f2f2f0));
181
- --_muted-on-paper: color-mix(in srgb, var(--color-ink) 66%, var(--color-paper, #ffffff));
182
177
  --_tone-2: color-mix(in srgb, var(--color-brand) 14%, var(--color-surface, #f2f2f0));
183
- --_muted-on-tone-2: color-mix(in srgb, var(--color-ink, #141414) 72%, var(--_tone-2));
184
- --_muted-on-brand: color-mix(in srgb, var(--color-on-brand) 70%, var(--color-brand)); /* the tone-3 card's secondary words: on-brand faded into brand — was opacity 0.7, which no theme could set (timebank #132, 2026-09-22) */
178
+ --_onlight-muted: color-mix(in srgb, var(--color-ink) 70%, var(--_tone-2));
179
+ --_ondark-muted: color-mix(in srgb, var(--color-on-brand) 70%, var(--color-brand));
180
+
181
+ /* INK: TWO SETS, ONLIGHT AND ONDARK (Lh 2026-10-18: "there are text colours ONLIGHT and ONDARK. When the ground is light, use
182
+ onlight; when the ground is dark, use ondark"). Words and glyphs alike (icons, marks, dots, a check, a knob). Each set holds its
183
+ ink and its muted shade to 4.5:1 on every ground of its side. docs/reference.md "Ink follows its ground". */
184
+ --ink-onlight: var(--color-ink, #141414);
185
+ --ink-onlight-muted: var(--_onlight-muted, #575757); /* 4.6:1 on the water note and 4.9 on tone 4's grey, the darkest light grounds */
186
+ --ink-ondark: var(--color-on-brand, #ffffff);
187
+ --ink-ondark-muted: var(--_ondark-muted, #a8a8a8); /* 4.6:1 on tone 5's grey, the lightest dark ground */
188
+
189
+ /* SIDES: every ground says whether it is dark (1) or light (0); nothing else. Its words and glyphs follow from the side
190
+ (the surface list below). Dark mode is these switches turned to 1 with darker fills, and no rule per piece. */
191
+ --surface-dark: 0;
192
+ --card-1-dark: 0; --card-2-dark: 0; --card-3-dark: 1; --card-4-dark: 0; --card-5-dark: 1;
193
+ --accent-dark: 1; /* the brand fill: a primary button, a picked chip, a picked day */
194
+ --action-dark: 0; /* the paper fill of neutral controls: a button, a chip, a field, a plain tile */
195
+ --neg-dark: 1; /* a falling Delta's fill */
185
196
 
186
197
  /* app background ("earth-toned surface or shiny color, up to the app") */
187
198
  --surface: var(--color-surface, #f2f2f0);
188
- --on-surface: var(--color-ink, #141414);
189
- --on-surface-muted: var(--_muted-on-surface, #6b6b6b);
190
199
 
191
- /* card boundaries — 3 slots so stacked/adjacent cards can differ */
192
- --card-1-bg: var(--color-paper, #ffffff); --card-1-ink: var(--color-ink, #141414);
193
- --card-2-bg: var(--_tone-2, #e6e6e3); --card-2-ink: var(--color-ink, #141414);
194
- --card-3-bg: var(--color-brand, #141414); --card-3-ink: var(--color-on-brand, #ffffff);
200
+ /* card boundaries — five tones; each one's words follow its side */
201
+ --card-1-bg: var(--color-paper, #ffffff);
202
+ --card-2-bg: var(--_tone-2, #e6e6e3);
203
+ --card-3-bg: var(--color-brand, #141414);
195
204
  /* tones 4 · 5 (Lh 2026-09-25): more card colours for a palette that has them — the wireframe keeps them grey */
196
- --card-4-bg: #d4d4d0; --card-4-ink: var(--color-ink, #141414); --card-4-muted: #555555;
197
- --card-5-bg: #3d3d3d; --card-5-ink: #ffffff; --card-5-muted: #c4c4c4;
205
+ --card-4-bg: #d4d4d0;
206
+ --card-5-bg: #3d3d3d;
198
207
 
199
- --card-border: #141414; /* wireframe: visible outline; palettes may set transparent */
200
- --card-muted: var(--_muted-on-paper, #6b6b6b); /* secondary text inside cards (the default, tone-1 card) */
201
- --card-3-muted: var(--_muted-on-brand, #b9b9b9); /* the same text on the tone-3 card — a real colour, like the two above: a theme whose brand is not near-black sets it to reach its contrast (the wireframe's #b9b9b9 = white at 0.7 on #141414, what the opacity gave) */
202
- --card-2-muted: var(--_muted-on-tone-2, #5f5f5f); /* the same text on the tone-2 card — 5.1:1 on its grey (#6b6b6b is 4.3:1, under AA);
203
- a palette whose tone-2 ground is strong
204
- sets this to its tone-2 ink — a muted shade cannot reach AA there (clay) */
208
+ --card-border: #141414; /* wireframe: visible outline; coloured mode: --on-surface-muted (palette.css). Its edge, or the fill, holds 3:1 on the ground: cardGrounds() */
205
209
 
206
210
  /* actions */
207
211
  --accent: var(--color-brand, #141414); /* primary CTA fill */
208
- --on-accent: var(--color-on-brand, #ffffff);
209
212
  --action-bg: var(--color-paper, #ffffff); /* neutral buttons/chips/inputs */
210
- --action-ink: var(--color-ink, #141414);
211
213
  --action-border: #141414;
212
214
 
213
215
  /* signals (chip dots, deltas) */
@@ -218,12 +220,15 @@
218
220
  /* THE SIGNAL SET (Lh 2026-09-25; the standard, Lh 2026-10-02): ok (green) · warn (yellow) · error (red) · info (blue) — the same four
219
221
  meanings in every project, wireframe included; a theme may retune the shade, never the meaning. Each is dark enough for words and
220
222
  edges and comes with an icon and words, never the colour alone. `--signal-*-soft` (below :root) = its light ground. */
221
- --signal-warn: #8a6d00;
222
- --signal-ok: #2e7d32;
223
- --signal-info: #2f5f9e;
223
+ --signal-warn-onlight: #705903; /* each onlight shade 4.5:1 on every light ground, tone 4's grey the darkest (#7f6400 was 3.8 there) */
224
+ --signal-ok-onlight: #27692a;
225
+ --signal-info-onlight: #2e5c98;
224
226
  /* highlights (Lh 2026-09-25): four atmosphere colours a palette may set for decoration — a count, a mark, a chart dot; the wireframe keeps them grey */
225
227
  --highlight-1: #3d3d3d; --highlight-2: #8a8a8a; --highlight-3: #5f5f5f; --highlight-4: #b0b0b0;
226
- --signal-error: #c62828; /* something went wrong — a field's edge, the words that say what */
228
+ --signal-error-onlight: #af2525; /* something went wrong — a field's edge, the words that say what */
229
+ /* on a dark ground no shade of one hue holds 4.5:1 on every palette's dark fill and stays itself: a signal there is the ondark ink,
230
+ and the icon and the words carry the meaning. A palette may give its own (orchard) */
231
+ --signal-ok-ondark: var(--ink-ondark); --signal-warn-ondark: var(--ink-ondark); --signal-error-ondark: var(--ink-ondark); --signal-info-ondark: var(--ink-ondark);
227
232
 
228
233
  /* derived tints — read the element's own ink, so they work on any slot */
229
234
  --outline: var(--action-border); /* control edges (palette.css softens) */
@@ -252,14 +257,43 @@
252
257
  bars take over the page when the app runs edge to edge (viewport-fit=cover: Android Chrome, an iPhone home-screen app).
253
258
  PUBLISHED: backgrounds still run to the edge; what the member reads or taps stands clear of them. 0 without cover.
254
259
  --_safe-b-open = the bottom inset the keyboard does NOT already cover (a keyboard up hides the gesture bar). */
255
- /* a signal's SOFT ground: the signal washed 14% into the surface (tone 2's formula) — what a Snackbar stands on. Re-derived where a
256
- palette is set, so a palette's own signal shade gives its own soft */
257
- :root, [data-palette] {
258
- --signal-ok-soft: color-mix(in srgb, var(--signal-ok) 14%, var(--surface));
259
- --signal-warn-soft: color-mix(in srgb, var(--signal-warn) 14%, var(--surface));
260
- --signal-error-soft: color-mix(in srgb, var(--signal-error) 14%, var(--surface));
261
- --signal-info-soft: color-mix(in srgb, var(--signal-info) 14%, var(--surface));
260
+ /* THE ROLES OF THE SCREEN AND OF THE PAPER CONTROLS, from their sides. Re-derived wherever a palette or a mode is set, since one may
261
+ sit on <body>: a custom property is resolved where it is declared. A signal's SOFT ground (what a Snackbar stands on) is its
262
+ onlight shade washed 14% into the surface (tone 2's formula) */
263
+ :root, [data-palette], [data-mode] {
264
+ --on-surface: color-mix(in srgb, var(--ink-ondark) calc(var(--surface-dark) * 100%), var(--ink-onlight));
265
+ --on-surface-muted: color-mix(in srgb, var(--ink-ondark-muted) calc(var(--surface-dark) * 100%), var(--ink-onlight-muted));
266
+ --action-ink: color-mix(in srgb, var(--ink-ondark) calc(var(--action-dark) * 100%), var(--ink-onlight));
267
+ --action-muted: color-mix(in srgb, var(--ink-ondark-muted) calc(var(--action-dark) * 100%), var(--ink-onlight-muted));
268
+ /* the brand as a glyph on the paper (a typed PIN digit, a map's place mark): the brand on a light paper, ondark on a dark one. It stays
269
+ the paper's on a brand card, where --accent turns to the card's ink */
270
+ --action-accent: color-mix(in srgb, var(--ink-ondark) calc(var(--action-dark) * 100%), var(--accent));
271
+ --signal-ok-soft: color-mix(in srgb, var(--signal-ok-onlight) 14%, var(--surface));
272
+ --signal-warn-soft: color-mix(in srgb, var(--signal-warn-onlight) 14%, var(--surface));
273
+ --signal-error-soft: color-mix(in srgb, var(--signal-error-onlight) 14%, var(--surface));
274
+ --signal-info-soft: color-mix(in srgb, var(--signal-info-onlight) 14%, var(--surface));
262
275
  }
276
+ /* INK FOLLOWS ITS GROUND (Lh 2026-10-18: "When the ground is light, use onlight; when the ground is dark, use ondark"). A surface
277
+ says only which side it is, `--dark: 0` (light) or `1` (dark), from its fill's side token above; it does so in its own file
278
+ (card.css, media.css…) and is named in this list, which gives it the inks every piece on it reads: --card-ink (words, icons,
279
+ marks, dots: currentColor), --card-muted (secondary words), the four signals, --on-accent (the ink on the accent fill, whose
280
+ side is --accent-dark) and --accent-ink (the brand as a glyph). A piece with no fill of its own reads only these, so a dark
281
+ surface turns everything on it to ondark with no rule per piece. A piece with no fill that stands in for a surface (a stat
282
+ tile) takes its ground's side: `--dark: inherit`. inkGrounds() measures it; docs/reference.md "Ink follows its ground" */
283
+ :where(body, [data-palette], [data-mode], .card, .tile, .modal__drawer, .postcard__front, .postcard__back, .sticky, .post-paper,
284
+ .float-bar__pill, .snackbar__body, .delta, .track, .tile-badge, .avatar, .bubble__body, .map__hint, .sheet--paper > .sheet__body,
285
+ .postcard__band, .track__step, .toggle, .chip) {
286
+ --card-ink: color-mix(in srgb, var(--ink-ondark) calc(var(--dark) * 100%), var(--ink-onlight));
287
+ --card-muted: color-mix(in srgb, var(--ink-ondark-muted) calc(var(--dark) * 100%), var(--ink-onlight-muted));
288
+ --on-accent: color-mix(in srgb, var(--ink-ondark) calc(var(--accent-dark) * 100%), var(--ink-onlight));
289
+ --accent-ink: color-mix(in srgb, var(--ink-ondark) calc(var(--dark) * 100%), var(--accent));
290
+ --signal-ok: color-mix(in srgb, var(--signal-ok-ondark) calc(var(--dark) * 100%), var(--signal-ok-onlight));
291
+ --signal-warn: color-mix(in srgb, var(--signal-warn-ondark) calc(var(--dark) * 100%), var(--signal-warn-onlight));
292
+ --signal-error: color-mix(in srgb, var(--signal-error-ondark) calc(var(--dark) * 100%), var(--signal-error-onlight));
293
+ --signal-info: color-mix(in srgb, var(--signal-info-ondark) calc(var(--dark) * 100%), var(--signal-info-onlight));
294
+ }
295
+ :where(body, [data-palette], [data-mode]) { --dark: var(--surface-dark); }
296
+
263
297
  :root { --safe-top: calc(env(safe-area-inset-top, 0px) + var(--vv-top, 0px)); /* + the phone's pan while a keyboard is up (cardds.js) */ --safe-bottom: env(safe-area-inset-bottom, 0px); }
264
298
  * { --_safe-b-open: max(0px, var(--safe-bottom) - var(--kb, 0px)); }
265
299
 
@@ -3,7 +3,7 @@ import { type DotTone } from './Dot.js';
3
3
  export interface ChipProps extends ComponentProps<'span'> {
4
4
  /** filled accent: the selected / live state */
5
5
  on?: boolean;
6
- /** quiet: an untouched default value — muted words, the thin edge, nothing to find the eye (README rule 13) */
6
+ /** quiet: an untouched default value — muted words, the thin edge, nothing to find the eye (docs/reference.md rule 13) */
7
7
  muted?: boolean;
8
8
  /** a leading signal dot: `a` (the accent signal), `b` (the secondary), or one of the signal set — ok · warn · error · info */
9
9
  dot?: 'a' | 'b' | DotTone;
@@ -13,7 +13,7 @@ export interface DropdownProps extends Omit<ComponentProps<'div'>, 'onChange' |
13
13
  label?: ReactNode;
14
14
  /** right-aligned trigger: the panel grows leftwards (in TopBar actions) */
15
15
  end?: boolean;
16
- /** quiet: the value is still the default — muted words; drop it once the member picks (README rule 13) */
16
+ /** quiet: the value is still the default — muted words; drop it once the member picks (docs/reference.md rule 13) */
17
17
  muted?: boolean;
18
18
  /** MenuItems, each with a `value` */
19
19
  children?: ReactNode;