@sigx/zero-daisyui 0.14.0 → 0.15.0

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.
Files changed (44) hide show
  1. package/dist/css/components/container.css +1 -0
  2. package/dist/css/components/input.css +9 -0
  3. package/dist/css/components/nav-list.css +7 -0
  4. package/dist/css/index.css +17 -0
  5. package/dist/lynx/components/alert.css +7 -1
  6. package/dist/lynx/components/badge.css +2 -4
  7. package/dist/lynx/components/breadcrumbs.css +30 -21
  8. package/dist/lynx/components/button.css +2 -7
  9. package/dist/lynx/components/card.css +1 -2
  10. package/dist/lynx/components/carousel.css +4 -4
  11. package/dist/lynx/components/chat-log.css +5 -5
  12. package/dist/lynx/components/chat.css +1 -1
  13. package/dist/lynx/components/container.css +3 -2
  14. package/dist/lynx/components/diff.css +1 -1
  15. package/dist/lynx/components/divider.css +10 -10
  16. package/dist/lynx/components/drawer.css +8 -8
  17. package/dist/lynx/components/empty-state.css +1 -1
  18. package/dist/lynx/components/fieldset.css +1 -1
  19. package/dist/lynx/components/grid.css +2 -2
  20. package/dist/lynx/components/kbd.css +2 -3
  21. package/dist/lynx/components/menu.css +20 -1
  22. package/dist/lynx/components/nav-list.css +15 -2
  23. package/dist/lynx/components/navbar.css +9 -5
  24. package/dist/lynx/components/pagination.css +97 -65
  25. package/dist/lynx/components/radial-progress.css +10 -10
  26. package/dist/lynx/components/select.css +1 -2
  27. package/dist/lynx/components/spinner.css +2 -12
  28. package/dist/lynx/components/stack.css +2 -2
  29. package/dist/lynx/components/status.css +10 -20
  30. package/dist/lynx/components/steps.css +114 -22
  31. package/dist/lynx/components/table.css +1 -1
  32. package/dist/lynx/components/tabs.css +1 -1
  33. package/dist/lynx/components/timeline.css +12 -25
  34. package/dist/lynx/components/toast.css +2 -4
  35. package/dist/lynx/components/tree-view.css +31 -4
  36. package/dist/lynx/index.css +407 -249
  37. package/dist/lynx/manifest.json +2 -2
  38. package/dist/manifest.json +1 -1
  39. package/dist/recipes.d.ts.map +1 -1
  40. package/dist/recipes.js +282 -17
  41. package/dist/recipes.js.map +1 -1
  42. package/dist/report.json +548 -31
  43. package/package.json +4 -4
  44. package/src/recipes.ts +287 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigx/zero-daisyui",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "DaisyUI-flavored design system for SignalX Zero — daisy's token values and component look as a pure tokens+recipes skin over @sigx/zero primitives. No Tailwind, no daisyUI plugin required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -62,12 +62,12 @@
62
62
  "url": "https://github.com/signalxjs/zero/issues"
63
63
  },
64
64
  "peerDependencies": {
65
- "@sigx/zero": "^0.14.0"
65
+ "@sigx/zero": "^0.15.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "typescript": "^7.0.2",
69
- "@sigx/zero": "^0.14.0",
70
- "@sigx/zero-kit": "^0.14.0"
69
+ "@sigx/zero-kit": "^0.15.0",
70
+ "@sigx/zero": "^0.15.0"
71
71
  },
