@ponchia/ui 0.8.1 → 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.
Files changed (85) hide show
  1. package/CHANGELOG.md +149 -3
  2. package/MIGRATIONS.json +117 -27
  3. package/README.md +19 -11
  4. package/behaviors/index.d.ts +0 -2
  5. package/behaviors/index.d.ts.map +1 -1
  6. package/behaviors/index.js +0 -2
  7. package/behaviors/popover.js +4 -4
  8. package/classes/classes.json +48 -10
  9. package/classes/index.d.ts +16 -3
  10. package/classes/index.js +28 -3
  11. package/classes/vscode.css-custom-data.json +10 -10
  12. package/css/app.css +52 -30
  13. package/css/base.css +10 -14
  14. package/css/content.css +23 -21
  15. package/css/core.css +1 -0
  16. package/css/disclosure.css +17 -17
  17. package/css/feedback.css +15 -15
  18. package/css/forms.css +8 -7
  19. package/css/navigation.css +3 -3
  20. package/css/overlay.css +37 -39
  21. package/css/primitives.css +48 -28
  22. package/css/report.css +66 -42
  23. package/css/row.css +154 -0
  24. package/css/state.css +95 -6
  25. package/css/table.css +3 -3
  26. package/css/tokens.css +10 -10
  27. package/css/workbench.css +22 -10
  28. package/dist/bronto.css +1 -1
  29. package/dist/css/app.css +1 -1
  30. package/dist/css/base.css +1 -1
  31. package/dist/css/content.css +1 -1
  32. package/dist/css/disclosure.css +1 -1
  33. package/dist/css/feedback.css +1 -1
  34. package/dist/css/forms.css +1 -1
  35. package/dist/css/navigation.css +1 -1
  36. package/dist/css/overlay.css +1 -1
  37. package/dist/css/primitives.css +1 -1
  38. package/dist/css/report-kit.css +1 -1
  39. package/dist/css/report.css +1 -1
  40. package/dist/css/row.css +1 -0
  41. package/dist/css/state.css +1 -1
  42. package/dist/css/table.css +1 -1
  43. package/dist/css/tokens.css +1 -1
  44. package/dist/css/workbench.css +1 -1
  45. package/docs/adr/0004-prune-unused-adapters.md +5 -1
  46. package/docs/adr/0005-productive-tools-and-editorial-reports.md +58 -0
  47. package/docs/adr/0006-trusted-publishing.md +92 -0
  48. package/docs/architecture.md +16 -23
  49. package/docs/command.md +1 -2
  50. package/docs/compositions.md +110 -0
  51. package/docs/frontier-primitives.md +1 -2
  52. package/docs/migrations/0.8-to-0.9.md +66 -0
  53. package/docs/migrations/0.9-to-0.10.md +47 -0
  54. package/docs/package-contract.md +13 -13
  55. package/docs/reference.md +43 -18
  56. package/docs/reporting.md +15 -9
  57. package/docs/stability.md +20 -55
  58. package/docs/state.md +47 -0
  59. package/docs/theming.md +16 -0
  60. package/docs/usage.md +60 -30
  61. package/llms.txt +7 -18
  62. package/package.json +15 -54
  63. package/tokens/figma.variables.json +20 -20
  64. package/tokens/index.js +10 -10
  65. package/tokens/index.json +20 -20
  66. package/tokens/resolved.json +10 -10
  67. package/tokens/tokens.dtcg.json +20 -20
  68. package/behaviors/modal.d.ts +0 -45
  69. package/behaviors/modal.d.ts.map +0 -1
  70. package/behaviors/modal.js +0 -373
  71. package/qwik/index.d.ts +0 -48
  72. package/qwik/index.d.ts.map +0 -1
  73. package/qwik/index.js +0 -227
  74. package/react/index.d.ts +0 -45
  75. package/react/index.d.ts.map +0 -1
  76. package/react/index.js +0 -165
  77. package/solid/index.d.ts +0 -75
  78. package/solid/index.d.ts.map +0 -1
  79. package/solid/index.js +0 -172
  80. package/svelte/index.d.ts +0 -114
  81. package/svelte/index.d.ts.map +0 -1
  82. package/svelte/index.js +0 -197
  83. package/vue/index.d.ts +0 -116
  84. package/vue/index.d.ts.map +0 -1
  85. package/vue/index.js +0 -266
