@zeyos/zx 5.0.0 → 5.3.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 (154) hide show
  1. package/CHANGELOG.md +198 -0
  2. package/README.md +2 -1
  3. package/dist/types/components/account-menu/account-menu.d.ts +8 -0
  4. package/dist/types/components/activity-list/activity-list.d.ts +9 -1
  5. package/dist/types/components/app-icon/app-icon.d.ts +14 -2
  6. package/dist/types/components/app-sidebar/app-sidebar.d.ts +288 -14
  7. package/dist/types/components/calendar/calendar.d.ts +67 -5
  8. package/dist/types/components/card-view/card-view.d.ts +243 -4
  9. package/dist/types/components/card-view/record-card.d.ts +11 -0
  10. package/dist/types/components/context-menu/context-menu.d.ts +6 -2
  11. package/dist/types/components/data-filter/data-filter.d.ts +4 -4
  12. package/dist/types/components/dropdown/dropdown.d.ts +22 -7
  13. package/dist/types/components/field/field.d.ts +30 -0
  14. package/dist/types/components/fieldset/external-adapter.d.ts +83 -0
  15. package/dist/types/components/fieldset/fieldset.d.ts +7 -0
  16. package/dist/types/components/file-list/file-list.d.ts +35 -3
  17. package/dist/types/components/filter/filter.d.ts +127 -3
  18. package/dist/types/components/filter-panel/filter-panel.d.ts +36 -7
  19. package/dist/types/components/launcher/launcher.d.ts +8 -0
  20. package/dist/types/components/list-toolbar/list-toolbar.d.ts +15 -6
  21. package/dist/types/components/menu-button/menu-button.d.ts +6 -0
  22. package/dist/types/components/message/message.d.ts +14 -1
  23. package/dist/types/components/modal/modal.d.ts +30 -0
  24. package/dist/types/components/module-bar/module-bar.d.ts +395 -0
  25. package/dist/types/components/pagination/pagination.d.ts +17 -3
  26. package/dist/types/components/select/select.d.ts +6 -0
  27. package/dist/types/components/sheet/sheet.d.ts +15 -0
  28. package/dist/types/components/table/table.d.ts +265 -17
  29. package/dist/types/components/view/record-view.d.ts +59 -2
  30. package/dist/types/components/view-settings/view-settings.d.ts +879 -0
  31. package/dist/types/components/workspace-switcher/workspace-switcher.d.ts +327 -0
  32. package/dist/types/core/component.d.ts +12 -2
  33. package/dist/types/core/i18n.d.ts +27 -3
  34. package/dist/types/core/keyboard.d.ts +98 -1
  35. package/dist/types/core/messages.d.ts +382 -0
  36. package/dist/types/core/overlay-host.d.ts +28 -1
  37. package/dist/types/core/overlay-stack.d.ts +260 -0
  38. package/dist/types/index.d.ts +5 -2
  39. package/dist/types/internal/app-rail.d.ts +38 -0
  40. package/dist/types/internal/menu-items.d.ts +71 -3
  41. package/dist/types/zeyos/index.d.ts +1 -0
  42. package/dist/types/zeyos/launcher.d.ts +9 -0
  43. package/dist/types/zeyos/module-bar.d.ts +176 -0
  44. package/dist/types/zeyos/query.d.ts +31 -5
  45. package/dist/types/zeyos/table.d.ts +245 -8
  46. package/dist/types/zeyos/view.d.ts +16 -2
  47. package/dist/zx-zeyos.esm.js +4422 -430
  48. package/dist/zx-zeyos.esm.min.js +5 -5
  49. package/dist/zx.css +1472 -133
  50. package/dist/zx.esm.js +7433 -854
  51. package/dist/zx.esm.min.js +8 -8
  52. package/dist/zx.global.js +7433 -854
  53. package/dist/zx.global.min.js +8 -8
  54. package/dist/zx.min.css +1 -1
  55. package/docs/api.json +937 -119
  56. package/docs/llms.md +531 -63
  57. package/docs/llms.txt +6 -2
  58. package/package.json +1 -1
  59. package/src/components/account-menu/account-menu.js +12 -0
  60. package/src/components/activity-list/activity-list.js +27 -1
  61. package/src/components/app-icon/app-icon.css +13 -2
  62. package/src/components/app-icon/app-icon.js +11 -1
  63. package/src/components/app-rail/app-rail.css +19 -0
  64. package/src/components/app-sidebar/app-sidebar.css +204 -3
  65. package/src/components/app-sidebar/app-sidebar.js +646 -40
  66. package/src/components/breadcrumb/breadcrumb.css +1 -1
  67. package/src/components/calendar/calendar.css +1 -1
  68. package/src/components/calendar/calendar.js +26 -52
  69. package/src/components/card/card.css +2 -2
  70. package/src/components/card-view/card-view.css +76 -5
  71. package/src/components/card-view/card-view.js +514 -20
  72. package/src/components/card-view/record-card.js +14 -3
  73. package/src/components/code-editor/code-editor.css +1 -1
  74. package/src/components/code-editor/field-adapter.js +9 -2
  75. package/src/components/context-menu/context-menu.js +8 -2
  76. package/src/components/copy/copy-input.css +1 -1
  77. package/src/components/data-filter/data-filter.js +2 -2
  78. package/src/components/date-picker/time-picker.css +2 -2
  79. package/src/components/dock/dock.css +5 -4
  80. package/src/components/dropdown/dropdown.js +157 -72
  81. package/src/components/field/field.js +33 -3
  82. package/src/components/fieldset/external-adapter.js +363 -0
  83. package/src/components/fieldset/fieldset.js +10 -59
  84. package/src/components/file-list/file-list.js +144 -21
  85. package/src/components/filter/filter.css +86 -2
  86. package/src/components/filter/filter.js +300 -8
  87. package/src/components/filter-panel/filter-panel.js +149 -32
  88. package/src/components/finder/finder.css +1 -1
  89. package/src/components/kanban-view/kanban-view.css +3 -3
  90. package/src/components/kanban-view/kanban-view.js +5 -2
  91. package/src/components/launcher/launcher.css +1 -1
  92. package/src/components/launcher/launcher.js +29 -3
  93. package/src/components/list-toolbar/list-toolbar.js +39 -13
  94. package/src/components/master-panel/master-panel.js +0 -1
  95. package/src/components/menu-button/menu-button.css +63 -0
  96. package/src/components/menu-button/menu-button.js +97 -11
  97. package/src/components/message/message.js +60 -20
  98. package/src/components/modal/modal.css +1 -1
  99. package/src/components/modal/modal.js +66 -13
  100. package/src/components/module-bar/module-bar.css +486 -0
  101. package/src/components/module-bar/module-bar.js +1074 -0
  102. package/src/components/multi-value-editor/multi-value-editor.css +1 -1
  103. package/src/components/number-field/field-adapter.js +2 -1
  104. package/src/components/pagination/pagination.css +5 -5
  105. package/src/components/pagination/pagination.js +20 -4
  106. package/src/components/panel/panel.css +3 -2
  107. package/src/components/questionnaire/questionnaire.css +4 -4
  108. package/src/components/rating/field-adapter.js +2 -1
  109. package/src/components/rating/rating.css +1 -1
  110. package/src/components/search/search.css +6 -1
  111. package/src/components/select/select.js +9 -0
  112. package/src/components/sheet/sheet.css +1 -1
  113. package/src/components/sheet/sheet.js +74 -32
  114. package/src/components/slider/field-adapter.js +6 -1
  115. package/src/components/slider/slider.css +2 -2
  116. package/src/components/split-view/split-view.css +1 -1
  117. package/src/components/stat-tile/stat-tile.css +1 -1
  118. package/src/components/stepper/stepper.css +1 -1
  119. package/src/components/tabbox/tabbox.css +9 -5
  120. package/src/components/table/table.css +86 -11
  121. package/src/components/table/table.js +628 -57
  122. package/src/components/tag-picker/field-adapter.js +2 -1
  123. package/src/components/tooltip/tooltip.js +35 -17
  124. package/src/components/tree/tree.css +1 -1
  125. package/src/components/view/record-view.css +1 -1
  126. package/src/components/view/record-view.js +178 -18
  127. package/src/components/view-settings/view-settings.css +285 -0
  128. package/src/components/view-settings/view-settings.js +1830 -0
  129. package/src/components/workspace-switcher/workspace-switcher.css +188 -0
  130. package/src/components/workspace-switcher/workspace-switcher.js +463 -0
  131. package/src/core/component.js +88 -17
  132. package/src/core/fontawesome.js +5 -1
  133. package/src/core/i18n.js +47 -4
  134. package/src/core/icons.js +12 -2
  135. package/src/core/keyboard.js +206 -11
  136. package/src/core/messages.js +427 -0
  137. package/src/core/overlay-host.js +64 -9
  138. package/src/core/overlay-stack.js +487 -0
  139. package/src/core/position.js +22 -3
  140. package/src/index.js +5 -2
  141. package/src/internal/app-rail.js +134 -53
  142. package/src/internal/menu-items.js +61 -3
  143. package/src/zeyos/form.js +5 -3
  144. package/src/zeyos/index.js +3 -0
  145. package/src/zeyos/launcher.js +8 -3
  146. package/src/zeyos/module-bar.js +181 -0
  147. package/src/zeyos/query.js +44 -13
  148. package/src/zeyos/table.js +220 -80
  149. package/src/zeyos/view.js +43 -93
  150. package/styles/base.css +16 -1
  151. package/styles/print.css +1 -1
  152. package/styles/tokens/dark.css +4 -0
  153. package/styles/tokens/semantic.css +56 -28
  154. package/styles/zx.css +3 -0
