actual-css 0.4.0 → 0.4.2

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 (83) hide show
  1. package/CHANGELOG.md +84 -35
  2. package/dist/actual.css +1 -20
  3. package/dist/actual.full.css +692 -221
  4. package/dist/actual.full.js +1 -1
  5. package/dist/actual.full.min.css +1 -1
  6. package/dist/actual.min.css +1 -1
  7. package/docs/design-notes/app-ui.md +33 -0
  8. package/docs/design-notes/enhancement-contract.md +25 -0
  9. package/docs/design-notes/grid.md +177 -4
  10. package/docs/design-notes/references.md +1 -1
  11. package/docs/navigation.json +7 -1
  12. package/docs/pages/components/alert.md +5 -0
  13. package/docs/pages/components/app-navigation.md +34 -0
  14. package/docs/pages/components/avatar.md +10 -0
  15. package/docs/pages/components/badge.md +2 -0
  16. package/docs/pages/components/button.md +30 -0
  17. package/docs/pages/components/card.md +5 -1
  18. package/docs/pages/components/fab.md +2 -0
  19. package/docs/pages/components/indicator.md +52 -0
  20. package/docs/pages/components/list.md +62 -0
  21. package/docs/pages/components/navbar.md +6 -0
  22. package/docs/pages/components/rating.md +68 -0
  23. package/docs/pages/components/steps.md +57 -0
  24. package/docs/pages/enhancements/flyout.md +2 -2
  25. package/docs/pages/enhancements/tabs.md +1 -2
  26. package/docs/pages/examples/overview.md +8 -0
  27. package/docs/pages/forms/otp.md +32 -0
  28. package/docs/pages/forms/states-and-sizes.md +3 -3
  29. package/docs/pages/guides/integrating-actual-css.md +6 -0
  30. package/docs/pages/layout/app-layout.md +57 -0
  31. package/docs/pages/layout/app-shell.md +28 -7
  32. package/docs/pages/layout/center.md +12 -1
  33. package/docs/pages/layout/choosing.md +15 -0
  34. package/docs/pages/layout/grid.md +41 -8
  35. package/docs/pages/layout/sidebar-layout.md +19 -0
  36. package/docs/pages/layout/stack.md +17 -0
  37. package/docs/pages/patterns/icon-slot.md +61 -0
  38. package/docs/pages/patterns/structured-lists.md +38 -40
  39. package/package.json +3 -2
  40. package/scripts/reserved-classes.json +17 -0
  41. package/src/css/components/actions.css +1 -0
  42. package/src/css/components/app-nav.css +76 -0
  43. package/src/css/components/avatar.css +4 -0
  44. package/src/css/components/badge.css +1 -13
  45. package/src/css/components/breadcrumb.css +1 -0
  46. package/src/css/components/button.css +8 -38
  47. package/src/css/components/card.css +11 -11
  48. package/src/css/components/chat.css +0 -6
  49. package/src/css/components/drawer.css +0 -6
  50. package/src/css/components/fab.css +1 -7
  51. package/src/css/components/index.css +5 -0
  52. package/src/css/components/indicator.css +47 -0
  53. package/src/css/components/list.css +83 -0
  54. package/src/css/components/menu.css +0 -7
  55. package/src/css/components/modal.css +0 -17
  56. package/src/css/components/navbar.css +8 -15
  57. package/src/css/components/pagination.css +1 -0
  58. package/src/css/components/rating.css +101 -0
  59. package/src/css/components/steps.css +123 -0
  60. package/src/css/components/tab.css +21 -22
  61. package/src/css/components/tooltip.css +1 -10
  62. package/src/css/core/focus.css +0 -8
  63. package/src/css/core/theme.css +0 -10
  64. package/src/css/core/tokens.css +1 -2
  65. package/src/css/effects/aura.css +1 -10
  66. package/src/css/forms/choice-card.css +6 -15
  67. package/src/css/forms/form-actions.css +1 -0
  68. package/src/css/forms/otp.css +7 -2
  69. package/src/css/forms/range.css +14 -4
  70. package/src/css/layout/app-layout.css +102 -0
  71. package/src/css/layout/app-shell.css +1 -1
  72. package/src/css/layout/center.css +1 -0
  73. package/src/css/layout/cluster.css +1 -0
  74. package/src/css/layout/container-query.css +6 -4
  75. package/src/css/layout/grid.css +25 -11
  76. package/src/css/layout/index.css +4 -2
  77. package/src/css/layout/scroll-snap.css +1 -0
  78. package/src/css/layout/sidebar-layout.css +23 -1
  79. package/src/css/layout/switcher.css +1 -0
  80. package/src/css/layout/topbar.css +1 -0
  81. package/src/css/typography/prose.css +4 -0
  82. package/src/js/tooltip.js +2 -1
  83. package/docs/pages/layout/list.md +0 -41