@@ -6,6 +6,8 @@
6
6
  /* --- Layout composition --- */
7
7
 
8
8
  .ui-stack {
9
+ min-inline-size: 0;
10
+ grid-template-columns: minmax(0, 1fr);
9
11
  display: grid;
10
12
  gap: var(--stack-gap, var(--space-md));
11
13
  }
@@ -169,7 +171,7 @@
169
171
  .ui-app-metrics {
170
172
  display: grid;
171
173
  gap: var(--space-md);
172
- grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
174
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
173
175
  }
174
176
 
175
177
  /* Inside an opt-in .ui-cq container, collapse to one column when the
@@ -201,27 +203,27 @@
201
203
  .ui-stat__label,
202
204
  .ui-app-metric__label {
203
205
  color: var(--text-dim);
204
- font-family: var(--mono);
206
+ font-family: var(--sans);
205
207
  font-size: var(--text-2xs);
206
- letter-spacing: var(--tracking-wide);
207
- text-transform: uppercase;
208
+ letter-spacing: 0;
209
+ text-transform: none;
208
210
  }
209
211
 
210
212
  .ui-stat__value,
211
213
  .ui-app-metric__value {
212
214
  color: var(--text);
213
- font-family: var(--display);
215
+ font-family: var(--sans);
214
216
  font-size: 1.9rem;
215
217
  font-variant-numeric: tabular-nums;
216
218
  font-weight: var(--display-weight-strong);
217
- letter-spacing: 0.02em;
219
+ letter-spacing: 0;
218
220
  line-height: 1.05;
219
221
  overflow-wrap: anywhere; /* break an unspaced ID/hash rather than overflow */
220
222
  }
221
223
 
222
224
  .ui-stat__delta,
223
225
  .ui-app-metric__delta {
224
- font-family: var(--mono);
226
+ font-family: var(--sans);
225
227
  font-size: var(--text-xs);
226
228
  }
227
229
 
@@ -329,18 +331,18 @@
329
331
  color: var(--success);
330
332
  }
331
333
 
332
- /* --- Eyebrow / section label — dot-matrix face --- */
334
+ /* --- Eyebrow / section label — supporting text --- */
333
335
 
334
336
  .ui-eyebrow {
335
337
  /* accent-strong, not accent: this is small bold text and must clear
336
338
  WCAG AA 4.5:1 on the soft/tinted surfaces eyebrows sit on too. */
337
339
  color: var(--accent-text);
338
- font-family: var(--display);
340
+ font-family: var(--sans);
339
341
  font-size: var(--text-xs);
340
342
  font-weight: 700;
341
- letter-spacing: var(--tracking-wide);
343
+ letter-spacing: 0;
342
344
  margin: 0;
343
- text-transform: uppercase;
345
+ text-transform: none;
344
346
  }
345
347
 
346
348
  .ui-eyebrow--muted {
@@ -363,17 +365,17 @@
363
365
  color: var(--button-text);
364
366
  cursor: pointer;
365
367
  display: inline-flex;
366
- font-family: var(--mono);
368
+ font-family: var(--sans);
367
369
  font-size: var(--text-sm);
368
370
  font-weight: 600;
369
371
  gap: 0.45rem;
370
372
  justify-content: center;
371
- letter-spacing: var(--tracking-wide);
373
+ letter-spacing: 0;
372
374
  line-height: 1;
373
375
  min-block-size: 2.4rem;
374
376
  min-inline-size: 2.4rem;
375
377
  padding: 0.66rem 1rem;
376
- text-transform: uppercase;
378
+ text-transform: none;
377
379
  transition:
378
380
  background-color var(--duration-fast) var(--ease-standard),
379
381
  border-color var(--duration-fast) var(--ease-standard),
@@ -554,14 +556,14 @@
554
556
  text-decoration: none;
555
557
  }