@@ -58,7 +58,7 @@
58
58
  }
59
59
 
60
60
  .zx-breadcrumb__link:focus-visible {
61
- outline: 0;
61
+ outline-color: transparent;
62
62
  box-shadow: var(--zx-focus-ring);
63
63
  }
64
64
 
@@ -118,7 +118,7 @@
118
118
  .zx-calendar__more:focus-visible,
119
119
  .zx-calendar__month-week-number:focus-visible {
120
120
  z-index: 4;
121
- outline: none;
121
+ outline-color: transparent;
122
122
  box-shadow: var(--zx-focus-ring);
123
123
  }
124
124
 
@@ -47,7 +47,9 @@ import {
47
47
  * @property {CalendarReader} [eventEditable='editable'] Per-event move reader.
48
48
  * @property {CalendarReader} [eventDurationEditable='durationEditable'] Per-event resize reader.
49
49
  * @property {'milliseconds'|'seconds'} [dateUnit='milliseconds'] Unit for numeric event dates.
50
- * @property {Record<string, string>} [msg] Localized component messages.
50
+ * @property {Record<string, string>} [msg] Per-instance messages, keyed `calendar.*` (`calendar.today`,
51
+ * `calendar.next`, …). The bare keys of earlier versions (`today`, `next`) are still read, after the
52
+ * namespaced key, until the next major version.
51
53
  * @property {(event: CalendarEvent) => Node|string|null} [renderEvent] Optional safe event-content renderer.
52
54
  * @property {(event: CustomEvent<{events: CalendarEvent[]}>) => void} [oneventschange] Programmatic event-data listener.
53
55
  * @property {(event: CustomEvent<{view: CalendarView, oldView: CalendarView}>) => void} [onviewchange] View listener.
@@ -73,31 +75,6 @@ import {
73
75
 
74
76
  /** @typedef {{silent?: boolean}} CalendarSetOptions */
75
77
 
76
- const DEFAULT_MESSAGES = {
77
- today: 'Today',
78
- new: 'New',
79
- agenda: 'Agenda',
80
- day: 'Day',
81
- week: 'Week',
82
- month: 'Month',
83
- year: 'Year',
84
- previous: 'Previous period',
85
- next: 'Next period',
86
- allDay: 'All day',
87
- noEvents: 'No events',
88
- more: '+%1 more',
89
- loading: 'Loading calendar…',
90
- move: 'Move %1',
91
- resize: 'Resize %1',
92
- moveStarted: 'Moving %1. Use arrow keys, Space to drop, or Escape to cancel.',
93
- resizeStarted: 'Resizing %1. Use arrow keys, Space to drop, or Escape to cancel.',
94
- editPreview: '%1, %2 to %3',
95
- editCancelled: 'Calendar edit cancelled.',
96
- editCommitted: '%1 updated.',
97
- calendar: 'Calendar',
98
- weekNumber: 'Week %1'
99
- };
100
-
101
78
  /**
102
79
  * Accessible, dependency-free agenda/day/week/month/year scheduling surface.
103
80
  * @fires Calendar#viewchange
@@ -147,8 +124,7 @@ export class Calendar extends Component {
147
124
  eventLocation: 'location',
148
125
  eventEditable: 'editable',
149
126
  eventDurationEditable: 'durationEditable',
150
- dateUnit: 'milliseconds',
151
- msg: DEFAULT_MESSAGES
127
+ dateUnit: 'milliseconds'
152
128
  };
153
129
 
154
130
  /** @returns {HTMLElement} */
@@ -178,9 +154,9 @@ export class Calendar extends Component {
178
154
  this._nowTimer = null;
179
155
 
180
156
  const navigation = h('div', { class: 'zx-calendar__navigation' },
181
- this._toolbarButton('previous', this.msg('previous'), 'chevron-left'),
182
- this._toolbarButton('today', this.msg('today')),
183
- this._toolbarButton('next', this.msg('next'), 'chevron-right'));
157
+ this._toolbarButton('previous', this.msg('calendar.previous'), 'chevron-left'),
158
+ this._toolbarButton('today', this.msg('calendar.today')),
159
+ this._toolbarButton('next', this.msg('calendar.next'), 'chevron-right'));
184
160
  const heading = h('h2', {
185
161
  ref: 'heading',
186
162
  class: 'zx-calendar__heading',
@@ -196,14 +172,14 @@ export class Calendar extends Component {
196
172
  class: 'zx-calendar__view-button',
197
173
  dataset: { calendarAction: 'view', view },
198
174
  disabled: this.options.disabled
199
- }, this.msg(view))));
175
+ }, this.msg(`calendar.${view}`))));
200
176
  const commands = h('div', { class: 'zx-calendar__commands' }, views,
201
177
  h('button', {
202
178
  type: 'button',
203
179
  class: 'zx-calendar__new',
204
180
  dataset: { calendarAction: 'new' },
205
181
  disabled: this.options.disabled
206
- }, icon('plus'), h('span', {}, this.msg('new'))));
182
+ }, icon('plus'), h('span', {}, this.msg('calendar.new'))));
207
183
  const toolbar = h('header', { class: 'zx-calendar__toolbar' }, navigation, heading, commands);