@@ -1,47 +1,45 @@
1
1
  # Structured Lists
2
2
 
3
- Use native lists plus layout primitives for rich content rows. Reset list chrome only when markers are not part of the content.
3
+ Choose list markup from the content semantics, then add only the layout or
4
+ component contract the collection needs.
4
5
 
5
- ```html demo
6
- <figure class="stack">
7
- <figcaption><strong>Most played songs this week</strong></figcaption>
6
+ | Need | Use |
7
+ | --- | --- |
8
+ | Bullets or order carry meaning | Native `<ul>` or `<ol>` |
9
+ | One leading element and one flexible content region | [`.media`](../layout/media.md) |
10
+ | Repeated application rows with leading, content, and trailing regions | [`.list`](../components/list.md) |
11
+ | A list of navigation links | [`.nav-list`](./navigation-list.md) |
12
+ | A richer collection with its own item structure | Native list plus layout primitives and components |
8
13
 
9
- <ul class="list-reset stack gap-none">
10
- <li class="media items-center py" style="border-block-end: var(--border-width) solid var(--border)">
11
- <div class="avatar">
12
- <img src="https://i.pravatar.cc/48?img=5" alt="Dio Lupa" />
13
- </div>
14
- <div class="cluster">
15
- <div class="stack grow" style="--gap: var(--space-10)">
16
- <strong>Dio Lupa</strong>
17
- <span class="muted">Remaining Reason</span>
18
- </div>
19
- <span class="muted">3:45</span>
20
- <button class="btn ghost" type="button" aria-label="Play">
21
- <i class="ti ti-player-play" aria-hidden="true"></i>
22
- </button>
23
- </div>
24
- </li>
14
+ `.media` and `.list` are not interchangeable. `.media` is geometry for one
15
+ two-part composition and requires exactly two direct children. `.list` owns the
16
+ repeated-row treatment: three regions, row padding, minimum touch height,
17
+ dividers, navigable-row hover, and supporting text.
25
18
 
26
- <li class="media items-center py" style="border-block-end: var(--border-width) solid var(--border)">
27
- <div class="avatar">
28
- <img src="https://i.pravatar.cc/48?img=10" alt="Astral Planes" />
29
- </div>
30
- <div class="cluster">
31
- <div class="stack grow" style="--gap: var(--space-10)">
32
- <strong>Astral Planes</strong>
33
- <span class="muted">Neon Drift</span>
34
- </div>
35
- <span class="muted">4:12</span>
36
- <button class="btn ghost" type="button" aria-label="Play">
37
- <i class="ti ti-player-play" aria-hidden="true"></i>
38
- </button>
39
- </div>
40
- </li>
41
- </ul>
42
- </figure>
43
- ```
19
+ Keep native markers when they communicate sequence, rank, or grouping. Remove
20
+ them with `.list-reset` only when they are not part of the content. A reset
21
+ changes list chrome; it does not create a row component.
44
22
 
45
- Use `.actions` for action controls and `.nav-list` for navigation links. For structured content items, compose `.list-reset`, `.stack`, `.cluster`, `.media`, and components directly.
23
+ For a collection whose items are complete compositions rather than application
24
+ rows, keep the native list and compose each item independently:
46
25
 
