@usableapp/cardds 0.7.45 → 0.7.46

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 CHANGED
@@ -2,6 +2,15 @@
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.46 — 2026-10-03
6
+
7
+ ### Changed
8
+ - **A larger text pulls the controls with it, half as fast** (Lh 2026-10-03): `setTextScale(percent)` now writes `--tap-base` as well as `--fs-base` — 115% text → 107.5% controls · 130% → 115% · 145% → 122.5% · 160% → 130%; at 100% and under, the controls keep the theme's size. Before, only the words grew and outgrew what holds them (a number on its round's bottom edge, a title tight in the top bar). Nothing to change in an app that calls `setTextScale`: buttons, bars, rounds and icons grow by themselves — look at a dense screen at 160%, it has less room for content than before. An app that sets `--fs-base` on `<html>` by hand gets none of this: call `setTextScale`.
9
+ - New export **`controlsFor(percent)`** — the controls' share for a text size, for an app that wants to show or store the pair.
10
+
11
+ ### Fixed
12
+ - **`SheetSteps numbered`: the number sits in the middle of its disc at every text size** — the disc is cut from its own number (`1.408em`, 24px at the default text as before) instead of a fixed 24px, and the digit is lifted onto the middle. Knobs `--sheet-step-num-size` (now listed) · `--sheet-step-num-lift`. If your theme set `--sheet-step-num-size` in rem, it still wins — but then it no longer follows the text.
13
+
5
14
  ## 0.7.45 — 2026-10-03
6
15
 
7
16
  ### Changed
package/README.md CHANGED
@@ -653,7 +653,7 @@ Rules:
653
653
  any role can be set outright.
654
654
  - The member's text-size setting is the same `--fs-base`, written on `<html>`
655
655
  at run time by `setTextScale(percent)` (a share of the theme's base; 100 = the
656
- theme's own): the words grow, the things keep their size. (`--text-scale`, which multiplied the root and zoomed the UI too, is gone.)
656
+ theme's own): the words grow, and the things grow HALF as much (`--tap-base`; `controlsFor(percent)` — 130% text → 115% controls, 160% → 130%), so a larger text still fits what holds it. (`--text-scale`, which multiplied the root and zoomed the UI too, is gone.)
657
657
 
658
658
  Try it live: the gallery's nav (`npm run dev`) has a slider per size base, and
659
659
  palette `own` shows a colour well per colour base.
@@ -684,8 +684,8 @@ default) and steps narrow phones (≤360px) to `93.75%`, which keeps the
684
684
  column, its 48px taps and its type in proportion on 320–360 screens. Only
685
685
  `--border-w`, `--rule-w` and the focus ring stay in px, so edges stay crisp.
686
686
  An app with its own text-size setting calls `setTextScale(percent)`, which writes
687
- `--fs-base` on `<html>` from the theme's base (100% = the theme's; 160% = 2.2rem by default): only the type and its holders (the count
688
- badge, the inline icon) grow; taps, spacing and radii keep their size.
687
+ `--fs-base` on `<html>` from the theme's base (100% = the theme's; 160% = 2.2rem by default): the type and its holders (the count
688
+ badge, the inline icon) grow, the controls grow half as much (`--tap-base`), spacing and radii keep their size.
689
689
  Components never write a raw length: spacing from `--sp-*`, control sizes from
690
690
  `--tap`, `--tap-lg`, `--btn-h`, `--bar-h`, `--header-h`, `--fab`, `--badge`, container
691
691
  padding from `--screen-pad` / `--card-pad`, radii from
package/css/sheet.css CHANGED
@@ -413,8 +413,10 @@
413
413
  }