208
184
  const body = h('div', { ref: 'body', class: 'zx-calendar__body' });
209
185
  const loading = h('div', {
@@ -211,7 +187,7 @@ export class Calendar extends Component {
211
187
  class: 'zx-calendar__loading',
212
188
  role: 'status',
213
189
  hidden: true
214
- }, this.msg('loading'));
190
+ }, this.msg('calendar.loading'));
215
191
  const status = h('div', {
216
192
  ref: 'status',
217
193
  class: 'zx-calendar__status',
@@ -220,7 +196,7 @@ export class Calendar extends Component {
220
196
  ariaAtomic: 'true'
221
197
  });
222
198
  root.replaceChildren(toolbar, body, loading, status);
223
- root.setAttribute('aria-label', this.msg('calendar'));
199
+ root.setAttribute('aria-label', this.msg('calendar.label'));
224
200
  root.dataset.view = this._view;
225
201
  root.dataset.state = 'ready';
226
202
 
@@ -470,7 +446,7 @@ export class Calendar extends Component {
470
446
  }, this._format(day, { weekday: 'long', day: 'numeric', month: 'long' })));
471
447
  const entries = h('div', { class: 'zx-calendar__agenda-events', role: 'gridcell' });
472
448
  if (!events.length) {
473
- entries.append(h('p', { class: 'zx-calendar__agenda-empty' }, this.msg('noEvents')));
449
+ entries.append(h('p', { class: 'zx-calendar__agenda-empty' }, this.msg('calendar.noEvents')));
474
450
  } else {
475
451
  for (const event of events) entries.append(this._eventElement(event, { variant: 'agenda', day }));
476
452
  }
