@sigx/zero-daisyui 0.9.0 → 0.10.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.
package/dist/report.json CHANGED
@@ -10286,6 +10286,17 @@
10286
10286
  "what": "@property registrations, @layer, light-dark()/prefers-color-scheme",
10287
10287
  "detail": "omitted: colors are baked per theme block and switching is a class swap, so there is nothing left for them to do"
10288
10288
  },
10289
+ {
10290
+ "where": "lynx tokens",
10291
+ "what": "rem lengths (114)",
10292
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small"
10293
+ },
10294
+ {
10295
+ "where": "lynx recipe for \"grid\"",
10296
+ "what": "rem lengths (1)",
10297
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10298
+ "scope": "grid"
10299
+ },
10289
10300
  {
10290
10301
  "where": "lynx recipe for \"tabs\".\"list\"",
10291
10302
  "what": "display: inline-flex",
@@ -10298,6 +10309,12 @@
10298
10309
  "detail": "calc-holding custom-property chain inlined: value substituted into 0 consumer declaration(s) across 5 compound(s) and the definition dropped — lynx drops any declaration consuming var() of a property whose value holds calc() (measured, signalxjs/lynx#1075)",
10299
10310
  "scope": "tabs"
10300
10311
  },
10312
+ {
10313
+ "where": "lynx recipe for \"tabs\"",
10314
+ "what": "rem lengths (1)",
10315
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10316
+ "scope": "tabs"
10317
+ },
10301
10318
  {
10302
10319
  "where": "lynx recipe for \"switch\"",
10303
10320
  "what": "--switch-p",
@@ -10328,6 +10345,12 @@
10328
10345
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10329
10346
  "scope": "dialog"
10330
10347
  },
10348
+ {
10349
+ "where": "lynx recipe for \"dialog\"",
10350
+ "what": "rem lengths (2)",
10351
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10352
+ "scope": "dialog"
10353
+ },
10331
10354
  {
10332
10355
  "where": "lynx recipe for \"popover\".\"trigger\"",
10333
10356
  "what": "display: inline-flex",
@@ -10340,18 +10363,42 @@
10340
10363
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10341
10364
  "scope": "popover"
10342
10365
  },
10366
+ {
10367
+ "where": "lynx recipe for \"popover\"",
10368
+ "what": "rem lengths (1)",
10369
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10370
+ "scope": "popover"
10371
+ },
10343
10372
  {
10344
10373
  "where": "lynx recipe for \"tooltip\".\"trigger\"",
10345
10374
  "what": "display: inline-flex",
10346
10375
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10347
10376
  "scope": "tooltip"
10348
10377
  },
10378
+ {
10379
+ "where": "lynx recipe for \"tooltip\"",
10380
+ "what": "rem lengths (1)",
10381
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10382
+ "scope": "tooltip"
10383
+ },
10384
+ {
10385
+ "where": "lynx recipe for \"hover-card\"",
10386
+ "what": "rem lengths (1)",
10387
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10388
+ "scope": "hover-card"
10389
+ },
10349
10390
  {
10350
10391
  "where": "lynx recipe for \"menu\".\"trigger\"",
10351
10392
  "what": "display: inline-flex",
10352
10393
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10353
10394
  "scope": "menu"
10354
10395
  },
10396
+ {
10397
+ "where": "lynx recipe for \"menu\"",
10398
+ "what": "rem lengths (2)",
10399
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10400
+ "scope": "menu"
10401
+ },
10355
10402
  {
10356
10403
  "where": "lynx recipe for \"checkbox\".\"root\"",
10357
10404
  "what": "display: inline-flex",
@@ -10364,6 +10411,12 @@
10364
10411
  "detail": "calc-holding custom-property chain inlined: value substituted into 2 consumer declaration(s) across 6 compound(s) and the definition dropped — lynx drops any declaration consuming var() of a property whose value holds calc() (measured, signalxjs/lynx#1075)",
10365
10412
  "scope": "checkbox"
10366
10413
  },