72
72
  "publishConfig": {
73
73
  "access": "public"
package/src/recipes.ts CHANGED
@@ -1625,12 +1625,34 @@ export const menu: RecipeInput = {
1625
1625
  // Trigger-carried axes — same wiring as dialog, same reason. The dropdown
1626
1626
  // and its items are top-layer siblings the donut cannot reach.
1627
1627
  variants: { color: btnColors(), size: btnSizes },
1628
- // The btn paddings, restated physically — see `lynxBtnPad` (#1084).
1628
+ // The btn paddings, restated physically — see `lynxBtnPad` (#1084) —
1629
+ // and the trigger's press rendering, as popover's (`lynxBtnPressed`).
1629
1630
  targets: {
1630
1631
  web: floatingArrow('menu', panelArrowPaint),
1631
1632
  lynx: {
1632
1633
  parts: {
1633
- trigger: { base: lynxBtnPad(4) },
1634
+ // Content-sized like daisy's btn (signalxjs/lynx#1165), an
1635
+ // explicit row (lynx does not default the direction the way a
1636
+ // browser does), the held state in place of the dropped
1637
+ // `:hover`, and the box-shadow ring (signalxjs/lynx#1163).
1638
+ trigger: {
1639
+ base: { ...lynxBtnPad(4), ...lynxBtnFit, flexDirection: 'row' },
1640
+ states: { pressed: lynxBtnPressed, ...lynxFocus() },
1641
+ },
1642
+ // The popups' rows stack and span the panel: a flex column
1643
+ // (a lynx view's default is a shrink-wrapping linear box).
1644
+ popup: { base: { display: 'flex', flexDirection: 'column' } },
1645
+ 'sub-popup': { base: { display: 'flex', flexDirection: 'column' } },
1646
+ // Every row kind is a mark / label / shortcut / chevron row.
1647
+ // A touch list has no hover: lynx-zero stamps `highlighted` on
1648
+ // the row under the finger, so the web's highlight wash is the
1649
+ // press rendering as it stands. The ✓ (item-indicator) and ›
1650
+ // (sub-trigger) the web draws with `::after` render as
1651
+ // `<text>` glyphs in lynx-zero — there is no pseudo-element.
1652
+ item: { base: { flexDirection: 'row' } },
1653
+ 'checkbox-item': { base: { flexDirection: 'row' } },
1654
+ 'radio-item': { base: { flexDirection: 'row' } },
1655
+ 'sub-trigger': { base: { flexDirection: 'row' } },
1634
1656
  // The shortcut's reading-end push, restated physically (#1084).
1635
1657
  shortcut: { base: { marginLeft: 'auto', paddingLeft: 'var(--space-lg)' } },
1636
1658
  },
@@ -5374,6 +5396,30 @@ const treeRowSelectors: NonNullable<PartStyles['selectors']> = {
5374
5396
  },
5375
5397
  };
5376
5398
 
5399
+ /**
5400
+ * The tree rows' lynx states (signalxjs/lynx#1256). The web's press wash is
5401
+ * `[data-pressed]:not([data-disabled]):not([data-selected])`; lynx has no
5402
+ * absence classes, so the wash is the plain `pressed` state and a selected
5403
+ * row restores its accent fill below. The web's descendant rule that swaps
5404
+ * the check box's pair on a selected row (`[data-selected] &` on the box)
5405
+ * becomes the ROW's own custom properties: they inherit to the box inside
5406
+ * it. The focus ring is inset (rows sit flush) and drawn as a box-shadow,
5407
+ * which follows the row's radius where lynx's `outline` does not.
5408
+ */
5409
+ const lynxTreeRowStates: Record<string, CssProps> = {
5410
+ pressed: { background: 'var(--color-base-300)' },
5411
+ selected: {
5412
+ '--tree-check': 'var(--tree-on-accent)',
5413
+ '--tree-on-check': 'var(--tree-accent)',
5414
+ },
5415
+ ...lynxFocus({ inset: true }),
5416
+ };
5417
+
5418
+ /** A held selected row keeps its accent fill (the web's `:not([data-selected])`). */
5419
+ const lynxTreeRowSelectors: Record<string, CssProps> = {
5420
+ '&[data-selected][data-pressed]': { background: 'var(--tree-accent)' },
5421
+ };
5422
+
5377
5423
  /**
5378
5424
  * `tickGlyphFallback` for the node check box, whose tick is its `::after`:
5379
5425
  * the geometry drops and the same pseudo carries the glyph, in the medium's
@@ -5524,12 +5570,37 @@ export const treeView: RecipeInput = {
5524
5570
  xl: { root: { base: { '--tree-text': 'var(--text-lg)' } } },
5525
5571
  },
5526
5572
  },
5527
- // The indent, restated physically: logical spellings resolve on iOS but
5528
- // not on Android (measured, signalxjs/lynx#1084), so the emitter refuses
5529
- // them. Physical is the lynx target's norm — no RTL flow there.
5573
+ // lynx (signalxjs/lynx#1256, zero#478). No hover on a touch platform, no
5574
+ // `:not()`, no pseudo-elements, no descendant selectors: each web rule
5575
+ // those carry is restated on the part the runtime stamps. The skin's
5576
+ // `:dir(rtl)` mirror and the `@media` stops have no lynx form (no RTL
5577
+ // flow, no conditions) and stay dropped.
5530
5578
  targets: {
5531
5579
  lynx: {
5532
5580
  parts: {
5581
+ item: { states: lynxTreeRowStates, selectors: lynxTreeRowSelectors },
5582
+ 'branch-trigger': { states: lynxTreeRowStates, selectors: lynxTreeRowSelectors },
5583
+ // `inline-block` is not a lynx display value. The glyph is a
5584
+ // `<text>` part: a 1em box centred on it, so the quarter turn
5585
+ // pivots on the chevron instead of swinging it sideways.
5586
+ 'branch-indicator': { base: { display: 'flex', width: '1em', textAlign: 'center' } },
5587
+ // The mark is a `<text>` child lynx-zero renders (`✓` checked,
5588
+ // `−` indeterminate) in place of the web's clip-path `::after`
5589
+ // tick — clip-path and pseudo-elements are both dropped on
5590
+ // lynx. The glyph is the forced-colors fallback's shape
5591
+ // (`nodeTickFallback`), inked with the box's `-on` pair and
5592
+ // sized by inheritance from the row.
5593
+ 'node-checkbox': {
5594
+ base: {
5595
+ display: 'flex',
5596
+ alignItems: 'center',
5597
+ justifyContent: 'center',
5598
+ color: 'var(--tree-on-check)',
5599
+ },
5600
+ },
5601
+ // The indent, restated physically: logical spellings resolve
5602
+ // on iOS but not on Android (measured, signalxjs/lynx#1084),
5603
+ // so the emitter refuses them.
5533
5604
  'branch-content': { base: { paddingLeft: 'var(--space-lg)' } },
5534
5605
  },
5535
5606
  },
@@ -5633,6 +5704,10 @@ export const input: RecipeInput = {
5633
5704
  selectors: {
5634
5705
  // Same muting, same reason as `number-input/input` (#264).
5635
5706
  '&::placeholder': { color: 'color-mix(in oklab, var(--color-base-content) 60%, transparent)' },
5707
+ // zero draws its own ClearTrigger and clears on Escape, and Firefox
5708
+ // draws no native clear: hide the engine's cancel button everywhere (#446).
5709
+ '&::-webkit-search-cancel-button': { appearance: 'none', display: 'none' },
5710
+ '&::-webkit-search-decoration': { appearance: 'none' },
5636
5711
  },
5637
5712
  },
5638
5713
  // daisy's `label` inside `.input`: a quiet prefix/suffix at one edge,
@@ -6154,7 +6229,13 @@ export const alert: RecipeInput = {
6154
6229
  },
6155
6230
  },
6156
6231
  // Pinned top-right, its glyph on the padding edge. `inherit`
6157
- // is spelled as the root's own ink.
6232
+ // is spelled as the root's own ink. A square chip, the
6233
+ // glyph centred in it: the web's `line-height: 1` + 2xs
6234
+ // padding make an almost-square box, but lynx does not carry
6235
+ // the line-height into the glyph's `<text>`, so the padded
6236
+ // box was a narrow × in a tall line — a 14 × 20pt pill whose
6237
+ // press wash and focus ring drew as vertical ovals
6238
+ // (signalxjs/lynx#1253). The box is sized outright instead.
6158
6239
  close: {
6159
6240
  base: {
6160
6241
  position: 'absolute',
@@ -6162,6 +6243,13 @@ export const alert: RecipeInput = {
6162
6243
  right: 'calc(var(--alert-pad-x) - var(--space-2xs))',
6163
6244
  color: 'var(--color-base-content)',
6164
6245
  fontSize: 'var(--text-md)',
6246
+ display: 'flex',
6247
+ alignItems: 'center',
6248
+ justifyContent: 'center',
6249
+ boxSizing: 'border-box',
6250
+ padding: '0',
6251
+ width: 'calc(var(--text-md) + var(--space-2xs) * 2)',
6252
+ height: 'calc(var(--text-md) + var(--space-2xs) * 2)',
6165
6253
  },
6166
6254
  states: lynxFocus({ gap: 'var(--alert-tint)' }),
6167
6255
  },
@@ -6806,6 +6894,15 @@ export const kbd: RecipeInput = {
6806
6894
  ...lynxSides('border{}Width', 'var(--border)', ['Top', 'Right', 'Left']),
6807
6895
  borderBottomWidth: 'calc(var(--border) * 2)',
6808
6896
  ...lynxSides('border{}Color', 'var(--color-base-300)'),
6897
+ // The web's monospace cap comes from the browser's
6898
+ // UA style for `<kbd>`, not the recipe; lynx has no
6899
+ // UA sheet, so the face is spelled here
6900
+ // (signalxjs/lynx#1254). Concrete names, not a
6901
+ // token: iOS Lynx walks the list with
6902
+ // `UIFont fontWithName:` (Menlo ships on iOS, the
6903
+ // CSS generics do not resolve there), and
6904
+ // `monospace` serves the lynx web target.
6905
+ fontFamily: 'Menlo, monospace',
6809
6906
  },
6810
6907
  },
6811
6908
  },
@@ -7875,6 +7972,28 @@ export const navbar: RecipeInput = {
7875
7972
  xl: { root: { base: { minBlockSize: '6rem', fontSize: 'var(--text-lg)' } } },
7876
7973
  },
7877
7974
  },
7975
+ // Lynx (signalxjs/lynx#1257): `min-block-size` is not a lynx property,
7976
+ // so the bar's height ramp is restated as `min-height`; and a lynx flex
7977
+ // container is only a row when it says so, so the bar and its three
7978
+ // sections spell `flex-direction: row`.
7979
+ targets: {
7980
+ lynx: {
7981
+ parts: {
7982
+ root: { base: { flexDirection: 'row', minHeight: '4rem' } },
7983
+ start: { base: { flexDirection: 'row' } },
7984
+ center: { base: { flexDirection: 'row' } },
7985
+ end: { base: { flexDirection: 'row' } },
7986
+ },
7987
+ variants: {
7988
+ size: {
7989
+ xs: { root: { base: { minHeight: '2.5rem' } } },
7990
+ sm: { root: { base: { minHeight: '3rem' } } },
7991
+ lg: { root: { base: { minHeight: '5rem' } } },
7992
+ xl: { root: { base: { minHeight: '6rem' } } },
7993
+ },
7994
+ },
7995
+ },
7996
+ },
7878
7997
  };
7879
7998
 
7880
7999
  /**
@@ -7934,6 +8053,14 @@ export const navList: RecipeInput = {
7934
8053
  alignItems: 'center',
7935
8054
  gap: 'var(--space-sm)',
7936
8055
  textDecoration: 'none',
8056
+ // Without an href the link is a <button> (#451): drop its chrome.
8057
+ appearance: 'none',
8058
+ background: 'none',
8059
+ border: '0',
8060
+ font: 'inherit',
8061
+ textAlign: 'start',
8062
+ inlineSize: '100%',
8063
+ cursor: 'pointer',
7937
8064
  color: 'var(--nav-ink)',
7938
8065
  padding: 'var(--space-sm) var(--space-lg)',
7939
8066
  borderRadius: 'var(--radius-field)',
@@ -7981,6 +8108,27 @@ export const navList: RecipeInput = {
7981
8108
  xl: { root: { base: { fontSize: 'var(--text-lg)' } }, link: { base: { padding: 'var(--space-lg) var(--space-xl)' } } },
7982
8109
  },
7983
8110
  },
8111
+ // The web's block and inline boxes, restated for lynx (signalxjs/lynx#1259).
8112
+ // No `:hover` on a touch platform, and the link's anatomy declares no
8113
+ // `pressed` flag: a held link has lynx-zero's main-thread press scale.
8114
+ targets: {
8115
+ lynx: {
8116
+ parts: {
8117
+ // `display: block` has no lynx projection: a column, so the
8118
+ // link spans the list as a block `<li>` makes it.
8119
+ item: { base: { display: 'flex', flexDirection: 'column' } },
8120
+ // The icon / label / meta row, explicit (lynx does not
8121
+ // default the direction the way a browser does).
8122
+ link: { base: { flexDirection: 'row' } },
8123
+ // `inline-size` restated physically; the glyph centred in
8124
+ // its column on both axes.
8125
+ icon: { base: { width: '1.25em', flexDirection: 'row', alignItems: 'center' } },
8126
+ // The count's push to the far edge, restated physically —
8127
+ // `margin-inline-start` does not resolve on Android (#1084).
8128
+ meta: { base: { marginLeft: 'auto', flexDirection: 'row' } },
8129
+ },
8130
+ },
8131
+ },
7984
8132
  };
7985
8133
 
7986
8134
  /**
@@ -8090,6 +8238,37 @@ export const breadcrumbs: RecipeInput = {
8090
8238
  xl: { root: { base: { fontSize: 'var(--text-lg)' } } },
8091
8239
  },
8092
8240
  },
8241
+ // Lynx (signalxjs/lynx#1257):
8242
+ // - The list, the items and the ellipsis are explicit rows (a lynx flex
8243
+ // container is only a row when it says so).
8244
+ // - The trigger's `hover` ink is dropped on a touch platform; the
8245
+ // `pressed` flag carries it instead. Its resting ink moves onto a
8246
+ // lynx-only token so the base rule stays a plain var() read: the
8247
+ // emitter bakes a `color-mix` declaration per theme under the host
8248
+ // class, and that baked rule would outrank the pressed one.
8249
+ // - The focus ring is the lynx box-shadow ring (outline has no offset
8250
+ // and ignores the radius there).
8251
+ // - The link's `hover` stays dropped: the link anatomy declares no
8252
+ // pressed flag, so there is nothing on lynx to carry it.
8253
+ // - The separator is a real part on both targets (lynx-zero renders it
8254
+ // as a text glyph), so daisy's `::before` chevron needs no lynx form.
8255
+ targets: {
8256
+ lynx: {
8257
+ tokens: { '--bc-trigger-ink': 'color-mix(in oklch, var(--color-base-content) 75%, transparent)' },
8258
+ parts: {
8259
+ list: { base: { flexDirection: 'row' } },
8260
+ item: { base: { flexDirection: 'row' } },
8261
+ ellipsis: { base: { flexDirection: 'row' } },
8262
+ 'ellipsis-trigger': {
8263
+ base: { color: 'var(--bc-trigger-ink)' },
8264
+ states: {
8265
+ pressed: { color: 'var(--color-base-content)' },
8266
+ 'focus-visible': lynxFocusRing('var(--color-primary)'),
8267
+ },
8268
+ },
8269
+ },
8270
+ },
8271
+ },
8093
8272
  };
8094
8273
 
8095
8274
  /**
@@ -8128,6 +8307,19 @@ const pageTrigger: PartStyles = {
8128
8307
  },
8129
8308
  };
8130
8309
 
8310
+ /** A pagination cell's box on lynx — see the recipe's lynx section. */
8311
+ const pageCellLynx: NonNullable<PartStyles['base']> = {
8312
+ minWidth: 'var(--pg-size)',
8313
+ height: 'var(--pg-size)',
8314
+ flexShrink: '0',
8315
+ };
8316
+
8317
+ /** The four triggers on lynx: the cell box, the held wash + sink, the ring. */
8318
+ const pageTriggerLynx: PartStyles = {
8319
+ base: pageCellLynx,
8320
+ states: { pressed: { background: 'var(--color-base-300)' }, ...lynxFocus() },
8321
+ };
8322
+
8131
8323
  /**
8132
8324
  * Pagination — daisy's join-of-buttons made of standalone btn cells: the
8133
8325
  * quiet base-200 fill, base-300 hover, the current page inverted into the
@@ -8224,13 +8416,35 @@ export const pagination: RecipeInput = {
8224
8416
  xl: { root: { base: { '--pg-size': 'calc(var(--size-field) * 14)', '--pg-font': 'var(--text-lg)' } } },
8225
8417
  },
8226
8418
  },
8227
- // The cell's inline padding, restated physically: logical spellings
8228
- // resolve on iOS but not on Android (measured, signalxjs/lynx#1084), so
8229
- // the emitter refuses them.
8419
+ // Lynx (signalxjs/lynx#1258):
8420
+ // - the cells' size, restated physically: `min-inline-size` and
8421
+ // `block-size` do not resolve on lynx (lynx#1145), so every cell
8422
+ // collapsed to its glyph. Read through `--pg-size`, so the compile
8423
+ // inlines the size steps per part, as it does the web's;
8424
+ // - the item's inline padding, physical: logical spellings resolve on
8425
+ // iOS but not on Android (measured, lynx#1084);
8426
+ // - the press: the web answers a pointer with `:hover`, which a touch
8427
+ // platform drops, so the held cell paints daisy's hover wash with the
8428
+ // 1px sink (`lynxBtnPressed`'s pair) — the current page keeps its
8429
+ // accent fill and only sinks;
8430
+ // - the focus ring as `lynxFocus`: lynx's outline has no offset and
8431
+ // ignores the radius (lynx#1163);
8432
+ // - no row shrink: a cell never squeezes below its size in a narrow row.
8433
+ // The glyphs' rtl flip has no replacement: lynx has no RTL flow.
8230
8434
  targets: {
8231
8435
  lynx: {
8232
8436
  parts: {
8233
- item: { base: { paddingLeft: 'var(--space-2xs)', paddingRight: 'var(--space-2xs)' } },
8437
+ root: { base: { flexDirection: 'row' } },
8438
+ item: {
8439
+ base: { ...pageCellLynx, paddingLeft: 'var(--space-2xs)', paddingRight: 'var(--space-2xs)' },
8440
+ states: lynxFocus(),
8441
+ selectors: { '&[data-pressed][data-state="inactive"]': { background: 'var(--color-base-300)' } },
8442
+ },
8443
+ ellipsis: { base: pageCellLynx },
8444
+ 'first-trigger': pageTriggerLynx,
8445
+ 'prev-trigger': pageTriggerLynx,
8446
+ 'next-trigger': pageTriggerLynx,
8447
+ 'last-trigger': pageTriggerLynx,
8234
8448
  },
8235
8449
  },
8236
8450
  },
@@ -8250,6 +8464,12 @@ const stepInk = (accent: string, role: string): string =>
8250
8464
  `color-mix(in oklab, ${accent} `
8251
8465
  + `${Math.min(ROLE_INK_KEEP[role as keyof typeof roles] ?? 55, 70)}%, var(--color-base-content))`;
8252
8466
 
8467
+ /**
8468
+ * The complete disc's fill: 20% of the accent over base-100, in OKLAB (see
8469
+ * the indicator's `complete` state for why not OKLCH).
8470
+ */
8471
+ const stepTint = (accent: string): string => `color-mix(in oklab, ${accent} 20%, var(--color-base-100))`;
8472
+
8253
8473
  /** A Steps root holding wizard parts (#296) — the panel or the triggers. */
8254
8474
  const STEPS_WIZARD = '&:has(> [data-scope="steps"]:is([data-part="content"], [data-part="prev-trigger"], [data-part="next-trigger"]))';
8255
8475
 
@@ -8367,7 +8587,7 @@ export const steps: RecipeInput = {
8367
8587
  // (warning's yellow came out pink) — which the browser parity
8368
8588
  // check caught once per-step colour put all eight roles on
8369
8589
  // the disc (#112).
8370
- complete: { background: 'color-mix(in oklab, var(--steps-accent) 20%, var(--color-base-100))', color: 'var(--steps-complete-ink)' },
8590
+ complete: { background: stepTint('var(--steps-accent)'), color: 'var(--steps-complete-ink)' },
8371
8591
  inactive: { background: 'var(--color-base-200)', color: 'var(--color-base-content)' },
8372
8592
  invalid: { background: 'var(--color-error)', color: 'var(--color-error-content)' },
8373
8593
  },
@@ -8455,32 +8675,82 @@ export const steps: RecipeInput = {
8455
8675
  xl: { root: { base: { '--steps-ind': 'calc(var(--size-selector) * 9)', '--steps-font': 'var(--text-md)' } } },
8456
8676
  },
8457
8677
  },
8458
- // The bridge's anchors and the vertical item's tail padding, restated
8459
- // physically: logical spellings resolve on iOS but not on Android
8460
- // (measured, signalxjs/lynx#1084), so the emitter refuses them. Physical
8461
- // is the lynx target's norm — no RTL flow there to mirror with.
8678
+ // Lynx. Physical spellings throughout: logical insets, margins and
8679
+ // paddings resolve on iOS but not on Android (measured,
8680
+ // signalxjs/lynx#1084), and `inline-size` / `block-size` do not resolve
8681
+ // at all (lynx#1145) — without the restatement the discs and lines did
8682
+ // not paint. Also (signalxjs/lynx#1258):
8683
+ // - the complete disc's tint and ink read `--steps-accent` through a
8684
+ // colour function, which cannot bake; the base pair is restated over
8685
+ // primary, and each colour already restates the ink on its item, so
8686
+ // the tint joins it there;
8687
+ // - the bridge runs from this disc's edge to the next disc's edge —
8688
+ // `50% + ind/2` for `100% - ind` — instead of centre to centre under
8689
+ // the disc, so it needs no z-index across sibling items; the item
8690
+ // stops clipping (a lynx view's `overflow` defaults to hidden) so the
8691
+ // bridge can reach past its box;
8692
+ // - the `:has()` wizard wrap becomes the `wizard` stamp lynx-zero puts on
8693
+ // the root while a panel or trigger is mounted (raw css below);
8694
+ // - the focus ring as `lynxFocus` (lynx#1163), and Back/Next's press as
8695
+ // daisy's hover wash + sink (`lynxBtnPressed`), `:hover` being dropped.
8462
8696
  targets: {
8463
8697
  lynx: {
8698
+ tokens: {
8699
+ '--steps-complete-ink': stepInk('var(--color-primary)', 'primary'),
8700
+ '--steps-complete-tint': stepTint('var(--color-primary)'),
8701
+ },
8464
8702
  parts: {
8703
+ root: { base: { flexDirection: 'row', overflow: 'visible' } },
8465
8704
  item: {
8705
+ base: { overflow: 'visible' },
8706
+ states: lynxFocus(),
8466
8707
  selectors: {
8467
8708
  '&[data-orientation="vertical"]': { paddingBottom: 'var(--space-lg)' },
8468
8709
  },
8469
8710
  },
8711
+ indicator: {
8712
+ base: { width: 'var(--steps-ind)', height: 'var(--steps-ind)' },
8713
+ states: { complete: { background: 'var(--steps-complete-tint)' } },
8714
+ },
8470
8715
  separator: {
8471
8716
  selectors: {
8472
8717
  '&[data-orientation="horizontal"]': {
8473
- top: 'calc(var(--space-xs) + var(--steps-ind) / 2)',
8474
- left: '50%',
8718
+ top: 'calc(var(--space-xs) + (var(--steps-ind) - var(--border)) / 2)',
8719
+ left: 'calc(50% + var(--steps-ind) / 2)',
8720
+ width: 'calc(100% - var(--steps-ind))',
8721
+ height: 'var(--border)',
8475
8722
  },
8476
8723
  '&[data-orientation="vertical"]': {
8477
8724
  left: 'calc(var(--space-xs) + (var(--steps-ind) - var(--border)) / 2)',
8478
8725
  top: 'calc(var(--space-xs) + var(--steps-ind))',
8479
8726
  bottom: 'calc(var(--space-xs) * -1)',
8727
+ width: 'var(--border)',
8480
8728
  },
8481
8729
  },
8482
8730
  },
8731
+ 'prev-trigger': {
8732
+ base: { ...lynxBtnPad(4), ...lynxBtnFit },
8733
+ states: { pressed: lynxBtnPressed, ...lynxFocus() },
8734
+ },
8735
+ 'next-trigger': {
8736
+ base: { ...lynxBtnPad(4), ...lynxBtnFit, marginLeft: 'auto' },
8737
+ states: { pressed: lynxBtnPressed, ...lynxFocus() },
8738
+ },
8739
+ },
8740
+ variants: {
8741
+ color: Object.fromEntries(ROLES.map((c) => [c, { item: { base: {
8742
+ '--steps-complete-tint': stepTint(`var(--color-${c})`),
8743
+ } } }])),
8483
8744
  },
8745
+ // lynx-zero stamps `wizard` on the root while a Content,
8746
+ // PrevTrigger or NextTrigger is mounted — the web's `:has()`.
8747
+ // A lynx-zero rendering detail, not a modifier an author sets.
8748
+ css: `
8749
+ .zx-steps__root.zx-m-wizard {
8750
+ flex-wrap: wrap;
8751
+ row-gap: var(--space-md);
8752
+ }
8753
+ `,
8484
8754
  },
8485
8755
  },
8486
8756
  };