@@ -576,7 +552,7 @@ export class Calendar extends Component {
576
552
  /** @param {Date[]} days @returns {HTMLElement} */
577
553
  _renderAllDayRail(days) {
578
554
  const rail = h('div', { class: 'zx-calendar__all-day' },
579
- h('span', { class: 'zx-calendar__all-day-label' }, this.msg('allDay')));
555
+ h('span', { class: 'zx-calendar__all-day-label' }, this.msg('calendar.allDay')));
580
556
  const layer = h('div', {
581
557
  class: 'zx-calendar__all-day-grid',
582
558
  role: 'row',
@@ -625,7 +601,7 @@ export class Calendar extends Component {
625
601
  type: 'button',
626
602
  class: 'zx-calendar__month-week-number',
627
603
  dataset: { calendarAction: 'week', date: calendarDayKey(start) },
628
- ariaLabel: this.msg('weekNumber', isoWeek(start)),
604
+ ariaLabel: this.msg('calendar.weekNumber', isoWeek(start)),
629
605
  disabled: this.options.disabled
630
606
  }, String(isoWeek(start))));
631
607
  const days = h('div', { class: 'zx-calendar__month-days' });
@@ -666,7 +642,7 @@ export class Calendar extends Component {
666
642
  dataset: { calendarAction: 'more', date: calendarDayKey(day), count: String(count) },
667
643
  style: { gridColumn: String(index + 1), gridRow: String(eventLimit + 1) },
668
644
  disabled: this.options.disabled
669
- }, this.msg('more', count)));
645
+ }, this.msg('calendar.more', count)));
670
646
  }
