@usableapp/cardds 0.6.12 → 0.6.13

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,23 @@
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.13 — 2026-09-24
6
+
7
+ ### `CallSheet ways`: several ways in, each calling its own sheet (new)
8
+ - Before: `CallSheet` took one `action` + one `sheet`. After: it can also take `ways: [{ action, sheet }]`. Each way gets a button
9
+ sized to its words, and the buttons wrap like a `CtaPack` (the first is primary, the rest quiet). Each button brings up its own
10
+ sheet (away → full), and only one sheet is up at a time. Each sheet holds that way's WHOLE form, with its submit on `foot`.
11
+ - `open` / `defaultOpen` = the way's index, or `null` for none (`true` = the first). `onOpenChange(open, way)` gets the index as a
12
+ second argument. `action` + `sheet` still work unchanged.
13
+ - Gallery screen **SignIn**: เข้าใช้งาน with three ways (register · code · face scan).
14
+
15
+ ### `--scrim` is always black
16
+ - Before: the scrim was 50% of `--card-3-bg` (the brand), so a coloured theme dimmed in its brand colour. After: 50% black in
17
+ every palette (dim stage, the cover and postcard gradients, the gallery drawer). A project can still set `--scrim` in its theme.css.
18
+
19
+ - Gallery only: Palette and the Layout / Boxes / Keyboard switches sit above Settings, which now holds only the base sliders. The
20
+ nav widens with the text size. The Page · OneMove story is removed (the Install screen shows it).
21
+
5
22
  ## 0.6.12 — 2026-09-23
6
23
 
7
24
  - Gallery only (nothing changes in the package's components or CSS):
package/css/tokens.css CHANGED
@@ -195,7 +195,7 @@
195
195
  --ink-rail: color-mix(in srgb, currentColor 30%, transparent); /* todo steps, ghost edges */
196
196
  --accent-soft: color-mix(in srgb, var(--accent) 22%, transparent); /* calendar marks */
197
197
  --accent-mid: color-mix(in srgb, var(--accent) 50%, transparent);
198
- --scrim: color-mix(in srgb, var(--card-3-bg) 50%, transparent); /* dim stage, cover gradient */
198
+ --scrim: color-mix(in srgb, #000 50%, transparent); /* dim stage, cover gradient — ALWAYS black, never the brand (Lh 2026-09-24) */
199
199
  }
200
200
 
201
201
  /* ============================================================
package/dist/cardds.css CHANGED
@@ -236,7 +236,7 @@
236
236
  --ink-rail: color-mix(in srgb, currentColor 30%, transparent); /* todo steps, ghost edges */
237
237
  --accent-soft: color-mix(in srgb, var(--accent) 22%, transparent); /* calendar marks */
238
238
  --accent-mid: color-mix(in srgb, var(--accent) 50%, transparent);
239
- --scrim: color-mix(in srgb, var(--card-3-bg) 50%, transparent); /* dim stage, cover gradient */
239
+ --scrim: color-mix(in srgb, #000 50%, transparent); /* dim stage, cover gradient — ALWAYS black, never the brand (Lh 2026-09-24) */
240
240
  }
241
241
 
242
242
  /* ============================================================
@@ -10,6 +10,13 @@ export interface CallSheetSheet {
10
10
  /** a small link UNDER that button (a `Link sm`, e.g. details for developers) */
11
11
  footLink?: ReactNode;
12
12
  }
13
+ /** one way in: its button and the sheet it calls */
14
+ export interface CallSheetWay {
15
+ /** the button's words */
16
+ action: ReactNode;
17
+ /** what that button brings up */
18
+ sheet: CallSheetSheet;
19
+ }
13
20
  export interface CallSheetProps extends Omit<ComponentProps<typeof Screen>, 'children' | 'fill' | 'top' | 'bottom' | 'title'> {
14
21
  /** a picture above the words (optional) */
15
22
  media?: ReactNode;
@@ -17,22 +24,25 @@ export interface CallSheetProps extends Omit<ComponentProps<typeof Screen>, 'chi
17
24
  heading: ReactNode;
18
25
  /** the words: a string is one paragraph */
19
26
  body?: ReactNode;
20
- /** the button that calls the sheet */
21
- action: ReactNode;
22
- /** what comes up */
23
- sheet: CallSheetSheet;
24
- /** CONTROLLED: the sheet is up — with `onOpenChange`; or `defaultOpen` */
25
- open?: boolean;
26
- defaultOpen?: boolean;
27
- onOpenChange?: (open: boolean) => void;
28
- /** the sheet's resting states once up (default "peek full") */
27
+ /** ONE way in: the button that calls the sheet (with `sheet`) */
28
+ action?: ReactNode;
29
+ /** what that button brings up */
30
+ sheet?: CallSheetSheet;
31
+ /** SEVERAL ways in (instead of `action` + `sheet`): one button each, sized to its words, wrapping like a CtaPack (the first primary, the rest quiet), each calling its own sheet */
32
+ ways?: CallSheetWay[];
33
+ /** CONTROLLED: which way's sheet is up — an index, or null for none (`true` = the first); with `onOpenChange`; or `defaultOpen` */
34
+ open?: number | boolean | null;
35
+ defaultOpen?: number | boolean | null;
36
+ onOpenChange?: (open: boolean, way: number | null) => void;
37
+ /** the sheets' resting states once up (default "peek full") */
29
38
  states?: string;
30
39
  /** layers over the screen */
31
40
  children?: ReactNode;
32
41
  }