414
414
  .sheet-step__title { font: var(--sheet-step-title-font, var(--type-label)); margin: 0; flex: 0 1 auto; min-width: 0; outline: none; /* the label size, not a body title: a pile of rows must stay small (Lh 2026-09-24) */ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
415
415
  .sheet-step__num { /* `numbered`: the step's number in a disc BEFORE its title (Lh 2026-09-25) — a white disc on the bar, the number in the ink */
416
- flex: none; display: grid; place-items: center; inline-size: var(--sheet-step-num-size, calc(var(--tap-base) / 2)); block-size: var(--sheet-step-num-size, calc(var(--tap-base) / 2));
417
- border-radius: 50%; font: var(--sheet-step-num-font, var(--type-caption)); font-variant-numeric: tabular-nums;
416
+ flex: none; display: grid; place-items: center; box-sizing: border-box; inline-size: var(--sheet-step-num-size, 1.408em); block-size: var(--sheet-step-num-size, 1.408em); /* em, not rem (Lh 2026-10-03, as the StackSheet's count): the disc is cut from ITS OWN number's size —
417
+ at a large text size the number grew and a 24px disc did not, so the digit sat on its bottom edge; 1.408em of a 17px caption = the 24px it always was */
418
+ padding-bottom: var(--sheet-step-num-lift, 0.1em); /* the room UNDER the number lifts it onto the disc's middle: a digit has no descender, so a centred line box sets it low */
419
+ border-radius: 50%; font: var(--sheet-step-num-font, var(--type-caption)); line-height: 1; font-variant-numeric: tabular-nums;
418
420
  background: var(--sheet-step-num-bg, var(--card-bg)); color: var(--sheet-step-num-ink, inherit);
419
421
  }
420
422
  .sheet-step__summary { color: inherit; opacity: 0.8; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
package/dist/cardds.css CHANGED
@@ -1737,8 +1737,10 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
1737
1737
  }
1738
1738
  .sheet-step__title { font: var(--sheet-step-title-font, var(--type-label)); margin: 0; flex: 0 1 auto; min-width: 0; outline: none; /* the label size, not a body title: a pile of rows must stay small (Lh 2026-09-24) */ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1739
1739
  .sheet-step__num { /* `numbered`: the step's number in a disc BEFORE its title (Lh 2026-09-25) — a white disc on the bar, the number in the ink */
1740
- flex: none; display: grid; place-items: center; inline-size: var(--sheet-step-num-size, calc(var(--tap-base) / 2)); block-size: var(--sheet-step-num-size, calc(var(--tap-base) / 2));
1741
- border-radius: 50%; font: var(--sheet-step-num-font, var(--type-caption)); font-variant-numeric: tabular-nums;
1740
+ flex: none; display: grid; place-items: center; box-sizing: border-box; inline-size: var(--sheet-step-num-size, 1.408em); block-size: var(--sheet-step-num-size, 1.408em); /* em, not rem (Lh 2026-10-03, as the StackSheet's count): the disc is cut from ITS OWN number's size —
1741
+ at a large text size the number grew and a 24px disc did not, so the digit sat on its bottom edge; 1.408em of a 17px caption = the 24px it always was */
1742
+ padding-bottom: var(--sheet-step-num-lift, 0.1em); /* the room UNDER the number lifts it onto the disc's middle: a digit has no descender, so a centred line box sets it low */
1743
+ border-radius: 50%; font: var(--sheet-step-num-font, var(--type-caption)); line-height: 1; font-variant-numeric: tabular-nums;
1742
1744
  background: var(--sheet-step-num-bg, var(--card-bg)); color: var(--sheet-step-num-ink, inherit);
1743
1745
  }
1744
1746
  .sheet-step__summary { color: inherit; opacity: 0.8; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { cx } from './cx.js';
4
4
  export * from './type/Icon.js';
5
5
  export { ICON_NAMES } from './type/icons.js';
6
6
  export * from './type/Text.js';
7
- export { setTextScale } from './type/textScale.js';
7
+ export { setTextScale, controlsFor } from './type/textScale.js';
8
8
  export { setWords, word, type WordKey } from './words.js';
9
9
  export * from './scaffold/Screen.js';
10
10
  export * from './scaffold/AppBar.js';
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ export { cx } from './cx.js';
8
8
  export * from './type/Icon.js';
9
9
  export { ICON_NAMES } from './type/icons.js';
10
10
  export * from './type/Text.js';
11
- export { setTextScale } from './type/textScale.js';
11
+ export { setTextScale, controlsFor } from './type/textScale.js';
12
12
  export { setWords, word } from './words.js';
13
13
  export * from './scaffold/Screen.js';
14
14
  export * from './scaffold/AppBar.js';
@@ -1,6 +1,14 @@
1
1
  /**
2
- * The member's text size: `--fs-base` on <html> as a share of the theme's own base (100 = as the theme set it).
3
- * Words grow, things keep their size. The base is read from the CSS (cardds's default or the project's theme.css) — never
4
- * copied into app code. Keeping the choice (localStorage, an account) is the app's.
2
+ * How much the CONTROLS grow for a text size (both a %, 100 = as the theme set it): half as fast as the words. A text-holder of
3
+ * a fixed size (a round with a number, a button, the top bar) is drawn for the theme's text — at a larger text the words outgrew
4
+ * it; growing the things at the same rate would zoom the whole UI and leave no room for content (Lh 2026-10-03, pairs set by
5
+ * measuring the gallery: 115 → 107.5 · 130 → 115 · 145 → 122.5 · 160 → 130). A smaller text never shrinks a control.
6
+ */
7
+ export declare const controlsFor: (percent: number) => number;
8
+ /**
9
+ * The member's text size: `--fs-base` on <html> as a share of the theme's own base (100 = as the theme set it), and with it
10
+ * `--tap-base` — the things grow half as much as the words (`controlsFor`), so a larger text still fits what holds it.
11
+ * The bases are read from the CSS (cardds's default or the project's theme.css) — never copied into app code. Keeping the choice
12
+ * (localStorage, an account) is the app's.
5
13
  */
6
14
  export declare function setTextScale(percent: number, root?: HTMLElement): void;
@@ -1,12 +1,25 @@
1
1
  /**
2
- * The member's text size: `--fs-base` on <html> as a share of the theme's own base (100 = as the theme set it).
3
- * Words grow, things keep their size. The base is read from the CSS (cardds's default or the project's theme.css) — never
4
- * copied into app code. Keeping the choice (localStorage, an account) is the app's.
2
+ * How much the CONTROLS grow for a text size (both a %, 100 = as the theme set it): half as fast as the words. A text-holder of
3
+ * a fixed size (a round with a number, a button, the top bar) is drawn for the theme's text — at a larger text the words outgrew
4
+ * it; growing the things at the same rate would zoom the whole UI and leave no room for content (Lh 2026-10-03, pairs set by
5
+ * measuring the gallery: 115 → 107.5 · 130 → 115 · 145 → 122.5 · 160 → 130). A smaller text never shrinks a control.
6
+ */
7
+ export const controlsFor = (percent) => 100 + Math.max(0, percent - 100) / 2;
8
+ /**
9
+ * The member's text size: `--fs-base` on <html> as a share of the theme's own base (100 = as the theme set it), and with it
10
+ * `--tap-base` — the things grow half as much as the words (`controlsFor`), so a larger text still fits what holds it.
11
+ * The bases are read from the CSS (cardds's default or the project's theme.css) — never copied into app code. Keeping the choice
12
+ * (localStorage, an account) is the app's.
5
13
  */
6
14
  export function setTextScale(percent, root = document.documentElement) {
7
15
  root.style.removeProperty('--fs-base');
16
+ root.style.removeProperty('--tap-base');
8
17
  if (percent === 100)
9
18
  return;
10
- const base = parseFloat(getComputedStyle(root).getPropertyValue('--fs-base')) || 1.375; // rem
11
- root.style.setProperty('--fs-base', `${(base * percent) / 100}rem`);
19
+ const cs = getComputedStyle(root);
20
+ const fs = parseFloat(cs.getPropertyValue('--fs-base')) || 1.375, tap = parseFloat(cs.getPropertyValue('--tap-base')) || 3; // rem
21
+ root.style.setProperty('--fs-base', `${(fs * percent) / 100}rem`);
22
+ const controls = controlsFor(percent);
23
+ if (controls !== 100)
24
+ root.style.setProperty('--tap-base', `${(tap * controls) / 100}rem`);
12
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usableapp/cardds",
3
- "version": "0.7.45",
3
+ "version": "0.7.46",
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.",