556
558
 
557
- /* CTA: the eyebrow-faced action link (accent · display · uppercase),
559
+ /* CTA: the accent action link with a directional cue,
558
560
  composed from the same tokens as .ui-eyebrow + the arrow glyph. */
559
561
  .ui-link--cta {
560
562
  color: var(--accent-text);
561
- font-family: var(--display);
563
+ font-family: var(--sans);
562
564
  font-weight: 700;
563
- letter-spacing: var(--tracking-wide);
564
- text-transform: uppercase;
565
+ letter-spacing: 0;
566
+ text-transform: none;
565
567
  }
566
568
 
567
569
  .ui-link--arrow::after,
@@ -603,14 +605,14 @@
603
605
  border-radius: var(--radius-sm);
604
606
  color: var(--text-soft);
605
607
  display: inline-flex;
606
- font-family: var(--mono);
608
+ font-family: var(--sans);
607
609
  font-size: var(--text-2xs);
608
610
  gap: 0.36rem;
609
- letter-spacing: var(--tracking-wide);
611
+ letter-spacing: 0;
610
612
  line-height: 1;
611
613
  min-block-size: 1.7rem;
612
614
  padding: 0.32rem 0.55rem;
613
- text-transform: uppercase;
615
+ text-transform: none;
614
616
  }
615
617
 
616
618
  .ui-chip--accent {
@@ -619,6 +621,24 @@
619
621
  border-color: var(--accent);
620
622
  }
621
623
 
624
+ /* Static labels in a pane header need less height than a clickable control. */
625
+ .ui-chip--dense {
626
+ min-block-size: 1.25rem;
627
+ padding: 0.15rem 0.4rem;
628
+ }
629
+
630
+ .ui-chip--dense:is(button, a, [role='button']) {
631
+ min-block-size: var(--tap-target-min);
632
+ min-inline-size: var(--tap-target-min);
633
+ }
634
+
635
+ @media (pointer: coarse) {
636
+ .ui-chip--dense:is(button, a, [role='button']) {
637
+ min-block-size: var(--tap-target);
638
+ min-inline-size: var(--tap-target);
639
+ }
640
+ }
641
+
622
642
  /* --- Badge / status pill --- */
623
643
 
624
644
  .ui-badge {
@@ -628,14 +648,14 @@
628
648
  border-radius: var(--radius-sm);
629
649
  color: var(--text-soft);
630
650
  display: inline-flex;
631
- font-family: var(--mono);
651
+ font-family: var(--sans);
632
652
  font-size: var(--text-2xs);
633
653
  font-weight: 700;
634
654
  gap: 0.34rem;
635
- letter-spacing: var(--tracking-wide);
655
+ letter-spacing: 0;
636
656
  line-height: 1;
637
657
  padding: 0.28rem 0.5rem;
638
- text-transform: uppercase;
658
+ text-transform: none;
639
659
  }
640
660
 
641
661
  /* Tone rides the border + tint; text stays the high-contrast neutral
@@ -726,17 +746,17 @@
726
746
 
727
747
  .ui-key-value dt {
728
748
  color: var(--text-dim);
729
- font-family: var(--mono);
749
+ font-family: var(--sans);
730
750
  font-size: var(--text-2xs);
731
751
  font-weight: 700;
732
- letter-spacing: var(--tracking-wide);
752
+ letter-spacing: 0;
733
753
  line-height: 1;
734
- text-transform: uppercase;
754
+ text-transform: none;
735
755
  }
736
756
 
737
757
  .ui-key-value dd {
738
758
  color: var(--text);
739
- font-family: var(--mono);
759
+ font-family: var(--sans);
740
760
  margin: 0;
741
761
  min-inline-size: 0;
742
762
  overflow-wrap: anywhere; /* IDs/hashes/paths are the common value — break, don't overflow */
package/css/report.css CHANGED
@@ -8,19 +8,31 @@
8
8
 