47
- `.media` is a two-slot object: it lays out exactly two children — the leading element and one content column. Trailing metadata and actions belong inside the content column (nest a `.cluster` and put `.grow` on the flexible part), never as extra row children: additional children silently wrap onto a second grid row.
26
+ ```html demo
27
+ <ul class="list-reset grid" style="--grid-min: 16rem">
28
+ <li>
29
+ <article class="card stack">
30
+ <span class="badge">Guide</span>
31
+ <h2>Choose a layout</h2>
32
+ <p>Match intrinsic behavior to the structure of the content.</p>
33
+ <a href="#layout-guide">Read the guide</a>
34
+ </article>
35
+ </li>
36
+ <li>
37
+ <article class="card stack">
38
+ <span class="badge">Reference</span>
39
+ <h2>Compose spacing</h2>
40
+ <p>Use shared rhythm without coupling content to a component.</p>
41
+ <a href="#spacing-reference">View the reference</a>
42
+ </article>
43
+ </li>
44
+ </ul>
45
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "actual-css",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Plain CSS component framework with semantic classes, universal variants, small tokens, theme hooks, and progressive enhancements.",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.4.0",
@@ -115,6 +115,7 @@
115
115
  "build:docs": "bun run build:themes && bun scripts/build-docs.js",
116
116
  "watch:docs": "bun run build:themes && bun scripts/build-docs.js --watch",
117
117
  "check:docs": "bun scripts/check-docs.js",
118
+ "check:doc-classes": "bun scripts/check-doc-classes.js",
118
119
  "check:compat": "bun scripts/check-compat.js",
119
120
  "check:css-api": "bun scripts/check-css-api.js",
120
121
  "check:color-space": "bun scripts/check-color-space.js",
@@ -135,7 +136,7 @@
135
136
  "check:sync": "bun scripts/check-sync.js",
136
137
  "test": "bun test",
137
138
  "test:changed": "bun test --changed=master",
138
- "build:all": "bun run lint && bun run build:dist && bun run build:js && bun run build:docs && bun run check:docs && bun run check:compat && bun run check:css-api && bun run check:color-space && bun run check:architecture && bun run check:enhance && bun run generate:reserved && bun run check:reserved && bun run check:sync && bun run check:links && bun run check:templates && bun run test && bun run build:size",
139
+ "build:all": "bun run lint && bun run build:dist && bun run build:js && bun run build:docs && bun run check:docs && bun run check:doc-classes && bun run check:compat && bun run check:css-api && bun run check:color-space && bun run check:architecture && bun run check:enhance && bun run generate:reserved && bun run check:reserved && bun run check:sync && bun run check:links && bun run check:templates && bun run test && bun run build:size",
139
140
  "prepublishOnly": "bun run build:all"
140
141
  },
141
142
  "devDependencies": {
@@ -10,6 +10,9 @@
10
10
  "align-self-center",
11
11
  "align-self-end",
12
12
  "align-self-start",
13
+ "app-layout",
14
+ "app-main",
15
+ "app-nav",
13
16
  "app-shell",
14
17
  "aura",
15
18
  "aura-glow",
@@ -26,6 +29,7 @@
26
29
  "border-context",
27
30
  "border-inline-end",
28
31
  "border-inline-start",
32
+ "bottom",
29
33
  "breadcrumb",
30
34
  "btn",
31
35
  "callout",
@@ -71,6 +75,7 @@
71
75
  "column-start-8",
72
76
  "column-start-9",
73
77
  "compact",
78
+ "complete",
74
79
  "container-query",
75
80
  "cursor-pointer",
76
81
  "danger",
@@ -124,6 +129,8 @@
124
129
  "had-scrollbar",
125
130
  "has-modal-open",
126
131
  "icon-only",
132
+ "indicator",
133
+ "indicator-item",
127
134
  "inline-size-full",
128
135
  "input",
129
136
  "input-icon",
@@ -146,6 +153,12 @@
146
153
  "link",
147
154
  "link-muted",
148
155
  "link-plain",
156
+ "list",
157
+ "list-item",
158
+ "list-item-content",
159
+ "list-item-text",
160
+ "list-item-title",
161
+ "list-item-trailing",
149
162
  "list-reset",
150
163
  "margin-block-end-auto",
151
164
  "margin-block-start-auto",
@@ -204,7 +217,9 @@
204
217
  "radius-sm-context",
205
218
  "raised",
206
219
  "range",
220
+ "rating",
207
221
  "required-mark",
222
+ "reverse",
208
223
  "row-gap-context",
209
224
  "scroll-snap",
210
225
  "scroll-target",
@@ -224,7 +239,9 @@
224
239
  "sr-only",
225
240
  "stable-gutter",
226
241
  "stack",
242
+ "start",
227
243
  "status-bar",
244
+ "steps",
228
245
  "sticky",
229
246
  "stretch",
230
247
  "subtle",
@@ -11,6 +11,7 @@
11
11
  --gap: var(--space-20);
12
12
 
13
13
  display: flex;
14
+ flex-direction: row;
14
15
  flex-wrap: wrap;
15
16
  align-items: center;
16
17
  gap: var(--gap);
@@ -0,0 +1,76 @@
1
+ /*
2
+ * Primary application navigation. The component owns the navigation surface
3
+ * and item states; app-layout owns whether that surface is a bottom bar or
4
+ * labelled side navigation.
5
+ *
6
+ * Public hooks:
7
+ * --app-nav-size
8
+ * --app-nav-gap
9
+ */
10
+ :where(.app-nav) {
11
+ --ui-bg: initial;
12
+ --ui-fg: initial;
13
+ --ui-border: initial;
14
+ }
15
+
16
+ .app-nav {
17
+ --app-nav-size: 4rem;
18
+ --app-nav-gap: var(--space-10);
19
+
20
+ position: sticky;
21
+ inset-block-end: 0;
22
+ z-index: var(--z-sticky);
23
+ display: grid;
24
+ grid-auto-flow: column;
25
+ grid-auto-columns: minmax(0, 1fr);
26
+ gap: var(--app-nav-gap);
27
+ min-block-size: calc(var(--app-nav-size) + env(safe-area-inset-bottom));
28
+ padding-block: var(--space-10) max(var(--space-10), env(safe-area-inset-bottom));
29
+ padding-inline: var(--space-10);
30
+ border-block-start: var(--border-width) solid var(--ui-border, var(--border));
31
+ background: var(--ui-bg, var(--surface));
32
+ color: var(--ui-fg, var(--text-muted));
33
+ }
34
+
35
+ .app-nav > a {
36
+ display: grid;
37
+ grid-template-rows: auto auto;
38
+ place-content: center;
39
+ justify-items: center;
40
+ gap: var(--space-10);
41
+ min-inline-size: 0;
42
+ min-block-size: var(--control-size-lg);
43
+ padding-inline: var(--space-10);
44
+ border-radius: var(--radius);
45
+ color: inherit;
46
+ font-size: var(--font-size-xs);
47
+ font-weight: var(--font-weight-medium);
48
+ line-height: var(--line-height-tight);
49
+ text-align: center;
50
+ text-decoration: none;
51
+ overflow-wrap: anywhere;
52
+ }
53
+
54
+ .app-nav > a > :where(svg, img, [aria-hidden="true"]) {
55
+ inline-size: 1.5rem;
56
+ block-size: 1.5rem;
57
+ font-size: 1.5rem;
58
+ line-height: 1;
59
+ }
60
+
61
+ .app-nav > a:hover {
62
+ background: var(--surface-subtle);
63
+ color: var(--text);
64
+ }
65
+
66
+ .app-nav > a:where([aria-current]:not([aria-current="false"])) {
67
+ background: var(--state-selected);
68
+ color: var(--state-selected-fg);
69
+ font-weight: var(--font-weight-bold);
70
+ }
71
+
72
+ @media print {
73
+ .app-nav {
74
+ display: none;
75
+ }
76
+ }
@@ -69,6 +69,9 @@
69
69
  }
70
70
  }
71
71
 
72
+ /* The initials element (a span or an accessible <abbr title="…">) fills the box.
73
+ text-decoration: none neutralizes the UA dotted underline on <abbr title="…">
74
+ inside the circular avatar. */
72
75
  .avatar > :first-child:not(:where(img, picture, .badge)) {
73
76
  display: inline-grid;
74
77
  place-items: center;
@@ -76,6 +79,7 @@
76
79
  block-size: 100%;
77
80
  overflow: hidden;
78
81
  border-radius: inherit;
82
+ text-decoration: none;
79
83
  }
80
84
 
81
85
  .avatar > img,
@@ -180,21 +180,9 @@ a.badge[aria-disabled="true"] {
180
180
  background: ButtonText;
181
181
  }
182
182
 
183
- :where(a.badge, button.badge):hover:not(:where(:disabled, [aria-disabled="true"])) {
184
- outline: var(--border-width) solid ButtonText;
185
- outline-offset: 2px;
186
- }
187
-
188
- .badge > button:not(:disabled):hover {
189
- outline: var(--border-width) solid currentColor;
190
- outline-offset: 1px;
191
- }
192
-
193
- button.badge:disabled,
194
183
  .badge[aria-disabled="true"] {
195
- border-color: GrayText;
196
- background: Canvas;
197
184
  color: GrayText;
185
+ border-color: GrayText;
198
186
  }
199
187
  }
200
188
  @media print {
@@ -6,6 +6,7 @@
6
6
  */
7
7
  .breadcrumb {
8
8
  display: flex;
9
+ flex-direction: row;
9
10
  flex-wrap: wrap;
10
11
  align-items: center;
11
12
  gap: var(--space-10);
@@ -92,7 +92,8 @@
92
92
 
93
93
  .btn.icon-only {
94
94
  inline-size: var(--btn-min-size);
95
- padding-inline: 0;
95
+ block-size: var(--btn-min-size);
96
+ padding: 0;
96
97
  }
97
98
 
98
99
  @supports (color: color-mix(in oklch, red, white)) {
@@ -164,14 +165,15 @@
164
165
  --ui-fg: var(--intent, currentColor);
165
166
  --ui-border: transparent;
166
167
  --btn-radius: var(--radius-sm);
167
- --btn-border-block-end-color: transparent;
168
- --btn-border-block-end-width: var(--border-width);
169
168
 
170
169
  min-block-size: auto;
171
170
  padding-inline: 0;
172
171
  inline-size: fit-content;
173
172
  max-inline-size: 100%;
174
- border-color: transparent;
173
+ /* No border at all: a link reads through its underline, and the inherited
174
+ .btn border made transparent would turn into a visible box in forced
175
+ colors. :focus-visible keeps its own outline. */
176
+ border: 0;
175
177
  text-decoration: underline;
176
178
  text-underline-offset: 0.18em;
177
179
  }
@@ -232,44 +234,12 @@ a.btn[aria-disabled="true"] {
232
234
  }
233
235
 
234
236
  @media (forced-colors: active) {
235
- .btn {
236
- border-color: ButtonText;
237
- background: ButtonFace;
238
- color: ButtonText;
239
- box-shadow: none;
240
- }
241
-
242
- .btn.link {
243
- border-color: transparent;
244
- background: Canvas;
245
- color: LinkText;
246
- }
247
-
248
- .btn:is([aria-pressed="true"], [aria-current="page"]):not(.link) {
249
- border-color: Highlight;
250
- background: Highlight;
251
- color: HighlightText;
252
- forced-color-adjust: none;
253
- }
254
-
255
- .btn:is([aria-pressed="true"], [aria-current="page"]):not(.link):focus-visible {
256
- outline: var(--focus-outline);
257
- box-shadow: none;
258
- }
259
-
260
- .btn:hover:not(:where(:disabled, [aria-disabled="true"], .link)) {
261
- outline: var(--border-width) solid ButtonText;
262
- outline-offset: 2px;
263
- }
264
-
265
- .btn:disabled,
266
237
  a.btn[aria-disabled="true"] {
267
- border-color: GrayText;
268
- background: Canvas;
269
238
  color: GrayText;
270
- forced-color-adjust: auto;
239
+ border-color: GrayText;
271
240
  }
272
241
  }
242
+
273
243
  @media print {
274
244
  :is(button, input[type="button"], input[type="submit"], input[type="reset"]).btn {
275
245
  display: none !important;
@@ -4,11 +4,14 @@
4
4
  * Surface, border, radius, padding, density, and elevation stay local here.
5
5
  * Direct header/footer children are structural slots; a direct footer is
6
6
  * anchored to the card's bottom edge when extra block space is available (so
7
- * price/action rows align across equal-height cards in a grid). Page layout
8
- * remains the job of markup and layout primitives outside the card.
7
+ * price/action rows align across equal-height cards in a grid). A bare card
8
+ * owns its direct-child rhythm; a layout primitive on the same element takes
9
+ * over that layout. Page layout remains the job of markup and layout
10
+ * primitives outside the card.
9
11
  *
10
12
  * Public hooks:
11
13
  * --card-pad
14
+ * --card-gap
12
15
  * --card-radius
13
16
  * --card-max-inline-size
14
17
  *
@@ -32,6 +35,7 @@
32
35
 
33
36
  .card {
34
37
  --card-pad: var(--space-40);
38
+ --card-gap: var(--space-30);
35
39
  --card-radius: var(--radius-lg);
36
40
  --card-max-inline-size: none;
37
41
  --card-bg: var(--ui-bg, var(--surface-raised));
@@ -58,10 +62,14 @@
58
62
  :where(.card) {
59
63
  display: flex;
60
64
  flex-direction: column;
65
+ gap: var(--card-gap);
61
66
  }
62
67
 
63
- .card > * {
68
+ /* Native block margins would add to flex gap because flex-item margins never
69
+ collapse. Zero specificity keeps intentional child utilities available. */
70
+ :where(.card) > * {
64
71
  min-inline-size: 0;
72
+ margin-block: 0;
65
73
  }
66
74
 
67
75
  .card > :where(header, footer) {
@@ -88,14 +96,6 @@
88
96
  margin-block-start: auto;
89
97
  }
90
98
 
91
- .card > :first-child {
92
- margin-block-start: 0;
93
- }
94
-
95
- .card > :last-child {
96
- margin-block-end: 0;
97
- }
98
-
99
99
  .card.raised {
100
100
  box-shadow: var(--shadow);
101
101
  }
@@ -97,9 +97,3 @@
97
97
  column-gap: 0;
98
98
  }
99
99
  }
100
-
101
- @media (forced-colors: active) {
102
- .chat-bubble {
103
- border-color: CanvasText;
104
- }
105
- }
@@ -138,12 +138,6 @@ dialog.drawer nav {
138
138
  }
139
139
  }
140
140
 
141
- @media (forced-colors: active) {
142
- dialog.drawer::backdrop {
143
- background: Canvas;
144
- }
145
- }
146
-
147
141
  @media (prefers-reduced-motion: no-preference) {
148
142
  dialog.drawer.is-static {
149
143
  animation: actual-dialog-static var(--duration-slow) var(--ease);
@@ -68,6 +68,7 @@
68
68
  max-inline-size: 16rem;
69
69
  padding: var(--space-10) var(--space-20);
70
70
  border-radius: var(--radius);
71
+ border: var(--border-width) solid transparent;
71
72
  background: var(--surface);
72
73
  color: var(--text);
73
74
  box-shadow: var(--shadow);
@@ -90,13 +91,6 @@
90
91
  transform: rotate(45deg);
91
92
  }
92
93
 
93
- @media (forced-colors: active) {
94
- .fab-label {
95
- border: var(--border-width) solid CanvasText;
96
- box-shadow: none;
97
- }
98
- }
99
-
100
94
  @media print {
101
95
  .fab {
102
96
  display: none;
@@ -27,11 +27,15 @@
27
27
 
28
28
  /* Display */
29
29
  @import "./avatar.css";
30
+ @import "./indicator.css";
30
31
  @import "./key.css";
31
32
  @import "./chat.css";
32
33
  @import "./fab.css";
34
+ @import "./rating.css";
35
+ @import "./steps.css";
33
36
 
34
37
  /* Navigation */
38
+ @import "./app-nav.css";
35
39
  @import "./navbar.css";
36
40
  @import "./breadcrumb.css";
37
41
  @import "./pagination.css";
@@ -39,6 +43,7 @@
39
43
  @import "./scrollspy.css";
40
44
 
41
45
  /* Data */
46
+ @import "./list.css";
42
47
  @import "./table.css";
43
48
  @import "./meter.css";
44
49
 
@@ -0,0 +1,47 @@
1
+ /*
2
+ * Indicator — generic corner positioning for overlaid component content.
3
+ *
4
+ * The container only establishes the containing block. The item owns no
5
+ * paint, size, or ring so badges and other components keep their own visual
6
+ * contract.
7
+ *
8
+ * Internal:
9
+ * --indicator-translate-x
10
+ * --indicator-translate-y
11
+ */
12
+ .indicator {
13
+ position: relative;
14
+ }
15
+
16
+ .indicator-item {
17
+ --indicator-translate-x: 50%;
18
+ --indicator-translate-y: -50%;
19
+
20
+ position: absolute;
21
+ inset-block-start: 0;
22
+ inset-inline-end: 0;
23
+ z-index: 1;
24
+ transform: translate(var(--indicator-translate-x), var(--indicator-translate-y));
25
+ }
26
+
27
+ .indicator-item.start {
28
+ --indicator-translate-x: -50%;
29
+
30
+ inset-inline-start: 0;
31
+ inset-inline-end: auto;
32
+ }
33
+
34
+ .indicator-item.bottom {
35
+ --indicator-translate-y: 50%;
36
+
37
+ inset-block-start: auto;
38
+ inset-block-end: 0;
39
+ }
40
+
41
+ .indicator-item:dir(rtl) {
42
+ --indicator-translate-x: -50%;
43
+ }
44
+
45
+ .indicator-item.start:dir(rtl) {
46
+ --indicator-translate-x: 50%;
47
+ }
@@ -0,0 +1,83 @@
1
+ /*
2
+ * Application list — repeated rows with optional leading and trailing regions.
3
+ * Content determines the number of lines; the component only owns the row
4
+ * geometry, dividers, and supporting-text treatment.
5
+ *
6
+ * Public hooks:
7
+ * --list-item-min-size
8
+ * --list-item-pad-block
9
+ * --list-item-pad-inline
10
+ * --list-item-gap
11
+ * --list-divider
12
+ */
13
+ .list {
14
+ --list-item-min-size: var(--control-size-lg);
15
+ --list-item-pad-block: var(--space-30);
16
+ --list-item-pad-inline: 0;
17
+ --list-item-gap: var(--gap);
18
+ --list-divider: var(--border-width) solid var(--border);
19
+
20
+ display: grid;
21
+ gap: 0;
22
+ margin: 0;
23
+ padding: 0;
24
+ border-block-start: var(--list-divider);
25
+ list-style: none;
26
+ }
27
+
28
+ .list > li {
29
+ margin: 0;
30
+ }
31
+
32
+ .list > :where(.list-item),
33
+ .list > li > .list-item {
34
+ display: grid;
35
+ grid-template-columns: auto minmax(0, 1fr) auto;
36
+ align-items: center;
37
+ gap: var(--list-item-gap);
38
+ min-block-size: var(--list-item-min-size);
39
+ padding-block: var(--list-item-pad-block);
40
+ padding-inline: var(--list-item-pad-inline);
41
+ }
42
+
43
+ .list > .list-item + .list-item,
44
+ .list > li + li {
45
+ border-block-start: var(--list-divider);
46
+ }
47
+
48
+ a.list-item {
49
+ color: inherit;
50
+ text-decoration: none;
51
+ }
52
+
53
+ a.list-item:hover {
54
+ background: var(--surface-subtle);
55
+ }
56
+
57
+ .list-item-content {
58
+ min-inline-size: 0;
59
+ }
60
+
61
+ .list-item-title,
62
+ .list-item-text {
63
+ display: block;
64
+ margin: 0;
65
+ }
66
+
67
+ .list-item-text {
68
+ color: var(--text-muted);
69
+ font-size: var(--font-size-sm);
70
+ overflow-wrap: anywhere;
71
+ }
72
+
73
+ .list-item-trailing {
74
+ justify-self: end;
75
+ min-inline-size: 0;
76
+ }
77
+
78
+ @media print {
79
+ .list > :where(.list-item),
80
+ .list > li > .list-item {
81
+ break-inside: avoid;
82
+ }
83
+ }
@@ -126,10 +126,3 @@
126
126
  border: 0;
127
127
  border-block-start: var(--border-width) solid var(--border);
128
128
  }
129
-
130
- @media (forced-colors: active) {
131
- .menu-item:focus-visible {
132
- outline: var(--border-width) solid ButtonText;
133
- outline-offset: -1px;
134
- }
135
- }
@@ -239,23 +239,6 @@ html.has-modal-open.had-scrollbar {
239
239
  }
240
240
  }
241
241
 
242
- @media (forced-colors: active) {
243
- dialog.modal {
244
- border-color: ButtonText;
245
- background: Canvas;
246
- color: CanvasText;
247
- box-shadow: none;
248
- }
249
-
250
- dialog.modal::backdrop {
251
- background: Canvas;
252
- }
253
-
254
- .dialog-icon {
255
- border: var(--border-width) solid CanvasText;
256
- }
257
- }
258
-
259
242
  /* Close controls. A close button is an action attached to a surface, so it
260
243
  never participates in the content flow. The modal and the drawer share the
261
244
  same simple placement — absolute at the panel's top inline-end, inside the