10414
+ {
10415
+ "where": "lynx recipe for \"checkbox\"",
10416
+ "what": "rem lengths (7)",
10417
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10418
+ "scope": "checkbox"
10419
+ },
10367
10420
  {
10368
10421
  "where": "lynx recipe for \"radio-group\".\"item\"",
10369
10422
  "what": "display: inline-flex",
@@ -10376,6 +10429,12 @@
10376
10429
  "detail": "calc-holding custom-property chain inlined: value substituted into 2 consumer declaration(s) across 6 compound(s) and the definition dropped — lynx drops any declaration consuming var() of a property whose value holds calc() (measured, signalxjs/lynx#1075)",
10377
10430
  "scope": "radio-group"
10378
10431
  },
10432
+ {
10433
+ "where": "lynx recipe for \"radio-group\"",
10434
+ "what": "rem lengths (6)",
10435
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10436
+ "scope": "radio-group"
10437
+ },
10379
10438
  {
10380
10439
  "where": "lynx recipe for \"progress\"",
10381
10440
  "what": "--progress-track-size",
@@ -10394,6 +10453,12 @@
10394
10453
  "detail": "calc-holding custom-property chain inlined: value substituted into 6 consumer declaration(s) across 5 compound(s) and the definition dropped — lynx drops any declaration consuming var() of a property whose value holds calc() (measured, signalxjs/lynx#1075)",
10395
10454
  "scope": "slider"
10396
10455
  },
10456
+ {
10457
+ "where": "lynx recipe for \"slider\"",
10458
+ "what": "rem lengths (2)",
10459
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10460
+ "scope": "slider"
10461
+ },
10397
10462
  {
10398
10463
  "where": "lynx recipe for \"select\".\"root\"",
10399
10464
  "what": "display: inline-flex",
@@ -10412,12 +10477,24 @@
10412
10477
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10413
10478
  "scope": "select"
10414
10479
  },
10480
+ {
10481
+ "where": "lynx recipe for \"select\"",
10482
+ "what": "rem lengths (14)",
10483
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10484
+ "scope": "select"
10485
+ },
10415
10486
  {
10416
10487
  "where": "lynx recipe for \"button\".\"root\"",
10417
10488
  "what": "display: inline-flex",
10418
10489
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10419
10490
  "scope": "button"
10420
10491
  },
10492
+ {
10493
+ "where": "lynx recipe for \"button\"",
10494
+ "what": "rem lengths (2)",
10495
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10496
+ "scope": "button"
10497
+ },
10421
10498
  {
10422
10499
  "where": "lynx recipe for \"avatar\"",
10423
10500
  "what": "--avatar-size",
@@ -10436,6 +10513,12 @@
10436
10513
  "detail": "calc-holding custom-property chain inlined: value substituted into 2 consumer declaration(s) across 5 compound(s) and the definition dropped — lynx drops any declaration consuming var() of a property whose value holds calc() (measured, signalxjs/lynx#1075)",
10437
10514
  "scope": "avatar-group"
10438
10515
  },
10516
+ {
10517
+ "where": "lynx recipe for \"toast\"",
10518
+ "what": "rem lengths (2)",
10519
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10520
+ "scope": "toast"
10521
+ },
10439
10522
  {
10440
10523
  "where": "lynx recipe for \"combobox\".\"root\"",
10441
10524
  "what": "display: inline-flex",
@@ -10460,6 +10543,12 @@
10460
10543
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10461
10544
  "scope": "combobox"
10462
10545
  },
10546
+ {
10547
+ "where": "lynx recipe for \"combobox\"",
10548
+ "what": "rem lengths (2)",
10549
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10550
+ "scope": "combobox"
10551
+ },
10463
10552
  {
10464
10553
  "where": "lynx recipe for \"toggle\".\"root\"",
10465
10554
  "what": "display: inline-flex",
@@ -10490,6 +10579,12 @@
10490
10579
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10491
10580
  "scope": "number-input"
10492
10581
  },