671
647
  row.append(days, lanes);
672
648
  wrapper.append(row);
@@ -758,7 +734,7 @@ export class Calendar extends Component {
758
734
  type: 'button',
759
735
  class: 'zx-calendar__event-resize',
760
736
  dataset: { eventAction: 'resize', eventId: key },
761
- ariaLabel: this.msg('resize', event.title),
737
+ ariaLabel: this.msg('calendar.resize', event.title),
762
738
  disabled: this.options.disabled
763
739
  }, h('span', { ariaHidden: 'true' })));
764
740
  }
@@ -886,7 +862,7 @@ export class Calendar extends Component {
886
862
  };
887
863
  control.setAttribute('aria-grabbed', 'true');
888
864
  control.closest('.zx-calendar__event')?.setAttribute('data-state', 'grabbed');
889
- this._announce(this.msg(resize ? 'resizeStarted' : 'moveStarted', item.title));
865
+ this._announce(this.msg(resize ? 'calendar.resizeStarted' : 'calendar.moveStarted', item.title));
890
866
  return;
891
867
  }
892
868
  if (!this._keyboardEdit || String(this._keyboardEdit.event.id) !== String(item.id)) return;
@@ -919,7 +895,7 @@ export class Calendar extends Component {
919
895
  if (proposed.end > proposed.start) edit.event = proposed;
920
896
  }
921
897
  edit.control.closest('.zx-calendar__event')?.setAttribute('data-preview', this._eventTime(edit.event, edit.event.start));
922
- this._announce(this.msg('editPreview', edit.event.title,
898
+ this._announce(this.msg('calendar.editPreview', edit.event.title,
923
899
  this._dateTimeLabel(edit.event.start), this._dateTimeLabel(edit.event.end)));
924
900
  }
925
901
 
@@ -1065,7 +1041,7 @@ export class Calendar extends Component {
1065
1041
  }
1066
1042
  wrapper.dataset.preview = this._eventTime(proposed, proposed.start);
1067
1043
  }