9
9
  .ui-report {
10
10
  /* Declare override-surface tokens first so authors can set them. */
11
- --report-width: 72rem;
11
+ --report-width: 64rem;
12
12
  --report-padding-block: var(--space-2xl);
13
- --report-gap: var(--space-lg);
14
- --report-measure: 74ch;
13
+ --report-gap: var(--space-xl);
14
+ --report-measure: 68ch;
15
15
 
16
16
  color: var(--text-soft);
17
17
  display: grid;
18
+ font-size: 1.125rem;
19
+ line-height: 1.65;
18
20
  gap: var(--report-gap);
19
21
  inline-size: min(100%, var(--report-width));
20
22
  margin-inline: auto;
21
23
  padding: var(--report-padding-block) var(--space-md);
22
24
  }
23
25
 
26
+ /* Keep reading measure independent of a wide figure or evidence table. */
27
+ .ui-report p,
28
+ .ui-report__section > :is(ul, ol, blockquote) {
29
+ max-inline-size: var(--report-measure);
30
+ }
31
+
32
+ .ui-report .ui-prose {
33
+ font-size: inherit;
34
+ }
35
+
24
36
  .ui-report--compact {
25
37
  --report-gap: var(--space-md);
26
38
  --report-padding-block: var(--space-xl);
@@ -74,14 +86,14 @@
74
86
 
75
87
  .ui-report__title {
76
88
  color: var(--text);
77
- font-family: var(--display);
78
- font-size: calc(var(--text-xl) * 1.35);
79
- font-weight: var(--display-weight-strong);
89
+ font-family: var(--sans);
90
+ font-size: clamp(2rem, 4vw, 3rem);
91
+ font-weight: 650;
80
92
  letter-spacing: 0;
81
- line-height: 1.05;
93
+ line-height: 1.15;
82
94
  margin: 0;
83
95
  max-inline-size: var(--report-measure);
84
- text-transform: uppercase;
96
+ text-transform: none;
85
97
  text-wrap: balance;
86
98
  }
87
99
 
@@ -98,14 +110,14 @@
98
110
  color: var(--text-dim);
99
111
  display: flex;
100
112
  flex-wrap: wrap;
101
- font-family: var(--mono);
102
- font-size: var(--text-2xs);
113
+ font-family: var(--sans);
114
+ font-size: var(--text-xs);
103
115
  gap: 0.55rem;
104
116
  letter-spacing: 0;
105
117
  list-style: none;
106
118
  margin: 0;
107
119
  padding: 0;
108
- text-transform: uppercase;
120
+ text-transform: none;
109
121
  }
110
122
 
111
123
  .ui-report__meta > * {
@@ -123,11 +135,22 @@
123
135
  }
124
136
 
125
137
  .ui-report__toc {
126
- border: 1px solid var(--line);
127
- border-radius: var(--radius-md);
138
+ border-block: 1px solid var(--line);
128
139
  display: grid;
129
140
  gap: var(--space-xs);
130
- padding: var(--space-md);
141
+ padding-block: var(--space-md);
142
+ }
143
+
144
+ .ui-report__toc > summary {
145
+ cursor: pointer;
146
+ font-size: var(--text-sm);
147
+ font-weight: 600;
148
+ min-block-size: var(--tap-target);
149
+ padding-block: var(--space-xs);
150
+ }
151
+
152
+ details.ui-report__toc:not([open]) > :not(summary) {
153
+ display: none;
131
154
  }
132
155
 
133
156
  .ui-report__toc ol,
@@ -162,7 +185,7 @@
162
185
 