10582
+ {
10583
+ "where": "lynx recipe for \"number-input\"",
10584
+ "what": "rem lengths (1)",
10585
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10586
+ "scope": "number-input"
10587
+ },
10493
10588
  {
10494
10589
  "where": "lynx recipe for \"rating-group\".\"root\"",
10495
10590
  "what": "display: inline-flex",
@@ -10616,6 +10711,12 @@
10616
10711
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10617
10712
  "scope": "join"
10618
10713
  },
10714
+ {
10715
+ "where": "lynx recipe for \"navbar\"",
10716
+ "what": "rem lengths (5)",
10717
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10718
+ "scope": "navbar"
10719
+ },
10619
10720
  {
10620
10721
  "where": "lynx recipe for \"nav-list\".\"icon\"",
10621
10722
  "what": "display: inline-flex",
@@ -10730,11 +10831,23 @@
10730
10831
  "detail": "calc-holding custom-property chain inlined: value substituted into 1 consumer declaration(s) across 5 compound(s) and the definition dropped — lynx drops any declaration consuming var() of a property whose value holds calc() (measured, signalxjs/lynx#1075)",
10731
10832
  "scope": "file-upload"
10732
10833
  },
10834
+ {
10835
+ "where": "lynx recipe for \"carousel\"",
10836
+ "what": "rem lengths (10)",
10837
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10838
+ "scope": "carousel"
10839
+ },
10733
10840
  {
10734
10841
  "where": "lynx recipe for \"countdown\".\"root\"",
10735
10842
  "what": "display: inline-flex",
10736
10843
  "detail": "rewritten to display: flex — lynx has no inline formatting context, and an unsupported display value keeps the default linear layout (signalxjs/lynx#1075)",
10737
10844
  "scope": "countdown"
10845
+ },
10846
+ {
10847
+ "where": "lynx recipe for \"diff\"",
10848
+ "what": "rem lengths (10)",
10849
+ "detail": "rewritten to px at 16px/rem — lynx resolves rem against its 14px default page font size (measured, signalxjs/lynx#1183), which would draw every rem-based size 12.5% small",
10850
+ "scope": "diff"
10738
10851
  }
10739
10852
  ],
10740
10853
  "dropped": [
@@ -12965,7 +13078,7 @@
12965
13078
  },
12966
13079
  {
12967
13080
  "where": "lynx recipe for \"drawer\".\"panel\"",
12968
- "what": "translate: var(--drawer-travel) 0",
13081
+ "what": "translate: var(--drawer-travel)",
12969
13082
  "detail": "the standalone translate property resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, spell the motion as a transform function (transform: translateX(...) translateY(...)) in the recipe's lynx target section",
12970
13083
  "scope": "drawer"
12971
13084
  },
@@ -13011,6 +13124,72 @@
13011
13124
  "detail": "inset-inline-end resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13012
13125
  "scope": "drawer"
13013
13126
  },