1068
- this._announce(this.msg('editPreview', proposed.title,
1044
+ this._announce(this.msg('calendar.editPreview', proposed.title,
1069
1045
  this._dateTimeLabel(proposed.start), this._dateTimeLabel(proposed.end)));
1070
1046
  }
1071
1047
 
@@ -1255,7 +1231,7 @@ export class Calendar extends Component {
1255
1231
  edit.control.removeAttribute('aria-grabbed');
1256
1232
  edit.control.closest('.zx-calendar__event')?.removeAttribute('data-state');
1257
1233
  this._keyboardEdit = null;
1258
- this._announce(this.msg('editCancelled'));
1234
+ this._announce(this.msg('calendar.editCancelled'));
1259
1235
  this._renderView({ preserveFocus: true });
1260
1236
  }
1261
1237
 
@@ -1286,7 +1262,7 @@ export class Calendar extends Component {
1286
1262
  this._replaceNormalizedEvent(oldEvent);
1287
1263
  this._mutationVersions.delete(key);
1288
1264
  this._renderView({ preserveFocus: true });
1289
- this._announce(this.msg('editCancelled'));
1265
+ this._announce(this.msg('calendar.editCancelled'));
1290
1266
  return true;
1291
1267
  };
1292
1268
  const detail = {
@@ -1299,7 +1275,7 @@ export class Calendar extends Component {
1299
1275
  };
1300
1276
  const emitted = this.emit('eventchange', detail);
1301
1277
  if (emitted.defaultPrevented) revert();
1302
- else this._announce(this.msg('editCommitted', proposed.title));
1278
+ else this._announce(this.msg('calendar.editCommitted', proposed.title));
1303
1279
  }
1304
1280
 
1305
1281
  /** @param {CalendarEvent} event @returns {void} */
@@ -1364,11 +1340,11 @@ export class Calendar extends Component {
1364
1340
 
1365
1341
  /** @param {CalendarEvent} event @param {Date} day @returns {string} */
1366
1342
  _eventTime(event, day) {
1367
- if (event.allDay) return this.msg('allDay');
1343
+ if (event.allDay) return this.msg('calendar.allDay');
1368
1344
  if (calendarEventSpansDays(event)) {
1369
1345
  if (sameCalendarDay(event.start, day)) return `${formatDateTime(event.start, this.options.locale)} →`;
1370
1346
  if (sameCalendarDay(event.end, day)) return `→ ${formatDateTime(event.end, this.options.locale)}`;
1371
- return this.msg('allDay');
1347
+ return this.msg('calendar.allDay');
1372
1348
  }
1373
1349
  const start = formatTimeDate(event.start, this.options.locale);
1374
1350
  if (event.end <= event.start) return start;
@@ -1490,10 +1466,8 @@ export class Calendar extends Component {
1490
1466
  }
1491
1467
 
1492
1468
  /**
1493
- * Resolves a message through the host translator, falling back to the built-in English text.
1494
- *
1495
- * Distinct from `msg()`: the built-in `msg` option answers the calendar's own vocabulary, so a
1496
- * dotted key falls past it to the host translator, which is what these strings never had.
1469
+ * Resolves a message through `msg()`, falling back to the built-in English text. Redundant now
1470
+ * that `msg()` ends in the default catalogue; kept until the private copies are removed.
1497
1471
  * @param {string} key Message key.
1498
1472
  * @param {string} fallback Built-in text, with `%1`-style placeholders.
1499
1473
  * @param {...unknown} args Interpolation values.
@@ -51,7 +51,7 @@
51
51
  }
52
52
 
53
53
  .zx-card:has(.zx-card__primary:focus-visible) {
54
- outline: 0;
54
+ outline-color: transparent;
55
55
  box-shadow: var(--zx-focus-ring);
56
56
  }
57
57
 
@@ -129,7 +129,7 @@
129
129
  }
130
130
 
131
131
  .zx-card__primary:focus-visible {
132
- outline: 0;
132
+ outline-color: transparent;
133
133
  }
134
134
 
135
135
  .zx-card__actions,
@@ -38,7 +38,7 @@
38
38
  }
39
39
 
40
40
  .zx-card-view__sort select:focus-visible {
41
- outline: none;
41
+ outline-color: transparent;
42
42
  box-shadow: var(--zx-focus-ring);
43
43
  }
44
44
 
@@ -59,6 +59,77 @@
59
59
  line-height: 1.3;
60
60
  }
61
61
 
62
+ /* The heading row: a plain wrapper in the tab model, a grid row in the roving one. */
63
+ .zx-card-view__group-header {
64
+ border-radius: var(--zx-radius-sm);
65
+ }
66
+
67
+ .zx-card-view__group-header:focus-visible {
68
+ outline: 2px solid transparent;
69
+ box-shadow: inset var(--zx-focus-ring);
70
+ }
71
+
72
+ /* A collapsible heading is an APG disclosure: the button carries the label, the chevron turns. */
73
+ .zx-card-view__group-toggle {
74
+ display: inline-flex;
75
+ align-items: center;
76
+ gap: var(--zx-space-1);
77
+ min-block-size: 0;
78
+ margin-inline-start: calc(-1 * var(--zx-space-1));
79
+ padding: var(--zx-space-1);
80
+ border: 0;
81
+ border-radius: var(--zx-radius-sm);
82
+ background: none;
83
+ color: inherit;
84
+ font: inherit;
85
+ cursor: pointer;
86
+ }
87
+
88
+ .zx-card-view__group-toggle:hover {
89
+ background: var(--zx-color-bg-hover);
90
+ }
91
+
92
+ .zx-card-view__group-toggle:focus-visible {
93
+ outline: 2px solid transparent;
94
+ box-shadow: var(--zx-focus-ring);
95
+ }
96
+
97
+ .zx-card-view__group-toggle > .zx-icon {
98
+ flex: none;
99
+ color: var(--zx-color-text-subtle);
100
+ }
101
+
102
+ .zx-card-view__group-toggle[aria-expanded="false"] > .zx-icon {
103
+ transform: rotate(-90deg);
104
+ }
105
+
106
+ .zx-card-view__group[data-collapsed="true"] .zx-card-view__group-heading {
107
+ margin-block-end: 0;
108
+ }
109
+
110
+ .zx-card-view__list[hidden] {
111
+ display: none;
112
+ }
113
+
114
+ /* Roving focus sits inside the card, so a host that restyles cards into flush rows still shows
115
+ it; the transparent outline is what forced-colors mode paints. */
116
+ .zx-card-view[data-keyboard="roving"] .zx-record-card:focus-visible {
117
+ outline: 2px solid transparent;
118
+ outline-offset: -2px;
119
+ box-shadow: inset var(--zx-focus-ring);
120
+ }
121
+
122
+ .zx-card-view__content[data-empty-focus]:focus-visible {
123
+ outline: 2px solid transparent;
124
+ box-shadow: inset var(--zx-focus-ring);
125
+ }
126
+
127
+ @media (prefers-reduced-motion: no-preference) {
128
+ .zx-card-view__group-toggle > .zx-icon {
129
+ transition: transform var(--zx-dur-fast) var(--zx-ease);
130
+ }
131
+ }
132
+
62
133
  .zx-card-view__list {
63
134
  display: grid;
64
135
  grid-template-columns: repeat(auto-fill,
@@ -103,7 +174,7 @@
103
174
  }
104
175
 
105
176
  .zx-record-card:focus-visible {
106
- outline: none;
177
+ outline-color: transparent;
107
178
  box-shadow: var(--zx-focus-ring);
108
179
  }
109
180
 
@@ -179,7 +250,7 @@
179
250
  }
180
251
 
181
252
  .zx-record-card__selection input:focus-visible {
182
- outline: none;
253
+ outline-color: transparent;
183
254
  box-shadow: var(--zx-focus-ring);
184
255
  }
185
256
 
@@ -246,7 +317,7 @@
246
317
 
247
318
  .zx-record-card__primary:focus-visible {
248
319
  border-radius: var(--zx-radius-sm);
249
- outline: none;
320
+ outline-color: transparent;
250
321
  box-shadow: var(--zx-focus-ring);
251
322
  }
252
323
 
@@ -291,7 +362,7 @@
291
362
  }
292
363
 
293
364
  .zx-record-card__action:focus-visible {
294
- outline: none;
365
+ outline-color: transparent;
295
366
  box-shadow: var(--zx-focus-ring);
296
367
  }
297
368