@usableapp/cardds 0.7.86 → 0.7.87
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 +21 -0
- package/README.md +26 -1
- package/bin/cardds.mjs +8 -3
- package/css/actions.css +1 -2
- package/css/card.css +1 -2
- package/css/choice.css +2 -2
- package/css/finish.css +97 -11
- package/css/forms.css +1 -2
- package/css/numbers.css +1 -2
- package/css/post.css +1 -2
- package/css/stack.css +1 -1
- package/css/stamp.css +3 -4
- package/css/step.css +6 -0
- package/css/sticky.css +1 -1
- package/css/tokens.css +6 -0
- package/dist/cardds.css +121 -29
- package/dist/cards/CardFeed.js +2 -9
- package/dist/catalog.json +1 -1
- package/dist/lists/Row.js +2 -9
- package/dist/pressable.d.ts +8 -0
- package/dist/pressable.js +6 -0
- package/dist/scaffold/Screen.js +2 -9
- package/dist/sheets/StackSheet.js +3 -7
- package/dist/sheets/sheetMeasure.d.ts +1 -0
- package/dist/sheets/sheetMeasure.js +14 -9
- package/dist/sheets/stackCard.js +41 -48
- package/dist/stamp/Stamp.js +3 -6
- package/dist/stamp/StampBook.js +2 -3
- package/dist/stamp/StampOn.js +1 -1
- package/dist/state.d.ts +5 -1
- package/dist/state.js +8 -0
- package/dist/sticky/Sticky.js +2 -3
- package/lib/catalog.mjs +24 -7
- package/lib/mcp.mjs +3 -3
- package/package.json +1 -1
package/dist/cardds.css
CHANGED
|
@@ -307,6 +307,12 @@
|
|
|
307
307
|
@property --sheet-half { syntax: "<number>"; inherits: true; initial-value: 0.5; }
|
|
308
308
|
@property --sheet-3q { syntax: "<number>"; inherits: true; initial-value: 0.25; }
|
|
309
309
|
|
|
310
|
+
/* the ring that turns while waiting: Spinner, FormNote busy */
|
|
311
|
+
@keyframes turn { to { rotate: 1turn; } }
|
|
312
|
+
/* a mark struck onto paper — shown large and faint, pressed a little past its size, then at rest: StampOn `arrive`, the post desk's
|
|
313
|
+
postmark (Lh 2026-10-12: one strike for both; the postmark used to slide in from up-left, turning). Both read --stamp-on-arrive-time */
|
|
314
|
+
@keyframes strike { from { scale: 2; opacity: 0; } 60% { scale: 0.92; opacity: 1; } }
|
|
315
|
+
|
|
310
316
|
/* ---- css/palette.css — color settings — the file you tune ---- */
|
|
311
317
|
/* ============================================================
|
|
312
318
|
cardds/palette.css — COLOR SETTINGS. The only file you tune.
|
|
@@ -898,12 +904,11 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
898
904
|
actions.css) and scrolls up like any page — nothing is capped, nothing
|
|
899
905
|
shrinks, no scroll box inside a box.
|
|
900
906
|
So on a .screen that is NOT --fill the group is in flow: the column is at
|
|
901
|
-
least one phone tall, the group takes the room after the top bar and
|
|
907
|
+
least one phone tall (step.css), the group takes the room after the top bar and
|
|
902
908
|
centres its children in it. The screen's own inset stays the inset.
|
|
903
909
|
<div class="screen"><header class="topbar">…</header>
|
|
904
910
|
<div class="screen__centre"><article class="card">…</article><div class="pager__at">…</div></div>
|
|
905
911
|
</div><div class="action-bar">…</div> */
|
|
906
|
-
.screen:not(.screen--fill):has(> .screen__centre) { min-height: 100dvh; display: flex; flex-direction: column; }
|
|
907
912
|
.screen:not(.screen--fill) > .screen__centre { flex: 1; padding-inline: 0; align-content: center; }
|
|
908
913
|
|
|
909
914
|
/* ---- the card that changes slides: out one side, the next in from the other ----
|
|
@@ -1387,7 +1392,7 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
1387
1392
|
}
|
|
1388
1393
|
/* a card standing in this room is FLAT (Lh 2026-10-09): the room clips at its own edges, and a card's shadow cut there drew a straight
|
|
1389
1394
|
line under the bar and along the first sheet. Its ground and its radius are what say "card" here. */
|
|
1390
|
-
:is([data-palette], [data-finish
|
|
1395
|
+
:is([data-palette], [data-finish]) .sheet-stack__base .card { box-shadow: none; }
|
|
1391
1396
|
|
|
1392
1397
|
/* ============================================================
|
|
1393
1398
|
.sheet-stack--flood — a closed stack whose open sheet FLOODS the screen: it rises over the top bar and fills the whole screen
|
|
@@ -2207,6 +2212,12 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
2207
2212
|
padding-bottom: var(--bottom-h, 0rem); /* exactly the bottom layer (measured by Screen): a page scrolls ONLY when the layer would cover its words, and then just far enough to clear them — at 100% nothing scrolls (Lh 2026-09-23) */
|
|
2208
2213
|
}
|
|
2209
2214
|
|
|
2215
|
+
/* a SCROLLING (not fill) screen becomes a column at least one phone tall when it holds a bottom or a centre:
|
|
2216
|
+
an .action-bar as its last child (Lh 2026-09-24, 0.7.0: the bar is the column's last row — at the foot when the words are short,
|
|
2217
|
+
sticky to the viewport's foot while they scroll; actions.css) or a .screen__centre (Lh 2026-09-12: the group is in flow, takes the
|
|
2218
|
+
room after the top bar and centres its children in it; a long one makes the page longer and runs under the bar; card.css) */
|
|
2219
|
+
.screen:not(.screen--fill):has(> .action-bar:last-child, > .screen__centre) { display: flex; flex-direction: column; min-height: 100dvh; }
|
|
2220
|
+
|
|
2210
2221
|
/* ============================================================
|
|
2211
2222
|
TOP + CONTENT in one flex column; BOTTOM is a LAYER over them (Lh 2026-09-23, second call — replaces "the bar is a row"):
|
|
2212
2223
|
in a .screen--fill the content runs to the screen's bottom edge, and the bar lies over it at the foot — it covers what is
|
|
@@ -2362,8 +2373,7 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
2362
2373
|
.form-note { display: flex; align-items: center; justify-content: center; gap: var(--sp-2); margin: 0; font: var(--form-note-font, var(--type-caption)); color: var(--form-note-ink, var(--card-muted)); text-align: center; }
|
|
2363
2374
|
.form-note > .icon { flex: none; }
|
|
2364
2375
|
.form-note--error { color: var(--form-note-error-ink, var(--signal-error)); }
|
|
2365
|
-
@media (prefers-reduced-motion: no-preference) { .form-note--busy > .icon { animation:
|
|
2366
|
-
@keyframes form-note-turn { to { rotate: 1turn; } }
|
|
2376
|
+
@media (prefers-reduced-motion: no-preference) { .form-note--busy > .icon { animation: turn 0.9s linear infinite; } } /* `turn`: tokens.css */
|
|
2367
2377
|
|
|
2368
2378
|
/* ---- css/journey.css — route, tile badge, note row ---- */
|
|
2369
2379
|
/* ============================================================
|
|
@@ -2702,10 +2712,9 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
2702
2712
|
display: flex;
|
|
2703
2713
|
gap: var(--sp-2);
|
|
2704
2714
|
}
|
|
2705
|
-
/* a bar INSIDE a scrolling (not fill) screen (Lh 2026-09-24, 0.7.0): the screen is a column at least one phone tall, the bar its
|
|
2715
|
+
/* a bar INSIDE a scrolling (not fill) screen (Lh 2026-09-24, 0.7.0): the screen is a column at least one phone tall (step.css), the bar its
|
|
2706
2716
|
last row — at the foot when the words are short, and sticky to the viewport's foot (above the keyboard) while they scroll;
|
|
2707
2717
|
it takes the room it needs in the column, so nothing is added to the content for it */
|
|
2708
|
-
.screen:not(.screen--fill):has(> .action-bar:last-child) { display: flex; flex-direction: column; min-height: 100dvh; }
|
|
2709
2718
|
.screen:not(.screen--fill) > .action-bar:last-child {
|
|
2710
2719
|
position: sticky; bottom: var(--kb, 0rem);
|
|
2711
2720
|
max-width: none;
|
|
@@ -3121,8 +3130,7 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
3121
3130
|
The ring turns; words beside it are optional and take the caption's look. Still when motion is reduced. */
|
|
3122
3131
|
.spinner { display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2); vertical-align: middle; font: var(--type-caption); color: var(--spinner-ink, currentColor); }
|
|
3123
3132
|
.spinner > .icon { flex: none; }
|
|
3124
|
-
@media (prefers-reduced-motion: no-preference) { .spinner > .icon { animation:
|
|
3125
|
-
@keyframes spinner-turn { to { rotate: 1turn; } }
|
|
3133
|
+
@media (prefers-reduced-motion: no-preference) { .spinner > .icon { animation: turn 0.9s linear infinite; } } /* `turn`: tokens.css */
|
|
3126
3134
|
|
|
3127
3135
|
/* ---- progress: one straight line, the done share solid, the rest faint (Lh 2026-09-22) — a voice note's
|
|
3128
3136
|
timeline, a download, a step count as a line. <div class="progress" role="progressbar" style="--progress-at: 0.4"></div>
|
|
@@ -3309,8 +3317,8 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
3309
3317
|
.chip-grid > .chip { justify-self: stretch; justify-content: center; min-height: var(--btn-h); padding-inline: var(--sp-2); }
|
|
3310
3318
|
.chip--pick { position: relative; } /* the input covers the whole chip, on a row as in a grid */
|
|
3311
3319
|
/* the hidden input, the same shape wherever a native radio/checkbox drives a picked look:
|
|
3312
|
-
a chip, a mood dot, a tile (media.css) */
|
|
3313
|
-
:is(.chip--pick, .mood__opt, .tile--pick) > input { appearance: none; position: absolute; inset: 0; margin: 0; opacity: 0; cursor: inherit; }
|
|
3320
|
+
a chip, a mood dot, a tile (media.css), a sticky's tone swatch (sticky.css) — the native input lies over its whole box, unseen */
|
|
3321
|
+
:is(.chip--pick, .mood__opt, .tile--pick, .sticky-pick__swatch) > input { appearance: none; position: absolute; inset: 0; margin: 0; opacity: 0; cursor: inherit; }
|
|
3314
3322
|
:is(.chip--pick, .tile--pick):has(:checked) { background: var(--accent); color: var(--on-accent); border-color: transparent; }
|
|
3315
3323
|
/* --sign: the trailing + that turns 45° into an × when picked — one mask, one rotate, no swap (Lh 2026-09-16) */
|
|
3316
3324
|
.chip--sign { padding-right: var(--sp-2); }
|
|
@@ -3956,7 +3964,7 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
3956
3964
|
box-shadow: inset 0 0 0 var(--border-w) var(--ink-tint); /* a pale tone still has an edge on a pale ground */
|
|
3957
3965
|
cursor: pointer;
|
|
3958
3966
|
}
|
|
3959
|
-
|
|
3967
|
+
/* its hidden input: the picks' one rule, choice.css */
|
|
3960
3968
|
.sticky-pick__swatch:has(> :checked) { outline: var(--rule-w) solid currentColor; outline-offset: var(--sp-0); }
|
|
3961
3969
|
.sticky-pick__swatch:has(> :focus-visible) { outline: var(--focus); outline-offset: var(--sp-1); }
|
|
3962
3970
|
|
|
@@ -4411,12 +4419,11 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
4411
4419
|
@media (prefers-reduced-motion: no-preference) { .stamp-on__remove { animation: stamp-on-remove-in var(--motion-press) ease-out; } }
|
|
4412
4420
|
@keyframes stamp-on-remove-in { from { opacity: 0; scale: 0.6; } }
|
|
4413
4421
|
|
|
4414
|
-
/* --arrive: the stamp sticks ITSELF (StampOn `arrive`) — struck onto its place
|
|
4415
|
-
|
|
4422
|
+
/* --arrive: the stamp sticks ITSELF (StampOn `arrive`) — struck onto its place (`strike`: tokens.css). The component reads the
|
|
4423
|
+
animation's name to tell the app it has landed. Knob: --stamp-on-arrive-time */
|
|
4416
4424
|
@media (prefers-reduced-motion: no-preference) {
|
|
4417
|
-
.stamp-on--arrive { animation:
|
|
4425
|
+
.stamp-on--arrive { animation: strike var(--stamp-on-arrive-time, var(--motion-sheet)) ease-in both; }
|
|
4418
4426
|
}
|
|
4419
|
-
@keyframes stamp-on-strike { from { scale: 2; opacity: 0; } 60% { scale: 0.92; opacity: 1; } }
|
|
4420
4427
|
|
|
4421
4428
|
/* ---- css/post.css — the post: postmark, a postcard read (letter), written (desk), kept (box) ---- */
|
|
4422
4429
|
/* cardds — the post: a postcard read (post-letter), written (post-desk) and kept (post-box), the postmark, the card stock.
|
|
@@ -4655,10 +4662,9 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
4655
4662
|
.post-desk__slot { border: 0; background: transparent; color: inherit; }
|
|
4656
4663
|
@media (prefers-reduced-motion: no-preference) {
|
|
4657
4664
|
.post-desk__slot > .stamp { animation: post-desk-stick var(--motion-quick) ease-out both; }
|
|
4658
|
-
.post-desk .postmark { animation:
|
|
4665
|
+
.post-desk .postmark { animation: strike var(--stamp-on-arrive-time, var(--motion-sheet)) ease-in both; } /* struck as a StampOn is (`strike`: tokens.css), in the same time */
|
|
4659
4666
|
}
|
|
4660
4667
|
@keyframes post-desk-stick { from { translate: 0 calc(-1 * var(--sp-8)); rotate: 14deg; opacity: 0; } }
|
|
4661
|
-
@keyframes post-desk-strike { from { translate: calc(-1 * var(--sp-3)) calc(-1 * var(--sp-6)); rotate: -24deg; opacity: 0; } }
|
|
4662
4668
|
/* the other half's showing edge brings it across: a tap-wide strip out to the screen's edge */
|
|
4663
4669
|
.post-desk__reach { position: absolute; inset-block: 0; width: var(--tap); border: 0; background: transparent; }
|
|
4664
4670
|
.post-desk__reach--address { inset-inline-end: calc(-1 * var(--screen-pad)); }
|
|
@@ -5402,19 +5408,37 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
5402
5408
|
|
|
5403
5409
|
/* ---- css/finish.css — light, shadow, edges — only under data-finish="lit" ---- */
|
|
5404
5410
|
/* ============================================================
|
|
5405
|
-
cardds/finish.css — FINISH:
|
|
5406
|
-
look read flat, "not finished"), apart from colour: palette.css says WHICH colours, this says
|
|
5407
|
-
|
|
5408
|
-
No attribute = nothing here applies — the flat look, unchanged.
|
|
5411
|
+
cardds/finish.css — FINISH: the finish of a card's paper. A style of its own (Lh 2026-10-02: the plain
|
|
5412
|
+
look read flat, "not finished"), apart from colour: palette.css says WHICH colours, this says what the
|
|
5413
|
+
material is and how it is lit. Apply with <html data-finish="…"> (or on any ancestor) beside any palette,
|
|
5414
|
+
or none, or "own". No attribute = nothing here applies — the flat look, unchanged.
|
|
5415
|
+
|
|
5416
|
+
FINISHES — four values of the one attribute (Lh 2026-10-12, from the timebank home with each injected:
|
|
5417
|
+
four finishes, variations of one concept, never new pieces; teeth · tape · ticket · slab were rejected):
|
|
5418
|
+
lit = lit from above: a lit top edge, a hairline ring and a layered shadow that grows with height; filled buttons stand up and go down under the finger; fields and pin cells are sunk.
|
|
5419
|
+
print = printed paper: an ink line in the card's own ink, a hard misregistered offset instead of a blurred shadow, paper grain over the card, a dotted rule under the head as on a printed form; information inside stays flat.
|
|
5420
|
+
sticker = a die-cut sticker: a white cut line round the card, a short hard drop, a slight tilt on a lone card, buttons with a bottom edge that press down.
|
|
5421
|
+
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.
|
|
5422
|
+
KNOBS (set in a theme, as any knob; docs/knobs.md lists them):
|
|
5423
|
+
print --print-off (the misregistration: how far the second pass missed) · --print-grain (the grain's opacity; a ::after, so the knob walk cannot probe it)
|
|
5424
|
+
sticker --sticker-cut (the paper left round the print) · --sticker-tilt (a lone card's lean; 0deg for none — a card in a stack or a list never leans)
|
|
5425
|
+
ink --ink-w (the line) · --ink-off (the offset)
|
|
5426
|
+
|
|
5427
|
+
Information inside a card stays flat under every finish: only a container or a control gets an edge.
|
|
5428
|
+
Colours are mixes of the roles (--on-surface, --card-ink, --accent, currentColor), never plain black,
|
|
5429
|
+
so a finish sits in any palette; the one plain white is the sticker's backing paper and the lit edge's light.
|
|
5430
|
+
============================================================ */
|
|
5431
|
+
|
|
5432
|
+
/* every finish: the finish IS the edge, so the wireframe's two borders step back (as [data-palette] in palette.css); ink puts its own line there below */
|
|
5433
|
+
[data-finish] { --card-border: transparent; --action-border: transparent; }
|
|
5409
5434
|
|
|
5410
|
-
|
|
5435
|
+
/* ============================================================
|
|
5436
|
+
lit — the light comes from above:
|
|
5411
5437
|
- a thing that stands UP (card, sheet, button) has a lit top edge, a hairline ring and a shadow
|
|
5412
5438
|
that grows with its height: card 1 · sheet / float 2 — the layers cardds already has;
|
|
5413
|
-
- a thing that is SUNK (a field, a pin cell) has its shadow inside, under its top edge
|
|
5414
|
-
- information inside a card stays flat: only a container or a control gets an edge.
|
|
5439
|
+
- a thing that is SUNK (a field, a pin cell) has its shadow inside, under its top edge.
|
|
5415
5440
|
Shadows are mixed from the ink (--on-surface), never plain black, so they sit in the palette.
|
|
5416
5441
|
============================================================ */
|
|
5417
|
-
|
|
5418
5442
|
[data-finish="lit"] {
|
|
5419
5443
|
--_shade: var(--on-surface);
|
|
5420
5444
|
--finish-edge: inset 0 1px 0 rgb(255 255 255 / 0.55); /* the lit top edge */
|
|
@@ -5440,9 +5464,6 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
5440
5464
|
--finish-sheen: linear-gradient(to bottom, rgb(255 255 255 / 0.16), rgb(255 255 255 / 0) 60%);
|
|
5441
5465
|
--finish-sunk: inset 0 1px 2px color-mix(in srgb, var(--_shade) 14%, transparent), 0 1px 0 rgb(255 255 255 / 0.5);
|
|
5442
5466
|
|
|
5443
|
-
/* the shadow is the edge: the wireframe's lines step back (as in every colour palette) */
|
|
5444
|
-
--card-border: transparent;
|
|
5445
|
-
--action-border: transparent;
|
|
5446
5467
|
--outline: color-mix(in srgb, currentColor 14%, transparent);
|
|
5447
5468
|
}
|
|
5448
5469
|
|
|
@@ -5484,3 +5505,74 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
5484
5505
|
/* ---- sunk: what the member types into ---- */
|
|
5485
5506
|
[data-finish="lit"] :is(.field, .pin__cell) { box-shadow: var(--finish-sunk); }
|
|
5486
5507
|
|
|
5508
|
+
/* ============================================================
|
|
5509
|
+
print — printed paper (riso / zine): the second pass missed by --print-off, so the card's shadow is a
|
|
5510
|
+
hard offset in its own ink; a line in that ink round the card; grain over the whole card; the head
|
|
5511
|
+
underlined by a dotted rule as on a printed form. A lone card's head is a form's head; a stacked
|
|
5512
|
+
sheet's, a row card's, a cover's (controls over a picture) and a folded feed card's (the head is the
|
|
5513
|
+
whole card) have no rule.
|
|
5514
|
+
============================================================ */
|
|
5515
|
+
[data-finish="print"] {
|
|
5516
|
+
--_ink: color-mix(in srgb, currentColor 70%, transparent);
|
|
5517
|
+
--outline: var(--_ink);
|
|
5518
|
+
}
|
|
5519
|
+
[data-finish="print"] .card {
|
|
5520
|
+
border: var(--border-w) solid var(--_ink);
|
|
5521
|
+
box-shadow: var(--print-off, 3px) var(--print-off, 3px) 0 0 color-mix(in srgb, var(--card-ink) 28%, transparent);
|
|
5522
|
+
isolation: isolate; /* the grain's blend stays inside the card */
|
|
5523
|
+
}
|
|
5524
|
+
/* the grain: a ::after, not ::before — .card--cover's scrim is its ::before. Over everything in the card (z-index 1, the foot's own level), touches pass through it */
|
|
5525
|
+
[data-finish="print"] .card::after {
|
|
5526
|
+
content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: 1;
|
|
5527
|
+
opacity: var(--print-grain, 0.32); mix-blend-mode: multiply;
|
|
5528
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.3 0 0 0 0 0.25 0 0 0 0 0.2 0 0 0 0.9 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
|
|
5529
|
+
}
|
|
5530
|
+
/* a dark card (the brand tone, a cover): multiply would only blacken it, so the grain lightens, fainter */
|
|
5531
|
+
[data-finish="print"] :is(.card--3, .card--cover)::after { mix-blend-mode: screen; opacity: calc(var(--print-grain, 0.32) * 0.56); }
|
|
5532
|
+
[data-finish="print"] .card:not(.card--row, .card--cover, .feed-card--small, .sheet-stack > *, .sheet-stack > :not(.sheet-stack__base) > *) > .card__head {
|
|
5533
|
+
padding-bottom: var(--sp-2);
|
|
5534
|
+
border-bottom: var(--rule-w) dotted color-mix(in srgb, currentColor 45%, transparent);
|
|
5535
|
+
}
|
|
5536
|
+
[data-finish="print"] :is(.btn, .chip) {
|
|
5537
|
+
border-color: var(--_ink);
|
|
5538
|
+
box-shadow: 2px 2px 0 0 color-mix(in srgb, currentColor 35%, transparent);
|
|
5539
|
+
}
|
|
5540
|
+
[data-finish="print"] .btn--primary { box-shadow: 2px 2px 0 0 color-mix(in srgb, var(--card-ink) 60%, transparent); }
|
|
5541
|
+
[data-finish="print"] :is(.btn, .chip):active { box-shadow: none; translate: 2px 2px; }
|
|
5542
|
+
[data-finish="print"] .card__thumb { border-style: dashed; }
|
|
5543
|
+
|
|
5544
|
+
/* ============================================================
|
|
5545
|
+
sticker — a die-cut sticker on a sheet: --sticker-cut of white paper left round the print, a short hard
|
|
5546
|
+
drop under it, a lone card leans by --sticker-tilt (the next one the other way); chunky buttons with a
|
|
5547
|
+
bottom edge that press down. A card in a stack, in a list, in a feed, a sheet or a modal never leans:
|
|
5548
|
+
those are placed by their holder, a lean would cut or cross them.
|
|
5549
|
+
============================================================ */
|
|
5550
|
+
[data-finish="sticker"] { --outline: color-mix(in srgb, currentColor 18%, transparent); }
|
|
5551
|
+
[data-finish="sticker"] .card {
|
|
5552
|
+
box-shadow:
|
|
5553
|
+
0 0 0 var(--sticker-cut, 5px) #fff,
|
|
5554
|
+
0 calc(var(--sticker-cut, 5px) + 4px) 0 0 color-mix(in srgb, var(--on-surface) 16%, transparent),
|
|
5555
|
+
0 calc(var(--sticker-cut, 5px) + 12px) 20px -8px color-mix(in srgb, var(--on-surface) 22%, transparent);
|
|
5556
|
+
}
|
|
5557
|
+
[data-finish="sticker"] .card:not(.sheet, .modal, .sheet-stack *, .card-list > *, .card-feed > *) { rotate: var(--sticker-tilt, 0.8deg); }
|
|
5558
|
+
[data-finish="sticker"] .card:not(.sheet, .modal, .sheet-stack *, .card-list > *, .card-feed > *):nth-of-type(even) { rotate: calc(-1 * var(--sticker-tilt, 0.8deg)); }
|
|
5559
|
+
[data-finish="sticker"] .card-list { gap: var(--sp-5); }
|
|
5560
|
+
[data-finish="sticker"] .btn {
|
|
5561
|
+
box-shadow: 0 3px 0 0 color-mix(in srgb, currentColor 30%, transparent);
|
|
5562
|
+
border-color: color-mix(in srgb, currentColor 25%, transparent);
|
|
5563
|
+
}
|
|
5564
|
+
[data-finish="sticker"] .btn--primary { box-shadow: 0 3px 0 0 color-mix(in srgb, var(--btn-primary-bg, var(--accent)) 55%, var(--on-surface)); }
|
|
5565
|
+
[data-finish="sticker"] .btn:active { box-shadow: none; translate: 0 3px; }
|
|
5566
|
+
[data-finish="sticker"] .chip { box-shadow: 0 0 0 3px #fff; }
|
|
5567
|
+
|
|
5568
|
+
/* ============================================================
|
|
5569
|
+
ink — a poster / comic print: --ink-w of the surface's ink round every boundary and control, and a hard
|
|
5570
|
+
offset of --ink-off in the same ink. The two wireframe borders come back as that line.
|
|
5571
|
+
============================================================ */
|
|
5572
|
+
[data-finish="ink"] { --card-border: var(--on-surface); --action-border: var(--on-surface); --outline: currentColor; }
|
|
5573
|
+
[data-finish="ink"] .card { border: var(--ink-w, 2.5px) solid var(--on-surface); box-shadow: var(--ink-off, 5px) var(--ink-off, 5px) 0 0 var(--on-surface); }
|
|
5574
|
+
[data-finish="ink"] :is(.btn, .chip, .icon-btn:not(.icon-btn-group > *)) { border: var(--ink-w, 2.5px) solid currentColor; box-shadow: 3px 3px 0 0 currentColor; }
|
|
5575
|
+
[data-finish="ink"] .btn--primary { border-color: var(--on-surface); box-shadow: 3px 3px 0 0 var(--on-surface); }
|
|
5576
|
+
[data-finish="ink"] .toggle { box-shadow: 2px 2px 0 0 var(--on-surface); }
|
|
5577
|
+
[data-finish="ink"] .card__thumb { border-width: var(--ink-w, 2.5px); }
|
|
5578
|
+
|
package/dist/cards/CardFeed.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Children, createContext, isValidElement, useContext, useId, useLayoutEffect, useRef } from 'react';
|
|
3
3
|
import { cx } from '../cx.js';
|
|
4
|
-
import { reducedMotion, useControlled, warnOnce } from '../state.js';
|
|
4
|
+
import { reducedMotion, setRefs, useControlled, warnOnce } from '../state.js';
|
|
5
5
|
import { Card } from './Card.js';
|
|
6
6
|
import { CardHead } from './CardHead.js';
|
|
7
7
|
import { CardFoot } from './CardFoot.js';
|
|
@@ -53,16 +53,9 @@ export function CardFeed({ big: bigProp, defaultBig, onBigChange, className, chi
|
|
|
53
53
|
}
|
|
54
54
|
tops.current = at;
|
|
55
55
|
});
|
|
56
|
-
const setRef = (node) => {
|
|
57
|
-
own.current = node;
|
|
58
|
-
if (typeof ref === 'function')
|
|
59
|
-
ref(node);
|
|
60
|
-
else if (ref)
|
|
61
|
-
ref.current = node;
|
|
62
|
-
};
|
|
63
56
|
if (!shown.length)
|
|
64
57
|
return null;
|
|
65
|
-
return (_jsx(FeedCtx.Provider, { value: { big, grow: (id) => request(id, 'tap') }, children: _jsx("div", { ref:
|
|
58
|
+
return (_jsx(FeedCtx.Provider, { value: { big, grow: (id) => request(id, 'tap') }, children: _jsx("div", { ref: setRefs(own, ref), className: cx('card-feed', className), ...rest, children: shown }) }));
|
|
66
59
|
}
|
|
67
60
|
const onSmallKey = (e) => {
|
|
68
61
|
if (e.target !== e.currentTarget || (e.key !== 'Enter' && e.key !== ' '))
|