@usableapp/cardds 0.1.7 → 0.2.1
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/README.md +114 -40
- package/cardds.js +62 -4
- package/css/actions.css +8 -0
- package/css/card.css +9 -3
- package/css/layover.css +0 -16
- package/css/lists.css +50 -0
- package/css/palette.css +5 -0
- package/css/sheet.css +38 -0
- package/css/step.css +20 -5
- package/css/theme.template.css +49 -0
- package/css/tokens.css +100 -69
- package/dist/actions/Chip.d.ts +1 -3
- package/dist/actions/Chip.js +2 -2
- package/dist/cardds.css +230 -93
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lists/Bubble.d.ts +18 -0
- package/dist/lists/Bubble.js +13 -0
- package/dist/scaffold/BaseContent.d.ts +5 -2
- package/dist/scaffold/BaseContent.js +5 -2
- package/dist/scaffold/Centre.d.ts +4 -2
- package/dist/scaffold/Centre.js +4 -2
- package/dist/sheets/Sheet.d.ts +7 -4
- package/dist/sheets/Sheet.js +6 -3
- package/package.json +1 -2
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
cardds/theme.template.css — A PROJECT'S THEME. Copy, rename, retune.
|
|
3
|
+
|
|
4
|
+
Not part of the bundle: copy this file into the project as its own
|
|
5
|
+
`theme.css` and load it AFTER cardds.css. It is the whole public
|
|
6
|
+
surface of the system — the four size bases and the colour roles.
|
|
7
|
+
Everything else in tokens.css is derived from these; a project never
|
|
8
|
+
sets a derived token (--sp-4, --fs-h1, --r-card, --tap, --sheet-*…)
|
|
9
|
+
and never a multiplier.
|
|
10
|
+
|
|
11
|
+
The values below are the defaults (the wireframe): as shipped, this
|
|
12
|
+
file changes nothing (tests/tokens.spec.js holds it to that).
|
|
13
|
+
|
|
14
|
+
On :root only. The size tokens are computed where tokens.css declares
|
|
15
|
+
them (:root), so a base set on a subtree does not reach them.
|
|
16
|
+
A stock palette's colours and this file's have the same weight — the
|
|
17
|
+
later file wins, so: after cardds.css.
|
|
18
|
+
============================================================ */
|
|
19
|
+
|
|
20
|
+
:root {
|
|
21
|
+
/* ---- size: four bases, the multipliers stay the system's ---- */
|
|
22
|
+
--sp-base: 0.25rem; /* 4 the room BETWEEN things: every --sp-N = base × N, so paddings and gaps */
|
|
23
|
+
--fs-base: 1rem; /* 16 the type: every --fs-*, the count badge, the inline icon */
|
|
24
|
+
--r-base: 1rem; /* 16 the corners: every --r-* (0 = square; chips and buttons stay fully round) */
|
|
25
|
+
--tap-base: 3rem; /* 48 the size of THINGS: touch targets, control heights, icons, avatars, ring, tiles
|
|
26
|
+
(a touch target never goes under 44px, whatever this says) */
|
|
27
|
+
/* the whole system at once (a member's text-size setting) is --text-scale, a unitless number — not a theme's job */
|
|
28
|
+
|
|
29
|
+
/* ---- faces ---- */
|
|
30
|
+
--font-ui: "PK Nonthaburi", -apple-system, system-ui, sans-serif;
|
|
31
|
+
--font-display: "FC Pride", var(--font-ui);
|
|
32
|
+
|
|
33
|
+
/* ---- colour: five bases, the roles derive (tone 2, the muted inks, the tints) ----
|
|
34
|
+
No default — unset = the wireframe. With colours of your own, put the page in coloured mode:
|
|
35
|
+
<html data-palette="own"> (any value no stock palette uses): cards take a shadow for their
|
|
36
|
+
wireframe border, controls a soft edge. */
|
|
37
|
+
/* --color-surface: #f9e8dc; */ /* the app's ground */
|
|
38
|
+
/* --color-ink: #241f1b; */ /* the words */
|
|
39
|
+
/* --color-paper: #ffffff; */ /* the plain card, neutral buttons and fields */
|
|
40
|
+
/* --color-brand: #ef4e0b; */ /* the primary action, the strong card */
|
|
41
|
+
/* --color-on-brand: #fff4ec; */ /* the words on the brand */
|
|
42
|
+
|
|
43
|
+
/* ---- colour roles: only where a derivation is not what you want — a role set here wins over it ----
|
|
44
|
+
--surface --on-surface --on-surface-muted
|
|
45
|
+
--card-1-bg --card-1-ink --card-2-bg --card-2-ink --card-3-bg --card-3-ink (three card tones)
|
|
46
|
+
--card-border --card-muted --card-2-muted
|
|
47
|
+
--accent --on-accent --action-bg --action-ink --action-border
|
|
48
|
+
--pos --neg --dot-a --dot-b */
|
|
49
|
+
}
|
package/css/tokens.css
CHANGED
|
@@ -15,56 +15,69 @@
|
|
|
15
15
|
--screen-w: 25rem; /* 400: mobile column — .screen, .action-bar, .sheet-stage */
|
|
16
16
|
--screen-centre: 40%; /* the human centre of a screen: the middle of its top four fifths — the bottom fifth is the thumb's (Lh, 2026-09-10). .card--centre sits here */
|
|
17
17
|
|
|
18
|
-
/* ----
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
--sp-
|
|
23
|
-
--
|
|
24
|
-
--
|
|
25
|
-
--
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
/* ---- the four bases: what a project retunes (Lh, 2026-09-20) ----
|
|
19
|
+
Every size token below is multiplier × its family's base. A project sets a BASE
|
|
20
|
+
and never a multiplier, so the proportions of the system hold at any size.
|
|
21
|
+
The px in the comments are at these defaults (1rem = 16px). */
|
|
22
|
+
--sp-base: 0.25rem; /* 4 spacing: --sp-N = base × N */
|
|
23
|
+
--fs-base: 1rem; /* 16 type: --fs-* */
|
|
24
|
+
--r-base: 1rem; /* 16 radius: --r-* (--r-chip stays fully round) */
|
|
25
|
+
--tap-base: 3rem; /* 48 the size of THINGS: touch targets and control heights (--tap*, --btn-h, --chip-h, --bar-h,
|
|
26
|
+
--header-h, --fab), icons, avatars, dots, the ring and the tiles. --sp-base is the room BETWEEN things.
|
|
27
|
+
Text-holders follow the type instead: --badge and --icon-xs (inline with captions) are on --fs-base.
|
|
28
|
+
Not on a base: --screen-w (the column), borders / rules / focus (px, crisp), shadows, motion. */
|
|
29
|
+
|
|
30
|
+
/* ---- spacing (4pt grid): the number in the name is the multiplier ---- */
|
|
31
|
+
--sp-0: calc(var(--sp-base) * 0.5); /* 2 hairline gaps (title→meta) */
|
|
32
|
+
--sp-1: var(--sp-base); /* 4 */
|
|
33
|
+
--sp-2: calc(var(--sp-base) * 2); /* 8 */
|
|
34
|
+
--sp-3: calc(var(--sp-base) * 3); /* 12 */
|
|
35
|
+
--sp-4: calc(var(--sp-base) * 4); /* 16 */
|
|
36
|
+
--sp-5: calc(var(--sp-base) * 5); /* 20 */
|
|
37
|
+
--sp-6: calc(var(--sp-base) * 6); /* 24 */
|
|
38
|
+
--sp-8: calc(var(--sp-base) * 8); /* 32 */
|
|
39
|
+
--sp-10: calc(var(--sp-base) * 10); /* 40 */
|
|
40
|
+
--sp-12: calc(var(--sp-base) * 12); /* 48 */
|
|
29
41
|
|
|
30
42
|
/* ---- touch & control sizes ---- */
|
|
31
|
-
--tap:
|
|
32
|
-
--tap
|
|
33
|
-
--tap-
|
|
34
|
-
--
|
|
35
|
-
--btn-
|
|
36
|
-
--
|
|
37
|
-
--
|
|
38
|
-
--
|
|
43
|
+
--tap-floor: 2.75rem; /* 44 the HIG floor — no --tap-base takes a touch target under it */
|
|
44
|
+
--tap: max(var(--tap-floor), var(--tap-base)); /* 48 primary touch target */
|
|
45
|
+
--tap-sm: max(var(--tap-floor), calc(var(--tap-base) * 11 / 12)); /* 44 minimum touch target */
|
|
46
|
+
--tap-lg: max(var(--tap-floor), calc(var(--tap-base) * 7 / 6)); /* 56 hero controls: track steps, send, field with action */
|
|
47
|
+
--btn-h: calc(var(--tap-base) * 13 / 12); /* 52 button height */
|
|
48
|
+
--btn-xl-h: calc(var(--tap-base) * 11 / 6); /* 88 the one giant CTA */
|
|
49
|
+
--chip-h: calc(var(--tap-base) * 19 / 24); /* 38 chip height */
|
|
50
|
+
--bar-h: calc(var(--tap-base) * 4 / 3); /* 64 float bar, day cell, deck actions */
|
|
51
|
+
--header-h: calc(var(--tap-base) * 5 / 4); /* 60 top bar — .topbar and .appbar alike */
|
|
39
52
|
--screen-pad: var(--sp-4); /* 16 the screen's inset — .sheet-stack cancels it */
|
|
40
|
-
--map-ring:
|
|
41
|
-
--fab:
|
|
42
|
-
--badge: 1.
|
|
43
|
-
--dot:
|
|
44
|
-
--dot-xs:
|
|
53
|
+
--map-ring: calc(var(--tap-base) * 10 / 3); /* the rough-area ring on a map (sheet.css .map__ring) — a neighbourhood, not a house */
|
|
54
|
+
--fab: calc(var(--tap-base) * 3 / 2); /* 72 square floating action */
|
|
55
|
+
--badge: calc(var(--fs-base) * 1.625); /* 26 count badge */
|
|
56
|
+
--dot: calc(var(--tap-base) * 5 / 24); /* 10 signal dot */
|
|
57
|
+
--dot-xs: calc(var(--tap-base) / 8); /* 6 marker dot */
|
|
45
58
|
|
|
46
59
|
/* ---- icons (icons.svg sprite, Lucide) ---- */
|
|
47
|
-
--icon:
|
|
48
|
-
--icon-sm:
|
|
49
|
-
--icon-lg:
|
|
50
|
-
--icon-xs:
|
|
60
|
+
--icon: calc(var(--tap-base) * 7 / 12); /* 28 default */
|
|
61
|
+
--icon-sm: calc(var(--tap-base) * 7 / 12); /* one size everywhere; retune if small contexts appear */
|
|
62
|
+
--icon-lg: calc(var(--tap-base) * 2 / 3); /* 32 empty states */
|
|
63
|
+
--icon-xs: var(--fs-base); /* 16 inline with captions/chips only (row meta, link arrows) */
|
|
51
64
|
|
|
52
65
|
/* ---- people & big elements ---- */
|
|
53
|
-
--avatar-sm:
|
|
54
|
-
--avatar:
|
|
55
|
-
--avatar-lg:
|
|
56
|
-
--avatar-xl:
|
|
57
|
-
--ring:
|
|
58
|
-
--ring-w:
|
|
59
|
-
--tile-min:
|
|
60
|
-
--tile-h:
|
|
66
|
+
--avatar-sm: calc(var(--tap-base) * 5 / 6); /* 40 row lead */
|
|
67
|
+
--avatar: calc(var(--tap-base) * 7 / 6); /* 56 card head, person row */
|
|
68
|
+
--avatar-lg: calc(var(--tap-base) * 5 / 3); /* 80 chooser row */
|
|
69
|
+
--avatar-xl: calc(var(--tap-base) * 2); /* 96 sheet head icon ring */
|
|
70
|
+
--ring: calc(var(--tap-base) * 11 / 3); /* 176 .ring gauge diameter */
|
|
71
|
+
--ring-w: calc(var(--tap-base) * 11 / 24); /* 22 .ring stroke */
|
|
72
|
+
--tile-min: calc(var(--tap-base) * 5 / 2); /* 120 .tile-grid column floor */
|
|
73
|
+
--tile-h: calc(var(--tap-base) * 11 / 4); /* 132 tile / band height */
|
|
61
74
|
|
|
62
75
|
/* ---- radius ---- */
|
|
63
76
|
--r-chip: 999px; /* pills, chips, buttons — always fully round */
|
|
64
|
-
--r-card:
|
|
65
|
-
--r-media:
|
|
66
|
-
--r-control: 0.
|
|
67
|
-
--r-badge: 0.
|
|
77
|
+
--r-card: calc(var(--r-base) * 2); /* 32 the one card radius: every card, row, tile, menu, sheet, fab */
|
|
78
|
+
--r-media: var(--r-base); /* 16 images inside cards */
|
|
79
|
+
--r-control: calc(var(--r-base) * 0.875); /* 14 fields, thumbs, menu rows */
|
|
80
|
+
--r-badge: calc(var(--r-base) * 0.625); /* 10 tile badge, bars */
|
|
68
81
|
|
|
69
82
|
/* ---- borders / rules / elevation (px on purpose: crisp at any scale) ---- */
|
|
70
83
|
--border-w: 1.5px;
|
|
@@ -85,22 +98,22 @@
|
|
|
85
98
|
--font-display: "FC Pride", var(--font-ui); /* the character face for headings and big numbers (fonts.css) */
|
|
86
99
|
--font-mono: "SF Mono", "JetBrains Mono", ui-monospace, monospace;
|
|
87
100
|
|
|
88
|
-
--fs-xs: 0.
|
|
89
|
-
--fs-caption: 0.
|
|
90
|
-
--fs-label: 0.
|
|
91
|
-
--fs-sm: 0.
|
|
92
|
-
--fs-body: 0.
|
|
93
|
-
--fs-md:
|
|
94
|
-
--fs-title: 1.
|
|
95
|
-
--fs-lg: 1.
|
|
96
|
-
--fs-h2: 1.
|
|
97
|
-
--fs-2xl: 1.
|
|
98
|
-
--fs-h1: 1.
|
|
99
|
-
--fs-3xl:
|
|
100
|
-
--fs-display: clamp(2.
|
|
101
|
-
--fs-stat: clamp(1.
|
|
102
|
-
--fs-hero: 3.
|
|
103
|
-
--fs-giant: clamp(
|
|
101
|
+
--fs-xs: calc(var(--fs-base) * 0.6875); /* 11 overline */
|
|
102
|
+
--fs-caption: calc(var(--fs-base) * 0.75); /* 12 */
|
|
103
|
+
--fs-label: calc(var(--fs-base) * 0.8125); /* 13 */
|
|
104
|
+
--fs-sm: calc(var(--fs-base) * 0.875); /* 14 chips, segments */
|
|
105
|
+
--fs-body: calc(var(--fs-base) * 0.9375); /* 15 */
|
|
106
|
+
--fs-md: var(--fs-base); /* 16 buttons */
|
|
107
|
+
--fs-title: calc(var(--fs-base) * 1.0625); /* 17 */
|
|
108
|
+
--fs-lg: calc(var(--fs-base) * 1.25); /* 20 day numbers, tile values */
|
|
109
|
+
--fs-h2: calc(var(--fs-base) * 1.375); /* 22 */
|
|
110
|
+
--fs-2xl: calc(var(--fs-base) * 1.5); /* 24 composer, small ring */
|
|
111
|
+
--fs-h1: calc(var(--fs-base) * 1.75); /* 28 */
|
|
112
|
+
--fs-3xl: calc(var(--fs-base) * 2); /* 32 xl button */
|
|
113
|
+
--fs-display: clamp(calc(var(--fs-base) * 2.125), 9vw, calc(var(--fs-base) * 2.625)); /* 34–42 */
|
|
114
|
+
--fs-stat: clamp(calc(var(--fs-base) * 1.875), 8vw, calc(var(--fs-base) * 2.375)); /* 30–38 big numbers */
|
|
115
|
+
--fs-hero: calc(var(--fs-base) * 3.5); /* 56 the one number on a sheet */
|
|
116
|
+
--fs-giant: clamp(calc(var(--fs-base) * 3), 15vw, calc(var(--fs-base) * 4)); /* 48–64 data bands */
|
|
104
117
|
|
|
105
118
|
/* level weight size / line-height family */
|
|
106
119
|
--type-display: 800 var(--fs-display) / 1.15 var(--font-display); /* leading: Thai marks stack to 1.1em up and 0.3em down in FC Pride — 1.02 clipped them (2026-09-10) */
|
|
@@ -120,35 +133,53 @@
|
|
|
120
133
|
/* ============================================================
|
|
121
134
|
COLOR ROLES — wireframe defaults (grayscale).
|
|
122
135
|
palette.css overrides these under [data-palette="…"].
|
|
136
|
+
|
|
137
|
+
THE FIVE COLOUR BASES (Lh, 2026-09-20) — a project's own colours, the
|
|
138
|
+
same idea as the size bases: set a base, the roles follow.
|
|
139
|
+
--color-surface the app's ground
|
|
140
|
+
--color-ink the words
|
|
141
|
+
--color-paper the plain card, neutral buttons and fields
|
|
142
|
+
--color-brand the primary action, the strong card, the signal dot
|
|
143
|
+
--color-on-brand the words on the brand
|
|
144
|
+
They have NO default: unset, every role below is its exact wireframe
|
|
145
|
+
value. That is what the fallbacks are for — a private mix (--_*) that
|
|
146
|
+
reads an unset base is invalid, so var(--_x, #grey) lands on the grey.
|
|
147
|
+
Set, the roles derive: tone 2 = the brand washed into the surface, the
|
|
148
|
+
muted inks = the ink washed into their ground. A role set directly
|
|
149
|
+
(a palette, or a project's theme.css) always wins over its derivation.
|
|
123
150
|
============================================================ */
|
|
151
|
+
--_muted-on-surface: color-mix(in srgb, var(--color-ink) 66%, var(--color-surface, #f2f2f0));
|
|
152
|
+
--_muted-on-paper: color-mix(in srgb, var(--color-ink) 66%, var(--color-paper, #ffffff));
|
|
153
|
+
--_tone-2: color-mix(in srgb, var(--color-brand) 14%, var(--color-surface, #f2f2f0));
|
|
154
|
+
--_muted-on-tone-2: color-mix(in srgb, var(--color-ink, #141414) 72%, var(--_tone-2));
|
|
124
155
|
|
|
125
156
|
/* app background ("earth-toned surface or shiny color, up to the app") */
|
|
126
|
-
--surface: #f2f2f0;
|
|
127
|
-
--on-surface: #141414;
|
|
128
|
-
--on-surface-muted: #6b6b6b;
|
|
157
|
+
--surface: var(--color-surface, #f2f2f0);
|
|
158
|
+
--on-surface: var(--color-ink, #141414);
|
|
159
|
+
--on-surface-muted: var(--_muted-on-surface, #6b6b6b);
|
|
129
160
|
|
|
130
161
|
/* card boundaries — 3 slots so stacked/adjacent cards can differ */
|
|
131
|
-
--card-1-bg: #ffffff; --card-1-ink: #141414;
|
|
132
|
-
--card-2-bg: #e6e6e3; --card-2-ink: #141414;
|
|
133
|
-
--card-3-bg: #141414; --card-3-ink: #ffffff;
|
|
162
|
+
--card-1-bg: var(--color-paper, #ffffff); --card-1-ink: var(--color-ink, #141414);
|
|
163
|
+
--card-2-bg: var(--_tone-2, #e6e6e3); --card-2-ink: var(--color-ink, #141414);
|
|
164
|
+
--card-3-bg: var(--color-brand, #141414); --card-3-ink: var(--color-on-brand, #ffffff);
|
|
134
165
|
|
|
135
166
|
--card-border: #141414; /* wireframe: visible outline; palettes may set transparent */
|
|
136
|
-
--card-muted: #6b6b6b; /* secondary text inside cards (the default, tone-1 card) */
|
|
137
|
-
--card-2-muted: #5f5f5f; /* the same text on the tone-2 card — 5.1:1 on its grey (#6b6b6b is 4.3:1, under AA);
|
|
167
|
+
--card-muted: var(--_muted-on-paper, #6b6b6b); /* secondary text inside cards (the default, tone-1 card) */
|
|
168
|
+
--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);
|
|
138
169
|
a palette whose tone-2 ground is strong
|
|
139
170
|
sets this to its tone-2 ink — a muted shade cannot reach AA there (clay) */
|
|
140
171
|
|
|
141
172
|
/* actions */
|
|
142
|
-
--accent: #141414; /* primary CTA fill */
|
|
143
|
-
--on-accent: #ffffff;
|
|
144
|
-
--action-bg: #ffffff; /* neutral buttons/chips/inputs */
|
|
145
|
-
--action-ink: #141414;
|
|
173
|
+
--accent: var(--color-brand, #141414); /* primary CTA fill */
|
|
174
|
+
--on-accent: var(--color-on-brand, #ffffff);
|
|
175
|
+
--action-bg: var(--color-paper, #ffffff); /* neutral buttons/chips/inputs */
|
|
176
|
+
--action-ink: var(--color-ink, #141414);
|
|
146
177
|
--action-border: #141414;
|
|
147
178
|
|
|
148
179
|
/* signals (chip dots, deltas) */
|
|
149
180
|
--pos: #8a8a8a;
|
|
150
181
|
--neg: #3d3d3d;
|
|
151
|
-
--dot-a: #141414;
|
|
182
|
+
--dot-a: var(--color-brand, #141414);
|
|
152
183
|
--dot-b: #8a8a8a;
|
|
153
184
|
|
|
154
185
|
/* derived tints — read the element's own ink, so they work on any slot */
|
package/dist/actions/Chip.d.ts
CHANGED
|
@@ -4,15 +4,13 @@ export interface ChipProps extends ComponentPropsWithoutRef<'span'> {
|
|
|
4
4
|
on?: boolean;
|
|
5
5
|
/** a leading signal dot: `a` (the accent signal) or `b` (the secondary) */
|
|
6
6
|
dot?: 'a' | 'b';
|
|
7
|
-
/** a speech tail under the chip (a mascot's greeting) */
|
|
8
|
-
bubble?: boolean;
|
|
9
7
|
/** the element: span (default), a link, or a button */
|
|
10
8
|
as?: 'span' | 'a' | 'button';
|
|
11
9
|
href?: string;
|
|
12
10
|
children?: ReactNode;
|
|
13
11
|
}
|
|
14
12
|
/** Chip — a status or attribute tag (with an optional signal Dot), or a small tap target; `on` when it is the live one. For a choice use ChipPick (`sign` for the +/× interest picker). */
|
|
15
|
-
export declare function Chip({ on, dot,
|
|
13
|
+
export declare function Chip({ on, dot, as, href, className, children, ...rest }: ChipProps): import("react").DetailedReactHTMLElement<{
|
|
16
14
|
slot?: string | undefined | undefined;
|
|
17
15
|
style?: import("react").CSSProperties | undefined;
|
|
18
16
|
title?: string | undefined | undefined;
|
package/dist/actions/Chip.js
CHANGED
|
@@ -3,9 +3,9 @@ import { createElement } from 'react';
|
|
|
3
3
|
import { cx } from '../cx.js';
|
|
4
4
|
import { Dot } from './Dot.js';
|
|
5
5
|
/** Chip — a status or attribute tag (with an optional signal Dot), or a small tap target; `on` when it is the live one. For a choice use ChipPick (`sign` for the +/× interest picker). */
|
|
6
|
-
export function Chip({ on, dot,
|
|
6
|
+
export function Chip({ on, dot, as, href, className, children, ...rest }) {
|
|
7
7
|
const el = as ?? (href ? 'a' : 'span');
|
|
8
|
-
return createElement(el, { href, type: el === 'button' ? 'button' : undefined, className: cx('chip', on && 'chip--on',
|
|
8
|
+
return createElement(el, { href, type: el === 'button' ? 'button' : undefined, className: cx('chip', on && 'chip--on', className), ...rest }, dot && _jsx(Dot, { b: dot === 'b' }), children);
|
|
9
9
|
}
|
|
10
10
|
/** ChipPick — a chip that is a choice: full-width in a ChipGrid (9:00 · 9:30 · …), or `sign` on a ChipRow (+ off, × on — the
|
|
11
11
|
* interest picker); the picked one fills with accent. A native radio/checkbox inside the label carries the state. */
|