163
186
  .ui-report__decision {
164
187
  background: var(--panel);
165
- border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
188
+ border: 0;
166
189
  border-inline-start: 3px solid var(--accent);
167
190
  border-radius: var(--radius-md);
168
191
  display: grid;
@@ -172,22 +195,22 @@
172
195
 
173
196
  .ui-report__decision-kicker {
174
197
  color: var(--accent-text);
175
- font-family: var(--mono);
198
+ font-family: var(--sans);
176
199
  font-size: var(--text-2xs);
177
- letter-spacing: var(--tracking-wide);
200
+ letter-spacing: 0;
178
201
  margin: 0;
179
- text-transform: uppercase;
202
+ text-transform: none;
180
203
  }
181
204
 
182
205
  .ui-report__decision-title {
183
206
  color: var(--text);
184
- font-family: var(--display);
207
+ font-family: var(--sans);
185
208
  font-size: var(--text-lg);
186
209
  font-weight: var(--display-weight);
187
210
  letter-spacing: 0;
188
211
  line-height: 1.18;
189
212
  margin: 0;
190
- text-transform: uppercase;
213
+ text-transform: none;
191
214
  text-wrap: balance;
192
215
  }
193
216
 
@@ -202,7 +225,7 @@
202
225
  color: var(--text-dim);
203
226
  display: flex;
204
227
  flex-wrap: wrap;
205
- font-family: var(--mono);
228
+ font-family: var(--sans);
206
229
  font-size: var(--text-2xs);
207
230
  gap: 0.45rem 0.75rem;
208
231
  letter-spacing: 0;
@@ -230,10 +253,10 @@
230
253
 
231
254
  .ui-report__decision-label {
232
255
  color: var(--text-dim);
233
- font-family: var(--mono);
256
+ font-family: var(--sans);
234
257
  font-size: var(--text-2xs);
235
- letter-spacing: var(--tracking-wide);
236
- text-transform: uppercase;
258
+ letter-spacing: 0;
259
+ text-transform: none;
237
260
  }
238
261
 
239
262
  .ui-report__decision-value {
@@ -346,10 +369,10 @@
346
369
  .ui-claim__scope,
347
370
  .ui-claim__refs {
348
371
  color: var(--text-dim);
349
- font-family: var(--mono);
372
+ font-family: var(--sans);
350
373
  font-size: var(--text-2xs);
351
374
  letter-spacing: 0;
352
- text-transform: uppercase;
375
+ text-transform: none;
353
376
  }
354
377
 
355
378
  .ui-claim__basis,
@@ -386,13 +409,13 @@
386
409
 
387
410
  .ui-report__section-head {
388
411
  color: var(--text);
389
- font-family: var(--display);
412
+ font-family: var(--sans);
390
413
  font-size: var(--text-xl);
391
- font-weight: var(--display-weight);
414
+ font-weight: 650;
392
415
  letter-spacing: 0;
393
416
  line-height: 1.1;
394
417
  margin: 0;
395
- text-transform: uppercase;
418
+ text-transform: none;
396
419
  text-wrap: balance;
397
420
  }
398
421
 
@@ -415,11 +438,11 @@
415
438
 
416
439
  .ui-report__caption {
417
440
  color: var(--text-dim);
418
- font-family: var(--mono);
441
+ font-family: var(--sans);
419
442
  font-size: var(--text-2xs);
420
443
  letter-spacing: 0;
421
444
  line-height: 1.5;
422
- text-transform: uppercase;
445
+ text-transform: none;
423
446
  }
424
447
 
425
448
  .ui-evidence-grid {
@@ -446,7 +469,7 @@
446
469
 
447
470
  .ui-evidence-item__meta {
448
471
  color: var(--text-dim);
449
- font-family: var(--mono);
472
+ font-family: var(--sans);
450
473
  font-size: var(--text-2xs);
451
474
  letter-spacing: 0;
452
475
  }
@@ -472,10 +495,10 @@
472
495
  .ui-evidence-item__window,
473
496
  .ui-evidence-item__source {
474
497
  color: var(--text-dim);
475
- font-family: var(--mono);
498
+ font-family: var(--sans);
476
499
  font-size: var(--text-2xs);
477
500
  letter-spacing: 0;
478
- text-transform: uppercase;
501
+ text-transform: none;
479
502
  }
480
503
 
481
504
  .ui-evidence-item__value {
@@ -516,13 +539,13 @@
516
539
 
517
540
  .ui-report__action-status {
518
541
  color: var(--text-dim);
519
- font-family: var(--mono);
542
+ font-family: var(--sans);
520
543
  font-size: var(--text-2xs);
521
544
  grid-column: 2;
522
545
  grid-row: 1;
523
- letter-spacing: var(--tracking-wide);
546
+ letter-spacing: 0;
524
547
  place-self: start end;
525
- text-transform: uppercase;
548
+ text-transform: none;
526
549
  white-space: nowrap;
527
550
  }
528
551
 
@@ -546,10 +569,10 @@
546
569
  .ui-report__action-priority,
547
570
  .ui-report__action-source {
548
571
  color: var(--text-dim);
549
- font-family: var(--mono);
572
+ font-family: var(--sans);
550
573
  font-size: var(--text-2xs);
551
574
  letter-spacing: 0;
552
- text-transform: uppercase;
575
+ text-transform: none;
553
576
  }
554
577
 
555
578
  .ui-report__action-criteria {
@@ -613,10 +636,10 @@
613
636
 
614
637
  .ui-compare__head {
615
638
  color: var(--text-dim);
616
- font-family: var(--mono);
639
+ font-family: var(--sans);
617
640
  font-size: var(--text-2xs);
618
- letter-spacing: var(--tracking-wide);
619
- text-transform: uppercase;
641
+ letter-spacing: 0;
642
+ text-transform: none;
620
643
  }
621
644
 
622
645
  /* A chart is NOT a bronto component — it needs scales + data binding, which the
@@ -660,6 +683,7 @@
660
683
  --line-strong: #b3b3b3;
661
684
 
662
685
  inline-size: auto;
686
+ font-size: 11pt;
663
687
  padding: 0;
664
688
  }
665
689
 
package/css/row.css ADDED
@@ -0,0 +1,154 @@
1
+ /* ==========================================================================
2
+ row — the dense selectable row. IN THE DEFAULT BUNDLE.
3
+
4
+ Every workbench grows a list of these: a search result, a file in an
5
+ explorer, an outline entry, a backlink, an inbox item, a commit. They are not
6
+ table rows — there is no column contract and no header — and they are not
7
+ menu items, because they persist rather than dismissing. But they are all the
8
+ same object: a full-width clickable line with a leading mark, a title that
9
+ gives up space first, and trailing metadata that does not.
10
+
11
+ Bronto already had this shape and it was imprisoned. `.ui-menu__item` is
12
+ exactly it, minus the persistence — so a consumer building an explorer either
13
+ claimed to be a menu or wrote the row again. One downstream workbench had
14
+ SIXTY-THREE families of it, about 1,200 lines, each re-deciding the selected
15
+ state, the hover, the ellipsis and the coarse-pointer floor.
16
+
17
+ `.ui-menu__item` now composes this, so the two cannot drift.
18
+
19
+ BOUNDARY. The host owns what a row means, what selects it, and what its
20
+ columns are. Bronto owns the line: its rhythm, its states, and the fact that
21
+ the title is the part that truncates. Rows that carry a severity should reach
22
+ for `.ui-severity-row` in `state.css` instead — that one adds the tone gutter.
23
+
24
+ In core rather than opt-in, unusually for a new surface, because
25
+ `.ui-menu__item` composes it and a core component cannot depend on a leaf.
26
+ ========================================================================== */
27
+
28
+ .ui-row {
29
+ align-items: center;
30
+ background: transparent;
31
+ border: 0;
32
+ border-radius: var(--radius-sm);
33
+ color: var(--text-soft);
34
+ cursor: pointer;
35
+ display: flex;
36
+ font: inherit;
37
+ gap: 0.5rem;
38
+
39
+ /* The companion to `__title`'s ellipsis, and the demo proved it is not
40
+ optional: a row is usually a flex or grid ITEM, whose automatic minimum
41
+ size is its min-content width — and `__title` is `white-space: nowrap`, so
42
+ that min-content is the WHOLE title. Without this a long title stops the
43
+ row shrinking and pushes its container past the viewport instead of
44
+ truncating. Caught at 320/360/390px by the overflow specs. */
45
+ min-inline-size: 0;
46
+ padding: 0.4rem 0.5rem;
47
+ text-align: start;
48
+ inline-size: 100%;
49
+ }
50
+
51
+ /* A row is usually a <button> or an <a>; when it is neither, it still needs to
52
+ look inert rather than pressable. */
53
+ .ui-row:not(button, a, [role='button'], [role='option'], [tabindex]) {
54
+ cursor: default;
55
+ }
56
+
57
+ /* The title gives up space FIRST — it is the only part of a row that can be
58
+ truncated without losing a fact. Everything else keeps its size. */
59
+ .ui-row__title {
60
+ flex: 1 1 auto;
61
+ min-inline-size: 0;
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ white-space: nowrap;
65
+ }
66
+
67
+ /* Trailing facts: a count, an age, a path fragment. Never the thing that
68
+ shrinks, because a half-rendered number is worse than no number. */
69
+ .ui-row__meta {
70
+ color: var(--text-dim);
71
+ flex: none;
72
+ font-family: var(--mono);
73
+ font-size: var(--text-2xs);
74
+ }
75
+
76
+ /* A leading mark — an icon, a glyph, a status dot. Sized by the host. */
77
+ .ui-row__mark {
78
+ display: inline-flex;
79
+ flex: none;
80
+ }
81
+
82
+ /* A row that wraps to a second line: a result with a snippet under its title.
83
+ The parts stack rather than sharing the baseline. */
84
+ .ui-row--stacked {
85
+ align-items: stretch;
86
+ flex-direction: column;
87
+ gap: 0.15rem;
88
+ }
89
+
90
+ .ui-row--stacked .ui-row__title {
91
+ flex: none;
92
+ }
93
+
94
+ /* Rows in a list read as one object when they share a rule; rows in a menu
95
+ float. `--ruled` is the list form. */
96
+ .ui-row--ruled {
97
+ border-block-end: 1px solid var(--line);
98
+ border-radius: 0;
99
+ }
100
+
101
+ /* --- States, and WHICH attribute is yours to use.
102
+
103
+ `aria-selected` is only valid on a row that has a role which accepts it —
104
+ `option` inside a `listbox`, or `row` / `tab` / `gridcell` / `treeitem`. On a
105
+ bare `<button>` it is invalid ARIA, and axe rates that CRITICAL. This project
106
+ shipped exactly that mistake in its own demo and the a11y gate caught it.
107
+
108
+ So: `aria-current` for a row that is merely the current one (the common
109
+ case), `aria-selected` only when the row genuinely carries an option/row
110
+ role, and `.is-selected` when neither applies. All three paint the same. --- */
111
+
112
+ .ui-row[aria-selected='true'],
113
+ .ui-row[aria-current]:not([aria-current='false']),
114
+ .ui-row.is-selected {
115
+ background: var(--panel-soft);
116
+ color: var(--text);
117
+ }
118
+
119
+ @media (hover: hover) {
120
+ .ui-row:is(button, a, [role='button'], [role='option'], [tabindex]):hover {
121
+ background: var(--bg-accent);
122
+ color: var(--text);
123
+ }
124
+ }
125
+
126
+ .ui-row:focus-visible {
127
+ background: var(--bg-accent);
128
+ color: var(--text);
129
+ outline: 2px solid var(--focus-ring);
130
+ outline-offset: -2px;
131
+ }
132
+
133
+ /* Touch: a row is a primary target in a list, so it floats to the full
134
+ tap-target rather than the 24px minimum. */
135
+ @media (pointer: coarse) {
136
+ .ui-row {
137
+ min-block-size: var(--tap-target);
138
+ }
139
+ }
140
+
141
+ /* Forced colours strip the tinted hover/selected background, which would leave
142
+ the current row indistinguishable from its siblings. Re-assert a system
143
+ Highlight, the same way the menu and combobox rows do. */
144
+ @media (forced-colors: active) {
145
+ .ui-row[aria-selected='true'],
146
+ .ui-row[aria-current]:not([aria-current='false']),
147
+ .ui-row.is-selected,
148
+ .ui-row:hover,
149
+ .ui-row:focus-visible {
150
+ forced-color-adjust: none;
151
+ background: Highlight;
152
+ color: HighlightText;
153
+ }
154
+ }