33
42
  /**
34
43
  * CallSheet — TEMPLATE, a `Screen` with its parts filled — no top · content: a `Step` holding ONE `Page` (picture · heading (the h1) ·
35
- * words · the button) and the `Sheet` that button calls · no bottom (the sheet finishes on its own foot). The page starts at the
36
- * screen's lead (15%). The sheet waits `away`; the button brings it up full; its handle takes it down to peek.
44
+ * words · the button, or several — `ways`) and the `Sheet` each button calls · no bottom (a sheet finishes on its own foot). The page
45
+ * starts at the screen's lead (15%). The sheets wait `away`; a button brings its own up full; the handle takes it down to peek.
46
+ * One sheet up at a time — a sheet holds that way's WHOLE form.
37
47
  */
38
- export declare function CallSheet({ media, heading, body, action, sheet, open: openProp, defaultOpen, onOpenChange, states, children, ...rest }: CallSheetProps): import("react").JSX.Element;
48
+ export declare function CallSheet({ media, heading, body, action, sheet, ways, open: openProp, defaultOpen, onOpenChange, states, children, ...rest }: CallSheetProps): import("react").JSX.Element;
@@ -9,19 +9,22 @@ import { CardHead } from '../cards/CardHead.js';
9
9
  import { CardFoot } from '../cards/CardFoot.js';
10
10
  import { Text } from '../type/Text.js';
11
11
  import { Btn } from '../actions/Btn.js';
12
+ const index = (o) => (o === true ? 0 : typeof o === 'number' ? o : null);
12
13
  /**
13
14
  * CallSheet — TEMPLATE, a `Screen` with its parts filled — no top · content: a `Step` holding ONE `Page` (picture · heading (the h1) ·
14
- * words · the button) and the `Sheet` that button calls · no bottom (the sheet finishes on its own foot). The page starts at the
15
- * screen's lead (15%). The sheet waits `away`; the button brings it up full; its handle takes it down to peek.
15
+ * words · the button, or several — `ways`) and the `Sheet` each button calls · no bottom (a sheet finishes on its own foot). The page
16
+ * starts at the screen's lead (15%). The sheets wait `away`; a button brings its own up full; the handle takes it down to peek.
17
+ * One sheet up at a time — a sheet holds that way's WHOLE form.
16
18
  */
17
- export function CallSheet({ media, heading, body, action, sheet, open: openProp, defaultOpen = false, onOpenChange, states = 'peek full', children, ...rest }) {
18
- const [own, setOwn] = useState(defaultOpen);
19
- const open = openProp ?? own;
19
+ export function CallSheet({ media, heading, body, action, sheet, ways, open: openProp, defaultOpen = null, onOpenChange, states = 'peek full', children, ...rest }) {
20
+ const list = ways ?? (sheet ? [{ action, sheet }] : []);
21
+ const [own, setOwn] = useState(index(defaultOpen));
22
+ const on = openProp === undefined ? own : index(openProp);
20
23
  const [at, setAt] = useState('full');
21
24
  const set = (next) => { if (openProp === undefined)
22
- setOwn(next); onOpenChange?.(next); };
23
- return (_jsxs(Screen, { fill: true, ...rest, children: [_jsxs(Step, { children: [_jsxs(Page, { children: [media, _jsx(CardHead, { level: "h1", heading: heading }), typeof body === 'string' ? _jsx(Text, { level: "body", children: body }) : body, _jsx(CtaPack, { children: _jsx(Btn, { primary: true, "aria-expanded": open, onClick: () => { setAt('full'); set(true); }, children: action }) })] }), _jsxs(Sheet, { state: open ? at : 'away', onStateChange: (s) => { if (s === 'away')
24
- set(false);
25
+ setOwn(next); onOpenChange?.(next !== null, next); };
26
+ return (_jsxs(Screen, { fill: true, ...rest, children: [_jsxs(Step, { children: [_jsxs(Page, { children: [media, _jsx(CardHead, { level: "h1", heading: heading }), typeof body === 'string' ? _jsx(Text, { level: "body", children: body }) : body, _jsx(CtaPack, { children: list.map((w, i) => (_jsx(Btn, { primary: i === 0, quiet: i > 0, "aria-expanded": on === i, onClick: () => { setAt('full'); set(i); }, children: w.action }, i))) })] }), list.map(({ sheet: sh }, i) => (_jsxs(Sheet, { state: on === i ? at : 'away', onStateChange: (s) => { if (s === 'away')
27
+ set(null);
25
28
  else
26
- setAt(s); }, states: states, children: [_jsx(CardHead, { heading: sheet.title }), _jsx(SheetBody, { children: open ? (typeof sheet.body === 'function' ? sheet.body() : sheet.body) : null }), (sheet.foot != null || sheet.footLink != null) && _jsx(CardFoot, { link: sheet.footLink, children: sheet.foot })] })] }), children] }));
29
+ setAt(s); }, states: states, children: [_jsx(CardHead, { heading: sh.title }), _jsx(SheetBody, { children: on === i ? (typeof sh.body === 'function' ? sh.body() : sh.body) : null }), (sh.foot != null || sh.footLink != null) && _jsx(CardFoot, { link: sh.footLink, children: sh.foot })] }, i)))] }), children] }));
27
30
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usableapp/cardds",
3
- "version": "0.6.12",
3
+ "version": "0.6.13",
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.",