13127
+ {
13128
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13129
+ "what": "selectors[\"&:where([data-placement=\"top\"], [data-placement=\"bottom\"])\"]",
13130
+ "detail": "not expressible in the class grammar — dropped; supply a lynx replacement in the recipe target section",
13131
+ "scope": "drawer"
13132
+ },
13133
+ {
13134
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13135
+ "what": "insetBlockStart: 0",
13136
+ "detail": "inset-block-start resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13137
+ "scope": "drawer"
13138
+ },
13139
+ {
13140
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13141
+ "what": "insetBlockEnd: auto",
13142
+ "detail": "inset-block-end resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13143
+ "scope": "drawer"
13144
+ },
13145
+ {
13146
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13147
+ "what": "insetInlineStart: 0",
13148
+ "detail": "inset-inline-start resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13149
+ "scope": "drawer"
13150
+ },
13151
+ {
13152
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13153
+ "what": "insetInlineEnd: 0",
13154
+ "detail": "inset-inline-end resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13155
+ "scope": "drawer"
13156
+ },
13157
+ {
13158
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13159
+ "what": "marginInline: auto",
13160
+ "detail": "margin-inline resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13161
+ "scope": "drawer"
13162
+ },
13163
+ {
13164
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13165
+ "what": "insetBlockStart: auto",
13166
+ "detail": "inset-block-start resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13167
+ "scope": "drawer"
13168
+ },
13169
+ {
13170
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13171
+ "what": "insetBlockEnd: 0",
13172
+ "detail": "inset-block-end resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13173
+ "scope": "drawer"
13174
+ },
13175
+ {
13176
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13177
+ "what": "insetInlineStart: 0",
13178
+ "detail": "inset-inline-start resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13179
+ "scope": "drawer"
13180
+ },
13181
+ {
13182
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13183
+ "what": "insetInlineEnd: 0",
13184
+ "detail": "inset-inline-end resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13185
+ "scope": "drawer"
13186
+ },
13187
+ {
13188
+ "where": "lynx recipe for \"drawer\".\"panel\"",
13189
+ "what": "marginInline: auto",
13190
+ "detail": "margin-inline resolves on iOS but not on Android (measured, signalxjs/lynx#1084) — cross-platform-asymmetric, treated as unsupported; dropped, restate the geometry with a physical spelling (top/right/bottom/left, margin-*/padding-*) in the recipe's lynx target section",
13191
+ "scope": "drawer"
13192
+ },
13014
13193
  {
13015
13194
  "where": "lynx recipe for \"drawer\".\"panel\"",
13016
13195
  "what": "at[\"starting-style\"]",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigx/zero-daisyui",
3
- "version": "0.9.0",
3
+ "version": "0.10.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.9.0"
65
+ "@sigx/zero": "^0.10.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "typescript": "^7.0.2",
69
- "@sigx/zero": "^0.9.0",
70
- "@sigx/zero-kit": "^0.9.0"
69
+ "@sigx/zero": "^0.10.0",
70
+ "@sigx/zero-kit": "^0.10.0"
71
71
  },
72
72
  "publishConfig": {
73
73
  "access": "public"
package/src/recipes.ts CHANGED
@@ -2939,6 +2939,38 @@ const fieldControl: NonNullable<PartStyles['base']> = {
2939
2939
  */
2940
2940
  const SELECT_CLEARABLE = '[data-scope="select"][data-part="root"]:has(> [data-scope="select"][data-part="clear-trigger"]) &';
2941
2941
 
2942
+ /**
2943
+ * The select trigger's lynx steps — `[inline padding in --size-field units,
2944
+ * font-size step]` — as the size variants set them (`lynxBtnPad` and the
2945
+ * web ramp's `fontSize`). One table, so the clear-trigger's offset below
2946
+ * cannot drift from the trigger it sits in.
2947
+ */
2948
+ const SELECT_LYNX_STEPS = {
2949
+ xs: [2, 'xs'],
2950
+ sm: [3, 'sm'],
2951
+ md: [4, 'sm'],
2952
+ lg: [5, 'md'],
2953
+ xl: [6, 'lg'],
2954
+ } as const satisfies Record<keyof typeof FIELD_STEPS, readonly [number, string]>;
2955
+
2956
+ /**
2957
+ * Where the lynx clear-trigger's 1.5rem chip sits at one size step
2958
+ * (signalxjs/lynx#1184): centred in the field — the root is exactly the
2959
+ * trigger's height, so half the field less half the chip, from the top —
2960
+ * and one `--space-xs` short of the chevron's 1em box, which sits inside the
2961
+ * trigger's border and end padding at that step's font size. Physical
2962
+ * `top`/`right` and direct `calc(var())` only: lynx resolves no logical
2963
+ * insets on Android and no `min()`, and drops a `var()` that holds a
2964
+ * `calc()`.
2965
+ */
2966
+ const lynxSelectClear = (step: keyof typeof SELECT_LYNX_STEPS): NonNullable<PartStyles['base']> => {
2967
+ const [pad, text] = SELECT_LYNX_STEPS[step];
2968
+ return {
2969
+ top: `calc(var(--size-field) * ${FIELD_STEPS[step] / 2} - 0.75rem)`,
2970
+ right: `calc(var(--border) + var(--size-field) * ${pad} + var(--text-${text}) + var(--space-xs))`,
2971
+ };
2972
+ };
2973
+
2942
2974
  export const select: RecipeInput = {
2943
2975
  component: 'select',
2944
2976
  // Accent as text/border ink only — daisy's highlighted item is a neutral
@@ -3144,9 +3176,23 @@ export const select: RecipeInput = {
3144
3176
  // A touch list has no highlight: the pressed item takes the
3145
3177
  // highlighted item's wash.
3146
3178
  item: { states: { pressed: { background: 'var(--color-base-200)' } } },
3179
+ // The × and the ▾ get a spacing contract (signalxjs/lynx#1184).
3180
+ // The web offsets the clear-trigger by "the md padding + 1em",
3181
+ // and the 1em is the clear-trigger's own text-sm: at lg/xl the
3182
+ // trigger's padding and chevron both grow, so the × slid onto
3183
+ // the ▾. Here the chevron is a 1em box (right-aligned, so an
3184
+ // unclearable select looks as before) and the clear-trigger a
3185
+ // 1.5rem square (WCAG 2.5.8's target) placed per size beside
3186
+ // it — see `lynxSelectClear`. The web's `min()` height and
3187
+ // `margin-block: auto` centring are dropped on lynx, which
3188
+ // left the box stretched to the field's full height: its
3189
+ // focus ring was a tall pill. The ring is inset, so it hugs
3190
+ // the chip and can never reach the chevron, and no gap shadow
3191
+ // paints past the chip's rounded corners.
3192
+ indicator: { base: { width: '1em', textAlign: 'right' } },
3147
3193
  'clear-trigger': {
3148
- base: { top: 'var(--space-xs)', bottom: 'var(--space-xs)', right: 'calc(var(--size-field) * 4 + 1em + var(--space-xs))', minWidth: '1.5rem' },
3149
- states: lynxFocus(),
3194
+ base: { ...lynxSelectClear('md'), width: '1.5rem', height: '1.5rem', minWidth: '1.5rem', boxSizing: 'border-box' },
3195
+ states: lynxFocus({ inset: true }),
3150
3196
  },
3151
3197
  },
3152
3198
  variants: {
@@ -3155,7 +3201,10 @@ export const select: RecipeInput = {
3155
3201
  color: Object.fromEntries(ROLES.map((c) => [c, { popup: { base: {
3156
3202
  '--select-accent': `var(--color-${c})`,
3157
3203
  } } }])),
3158
- size: { ...lynxBtnSizes('trigger'), md: { trigger: { base: lynxBtnPad(4) } } },
3204
+ size: Object.fromEntries((Object.keys(SELECT_LYNX_STEPS) as (keyof typeof SELECT_LYNX_STEPS)[]).map((step) => [step, {
3205
+ trigger: { base: lynxBtnPad(SELECT_LYNX_STEPS[step][0]) },
3206
+ 'clear-trigger': { base: lynxSelectClear(step) },
3207
+ }])),
3159
3208
  },
3160
3209
  },
3161
3210
  },
@@ -7337,9 +7386,11 @@ export const steps: RecipeInput = {
7337
7386
  /**
7338
7387
  * The modal sheet's slide (#83): in from its edge, back out to it.
7339
7388
  *
7340
- * `translate` is physical, so the travel is a custom property that flips with
7341
- * the placement AND the direction — off the reading start is leftward in LTR
7342
- * and rightward in RTL (the `rtl` hedge, as everywhere here). Keyed on
7389
+ * `translate` is physical, so the travel is a custom property — the whole
7390
+ * `x y` pair — that flips with the placement AND the direction: off the
7391
+ * reading start is leftward in LTR and rightward in RTL (the `rtl` hedge, as
7392
+ * everywhere here), while a `top` / `bottom` sheet travels on Y and mirrors
7393
+ * in neither (#291). Keyed on
7343
7394
  * `data-l-dock="sheet"`, the regime, which holds through the exit where
7344
7395
  * `:modal` does not, so the slide-out leaves from the sheet's own box.
7345
7396
  * Opacity stays at 1: the travel is the transition. Each direction rides the
@@ -7353,16 +7404,19 @@ const sheetSlide = (enter: string, exit: string): PartStyles => {
7353
7404
  return `translate ${tempo}, display ${duration} allow-discrete, overlay ${duration} allow-discrete`;
7354
7405
  };
7355
7406
  return {
7356
- base: { '--drawer-travel': '-100%' },
7407
+ base: { '--drawer-travel': '-100% 0' },
7357
7408
  selectors: {
7358
- '&[data-placement="end"]': { '--drawer-travel': '100%' },
7359
- [`&[data-placement="start"]${rtl}`]: { '--drawer-travel': '100%' },
7360
- [`&[data-placement="end"]${rtl}`]: { '--drawer-travel': '-100%' },
7361
- [sheet]: { opacity: '1', translate: 'var(--drawer-travel) 0', transition: travel(exit) },
7409
+ '&[data-placement="end"]': { '--drawer-travel': '100% 0' },
7410
+ [`&[data-placement="start"]${rtl}`]: { '--drawer-travel': '100% 0' },
7411
+ [`&[data-placement="end"]${rtl}`]: { '--drawer-travel': '-100% 0' },
7412
+ // The block edges travel on Y, and no direction mirrors them (#291).
7413
+ '&[data-placement="top"]': { '--drawer-travel': '0 -100%' },
7414
+ '&[data-placement="bottom"]': { '--drawer-travel': '0 100%' },
7415
+ [sheet]: { opacity: '1', translate: 'var(--drawer-travel)', transition: travel(exit) },
7362
7416
  [open]: { translate: 'none', transition: travel(enter) },
7363
7417
  },
7364
7418
  at: {
7365
- 'starting-style': { selectors: { [open]: { opacity: '1', translate: 'var(--drawer-travel) 0' } } },
7419
+ 'starting-style': { selectors: { [open]: { opacity: '1', translate: 'var(--drawer-travel)' } } },
7366
7420
  'reduced-motion': { selectors: { [sheet]: { transition: 'none' }, [open]: { transition: 'none' } } },
7367
7421
  },
7368
7422
  };
@@ -7432,6 +7486,38 @@ export const drawer: RecipeInput = {
7432
7486
  },
7433
7487
  '&[data-placement="start"][data-l-dock="sheet"]': { insetInlineStart: '0', insetInlineEnd: 'auto' },
7434
7488
  '&[data-placement="end"][data-l-dock="sheet"]': { insetInlineStart: 'auto', insetInlineEnd: '0' },
7489
+ /**
7490
+ * The block edges (#291): a sheet across the viewport's width,
7491
+ * pinned with `inset-block-*` — nothing here mirrors in RTL. Its
7492
+ * height is this recipe's: content-sized up to most of the
7493
+ * viewport, so the scrim stays in reach. Full width by default —
7494
+ * `measure` still caps the INLINE size (centred by the auto
7495
+ * margins), which the `:where()` keeps below the layout step
7496
+ * table's specificity whatever order the files load in.
7497
+ */
7498
+ '&:where([data-placement="top"], [data-placement="bottom"])': { '--l-measure': 'none' },
7499
+ '&[data-placement="top"][data-l-dock="sheet"]': {
7500
+ insetBlockStart: '0',
7501
+ insetBlockEnd: 'auto',
7502
+ insetInlineStart: '0',
7503
+ insetInlineEnd: '0',
7504
+ marginInline: 'auto',
7505
+ blockSize: 'auto',
7506
+ maxBlockSize: '85dvh',
7507
+ borderEndStartRadius: 'var(--radius-box)',
7508
+ borderEndEndRadius: 'var(--radius-box)',
7509
+ },
7510
+ '&[data-placement="bottom"][data-l-dock="sheet"]': {
7511
+ insetBlockStart: 'auto',
7512
+ insetBlockEnd: '0',
7513
+ insetInlineStart: '0',
7514
+ insetInlineEnd: '0',
7515
+ marginInline: 'auto',
7516
+ blockSize: 'auto',
7517
+ maxBlockSize: '85dvh',
7518
+ borderStartStartRadius: 'var(--radius-box)',
7519
+ borderStartEndRadius: 'var(--radius-box)',
7520
+ },
7435
7521
  },
7436
7522
  }),
7437
7523
  backdrop: {