@zeyos/zx 5.0.0 → 5.2.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/CHANGELOG.md +164 -0
- package/README.md +2 -1
- package/dist/types/components/account-menu/account-menu.d.ts +8 -0
- package/dist/types/components/activity-list/activity-list.d.ts +9 -1
- package/dist/types/components/app-icon/app-icon.d.ts +14 -2
- package/dist/types/components/app-sidebar/app-sidebar.d.ts +288 -14
- package/dist/types/components/calendar/calendar.d.ts +67 -5
- package/dist/types/components/card-view/card-view.d.ts +7 -4
- package/dist/types/components/card-view/record-card.d.ts +11 -0
- package/dist/types/components/context-menu/context-menu.d.ts +6 -2
- package/dist/types/components/data-filter/data-filter.d.ts +4 -4
- package/dist/types/components/dropdown/dropdown.d.ts +22 -7
- package/dist/types/components/field/field.d.ts +30 -0
- package/dist/types/components/fieldset/external-adapter.d.ts +83 -0
- package/dist/types/components/fieldset/fieldset.d.ts +7 -0
- package/dist/types/components/file-list/file-list.d.ts +35 -3
- package/dist/types/components/filter/filter.d.ts +127 -3
- package/dist/types/components/filter-panel/filter-panel.d.ts +36 -7
- package/dist/types/components/launcher/launcher.d.ts +8 -0
- package/dist/types/components/list-toolbar/list-toolbar.d.ts +15 -6
- package/dist/types/components/menu-button/menu-button.d.ts +6 -0
- package/dist/types/components/message/message.d.ts +14 -1
- package/dist/types/components/modal/modal.d.ts +30 -0
- package/dist/types/components/module-bar/module-bar.d.ts +395 -0
- package/dist/types/components/pagination/pagination.d.ts +17 -3
- package/dist/types/components/select/select.d.ts +6 -0
- package/dist/types/components/sheet/sheet.d.ts +15 -0
- package/dist/types/components/table/table.d.ts +265 -17
- package/dist/types/components/view/record-view.d.ts +59 -2
- package/dist/types/components/view-settings/view-settings.d.ts +879 -0
- package/dist/types/components/workspace-switcher/workspace-switcher.d.ts +327 -0
- package/dist/types/core/component.d.ts +12 -2
- package/dist/types/core/i18n.d.ts +27 -3
- package/dist/types/core/keyboard.d.ts +98 -1
- package/dist/types/core/messages.d.ts +382 -0
- package/dist/types/core/overlay-host.d.ts +28 -1
- package/dist/types/core/overlay-stack.d.ts +260 -0
- package/dist/types/index.d.ts +5 -2
- package/dist/types/internal/app-rail.d.ts +38 -0
- package/dist/types/internal/menu-items.d.ts +71 -3
- package/dist/types/zeyos/index.d.ts +1 -0
- package/dist/types/zeyos/launcher.d.ts +9 -0
- package/dist/types/zeyos/module-bar.d.ts +176 -0
- package/dist/types/zeyos/query.d.ts +31 -5
- package/dist/types/zeyos/table.d.ts +245 -8
- package/dist/types/zeyos/view.d.ts +16 -2
- package/dist/zx-zeyos.esm.js +4422 -430
- package/dist/zx-zeyos.esm.min.js +5 -5
- package/dist/zx.css +1417 -134
- package/dist/zx.esm.js +6986 -830
- package/dist/zx.esm.min.js +8 -8
- package/dist/zx.global.js +6986 -830
- package/dist/zx.global.min.js +8 -8
- package/dist/zx.min.css +1 -1
- package/docs/api.json +794 -17
- package/docs/llms.md +503 -63
- package/docs/llms.txt +6 -2
- package/package.json +1 -1
- package/src/components/account-menu/account-menu.js +12 -0
- package/src/components/activity-list/activity-list.js +27 -1
- package/src/components/app-icon/app-icon.css +13 -2
- package/src/components/app-icon/app-icon.js +11 -1
- package/src/components/app-rail/app-rail.css +19 -0
- package/src/components/app-sidebar/app-sidebar.css +204 -3
- package/src/components/app-sidebar/app-sidebar.js +646 -40
- package/src/components/breadcrumb/breadcrumb.css +1 -1
- package/src/components/calendar/calendar.css +1 -1
- package/src/components/calendar/calendar.js +26 -52
- package/src/components/card/card.css +2 -2
- package/src/components/card-view/card-view.css +5 -5
- package/src/components/card-view/card-view.js +13 -9
- package/src/components/card-view/record-card.js +14 -3
- package/src/components/code-editor/code-editor.css +1 -1
- package/src/components/code-editor/field-adapter.js +9 -2
- package/src/components/context-menu/context-menu.js +8 -2
- package/src/components/copy/copy-input.css +1 -1
- package/src/components/data-filter/data-filter.js +2 -2
- package/src/components/date-picker/time-picker.css +2 -2
- package/src/components/dock/dock.css +5 -4
- package/src/components/dropdown/dropdown.js +157 -72
- package/src/components/field/field.js +33 -3
- package/src/components/fieldset/external-adapter.js +363 -0
- package/src/components/fieldset/fieldset.js +10 -59
- package/src/components/file-list/file-list.js +144 -21
- package/src/components/filter/filter.css +86 -2
- package/src/components/filter/filter.js +300 -8
- package/src/components/filter-panel/filter-panel.js +149 -32
- package/src/components/finder/finder.css +1 -1
- package/src/components/kanban-view/kanban-view.css +3 -3
- package/src/components/kanban-view/kanban-view.js +5 -2
- package/src/components/launcher/launcher.css +1 -1
- package/src/components/launcher/launcher.js +29 -3
- package/src/components/list-toolbar/list-toolbar.js +39 -13
- package/src/components/master-panel/master-panel.js +0 -1
- package/src/components/menu-button/menu-button.css +63 -0
- package/src/components/menu-button/menu-button.js +97 -11
- package/src/components/message/message.js +60 -20
- package/src/components/modal/modal.css +1 -1
- package/src/components/modal/modal.js +66 -13
- package/src/components/module-bar/module-bar.css +486 -0
- package/src/components/module-bar/module-bar.js +1074 -0
- package/src/components/multi-value-editor/multi-value-editor.css +1 -1
- package/src/components/number-field/field-adapter.js +2 -1
- package/src/components/pagination/pagination.css +5 -5
- package/src/components/pagination/pagination.js +20 -4
- package/src/components/panel/panel.css +3 -2
- package/src/components/questionnaire/questionnaire.css +4 -4
- package/src/components/rating/field-adapter.js +2 -1
- package/src/components/rating/rating.css +1 -1
- package/src/components/search/search.css +4 -1
- package/src/components/select/select.js +9 -0
- package/src/components/sheet/sheet.css +1 -1
- package/src/components/sheet/sheet.js +74 -32
- package/src/components/slider/field-adapter.js +6 -1
- package/src/components/slider/slider.css +2 -2
- package/src/components/split-view/split-view.css +1 -1
- package/src/components/stat-tile/stat-tile.css +1 -1
- package/src/components/stepper/stepper.css +1 -1
- package/src/components/tabbox/tabbox.css +9 -5
- package/src/components/table/table.css +86 -11
- package/src/components/table/table.js +628 -57
- package/src/components/tag-picker/field-adapter.js +2 -1
- package/src/components/tooltip/tooltip.js +35 -17
- package/src/components/tree/tree.css +1 -1
- package/src/components/view/record-view.css +1 -1
- package/src/components/view/record-view.js +178 -18
- package/src/components/view-settings/view-settings.css +285 -0
- package/src/components/view-settings/view-settings.js +1830 -0
- package/src/components/workspace-switcher/workspace-switcher.css +188 -0
- package/src/components/workspace-switcher/workspace-switcher.js +463 -0
- package/src/core/component.js +88 -17
- package/src/core/fontawesome.js +5 -1
- package/src/core/i18n.js +47 -4
- package/src/core/icons.js +12 -2
- package/src/core/keyboard.js +206 -11
- package/src/core/messages.js +427 -0
- package/src/core/overlay-host.js +64 -9
- package/src/core/overlay-stack.js +487 -0
- package/src/core/position.js +22 -3
- package/src/index.js +5 -2
- package/src/internal/app-rail.js +134 -53
- package/src/internal/menu-items.js +61 -3
- package/src/zeyos/form.js +5 -3
- package/src/zeyos/index.js +3 -0
- package/src/zeyos/launcher.js +8 -3
- package/src/zeyos/module-bar.js +181 -0
- package/src/zeyos/query.js +44 -13
- package/src/zeyos/table.js +220 -80
- package/src/zeyos/view.js +43 -93
- package/styles/base.css +16 -1
- package/styles/print.css +1 -1
- package/styles/tokens/dark.css +4 -0
- package/styles/tokens/semantic.css +56 -28
- package/styles/zx.css +3 -0
package/docs/llms.txt
CHANGED
|
@@ -35,7 +35,9 @@ exports and as `window.zx.*`.
|
|
|
35
35
|
drag and resize, `optimistic: true|false`), backend-neutral nested `Filter`, simple client-side
|
|
36
36
|
`DataFilter`, `FilterPanel` (typed filter form built from a server's own field metadata;
|
|
37
37
|
`mode: 'draft'|'live'`, `serialize`), `ListToolbar` (search, live result count, view switch, and
|
|
38
|
-
tools whose badge is part of the accessible name), `
|
|
38
|
+
tools whose badge is part of the accessible name), `ViewSettings` (view-settings drawer content:
|
|
39
|
+
reorder, hide, and add fields, grouping, board axes; `bind()` to a record view),
|
|
40
|
+
`Pagination` (+ pure `paginationRange()`),
|
|
39
41
|
`SortControl` (searchable field selector with a direction toggle, one atomic `{id,dir}`),
|
|
40
42
|
`TreeView` (APG tree), `Finder` (Miller columns).
|
|
41
43
|
- Forms: `Form`, `Fieldset`, `Questionnaire` (guided one-question-at-a-time flow with branching), `Field` (type registry), `CodeEditor` (structured text in a native textarea; never executes or injects the value), `ValueList`, `MultiValueEditor`, `FieldUpload`.
|
|
@@ -47,7 +49,9 @@ exports and as `window.zx.*`.
|
|
|
47
49
|
canvas light; shared material roles govern chrome and overlays), `Avatar`, `Panel` (header/footer action
|
|
48
50
|
buttons), `MasterPanel`, `Tabbox`
|
|
49
51
|
(`variant: 'divided'|'bracket'|'line'|'segmented'`), `NavigationBar`, `AppSidebar` (expanded and
|
|
50
|
-
minimized vertical states plus horizontal rail layouts), `
|
|
52
|
+
minimized vertical states plus horizontal rail layouts; sections; a modules layout), `ModuleBar`
|
|
53
|
+
(colour-coded module strip or bar with flyout menus and an "All modules" catalogue), `AccountMenu`,
|
|
54
|
+
`WorkspaceSwitcher` (workspace tile, name and menu at the head of a navigation column), `Launcher`,
|
|
51
55
|
`spinner()`/`ProgressBar`/`InlineLoading`, `skeleton()`/`skeletonText()`/`skeletonTable()`,
|
|
52
56
|
`Toolbar` (APG toolbar with overflow menu), `SplitView`, `Dock`
|
|
53
57
|
(collapsible resizable pane stack; tab groups, regions, adopts a `Sheet`), `Stepper`,
|
package/package.json
CHANGED
|
@@ -124,6 +124,18 @@ export class AccountMenu extends Component {
|
|
|
124
124
|
return this;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Shows the avatar alone or the avatar with the name and secondary line — for a navigation
|
|
129
|
+
* column that narrows to icons and widens again. The trigger keeps its full accessible name
|
|
130
|
+
* either way.
|
|
131
|
+
* @param {boolean} compact
|
|
132
|
+
* @returns {this}
|
|
133
|
+
*/
|
|
134
|
+
setCompact(compact) {
|
|
135
|
+
this.el.dataset.compact = String(Boolean(compact));
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
|
|
127
139
|
/** Replaces account actions. @param {MenuButtonItem[]} items @returns {this} */
|
|
128
140
|
setItems(items) {
|
|
129
141
|
this._menu.setItems(items);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { Component } from '../../core/component.js';
|
|
3
3
|
import { h, restoreTarget, snapshotTarget } from '../../core/dom.js';
|
|
4
|
+
import { captureItemFocus, restoreItemFocus } from '../../core/keyboard.js';
|
|
4
5
|
import { uid } from '../../core/util.js';
|
|
5
6
|
import { skeleton, skeletonText } from '../skeleton/skeleton.js';
|
|
6
7
|
import { ActivityItem } from '../activity-item/activity-item.js';
|
|
@@ -208,8 +209,33 @@ export class ActivityList extends Component {
|
|
|
208
209
|
if (!this._createdRoot) restoreTarget(this.el, this._original);
|
|
209
210
|
}
|
|
210
211
|
|
|
211
|
-
/**
|
|
212
|
+
/**
|
|
213
|
+
* Rebuilds the list. Items are regrouped on every mutation, so the rows are new; focus that sat
|
|
214
|
+
* on an item's control is put back on the same control of the same activity (matched by `id`,
|
|
215
|
+
* else by position), so a live feed prepending entries does not throw the reader to `<body>`.
|
|
216
|
+
* @private
|
|
217
|
+
* @returns {void}
|
|
218
|
+
*/
|
|
212
219
|
_renderList() {
|
|
220
|
+
const root = /** @type {HTMLElement} */ (this.el);
|
|
221
|
+
const focus = captureItemFocus(root, (element) => {
|
|
222
|
+
const index = this._itemComponents.findIndex((item) => item.el?.contains(element));
|
|
223
|
+
if (index < 0) return null;
|
|
224
|
+
const component = this._itemComponents[index];
|
|
225
|
+
return { key: { id: component.getActivity().id ?? null, index }, element: component.el };
|
|
226
|
+
});
|
|
227
|
+
this._renderItems();
|
|
228
|
+
restoreItemFocus(root, focus, (key) => {
|
|
229
|
+
const memo = /** @type {{id: unknown, index: number}} */ (key);
|
|
230
|
+
const match = memo.id === null ? undefined
|
|
231
|
+
: this._itemComponents.find((item) => Object.is(item.getActivity().id ?? null, memo.id));
|
|
232
|
+
const fallback = match ?? this._itemComponents[Math.min(memo.index, this._itemComponents.length - 1)];
|
|
233
|
+
return fallback?.el ?? null;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** @private @returns {void} */
|
|
238
|
+
_renderItems() {
|
|
213
239
|
this._destroyItems();
|
|
214
240
|
this._groupSequence = 0;
|
|
215
241
|
const root = /** @type {HTMLElement} */ (this.el);
|
|
@@ -26,6 +26,17 @@
|
|
|
26
26
|
border-radius: var(--zx-radius-full);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/* A tone is identity from the theme's categorical palette. An inline `color` overrides it. */
|
|
30
|
+
.zx-app-icon[data-tone="blue"] { --zx-app-icon-color: var(--zx-color-tone-blue-solid); }
|
|
31
|
+
.zx-app-icon[data-tone="teal"] { --zx-app-icon-color: var(--zx-color-tone-teal-solid); }
|
|
32
|
+
.zx-app-icon[data-tone="green"] { --zx-app-icon-color: var(--zx-color-tone-green-solid); }
|
|
33
|
+
.zx-app-icon[data-tone="amber"] { --zx-app-icon-color: var(--zx-color-tone-amber-solid); }
|
|
34
|
+
.zx-app-icon[data-tone="orange"] { --zx-app-icon-color: var(--zx-color-tone-orange-solid); }
|
|
35
|
+
.zx-app-icon[data-tone="red"] { --zx-app-icon-color: var(--zx-color-tone-red-solid); }
|
|
36
|
+
.zx-app-icon[data-tone="pink"] { --zx-app-icon-color: var(--zx-color-tone-pink-solid); }
|
|
37
|
+
.zx-app-icon[data-tone="violet"] { --zx-app-icon-color: var(--zx-color-tone-violet-solid); }
|
|
38
|
+
.zx-app-icon[data-tone="slate"] { --zx-app-icon-color: var(--zx-color-tone-slate-solid); }
|
|
39
|
+
|
|
29
40
|
.zx-app-icon__surface {
|
|
30
41
|
position: absolute;
|
|
31
42
|
z-index: 0;
|
|
@@ -62,7 +73,7 @@
|
|
|
62
73
|
.zx-app-icon[data-glass="none"] .zx-app-icon__surface::after { display: none; }
|
|
63
74
|
|
|
64
75
|
.zx-app-icon[data-selected] .zx-app-icon__surface {
|
|
65
|
-
outline:
|
|
76
|
+
outline-color: transparent;
|
|
66
77
|
box-shadow: 0 0 0 1px var(--zx-color-bg-page),
|
|
67
78
|
0 0 0 3px var(--zx-app-icon-selected-ring),
|
|
68
79
|
var(--zx-app-icon-shadow-hover),
|
|
@@ -166,7 +177,7 @@
|
|
|
166
177
|
|
|
167
178
|
.zx-app-icon:is(a, button, [role="button"]):not(:disabled):not([aria-disabled="true"]):focus-visible .zx-app-icon__surface,
|
|
168
179
|
:is(a, button, [role="button"]):not(:disabled):not([aria-disabled="true"]):focus-visible .zx-app-icon__surface {
|
|
169
|
-
outline:
|
|
180
|
+
outline-color: transparent;
|
|
170
181
|
box-shadow: var(--zx-focus-ring), var(--zx-app-icon-shadow-hover), var(--zx-app-icon-halo);
|
|
171
182
|
}
|
|
172
183
|
|
|
@@ -3,10 +3,16 @@ import { h, restoreTarget, snapshotTarget } from '../../core/dom.js';
|
|
|
3
3
|
import { icon as renderIcon } from '../../core/icons.js';
|
|
4
4
|
import { isCssColor } from '../../core/util.js';
|
|
5
5
|
|
|
6
|
+
/** @typedef {'blue'|'teal'|'green'|'amber'|'orange'|'red'|'pink'|'violet'|'slate'} AppIconTone */
|
|
7
|
+
/** The categorical tones a `tone` option accepts. @type {ReadonlyArray<AppIconTone>} */
|
|
8
|
+
export const APP_ICON_TONES = Object.freeze(['blue', 'teal', 'green', 'amber', 'orange', 'red', 'pink', 'violet', 'slate']);
|
|
9
|
+
|
|
6
10
|
/**
|
|
7
11
|
* @typedef {Object} AppIconOptions
|
|
8
12
|
* @property {string|Node|(()=>string|Node)|null} [icon=null] Icon name, node, or lazy renderer.
|
|
9
|
-
* @property {string|null} [color=null] Identity colour
|
|
13
|
+
* @property {string|null} [color=null] Identity colour, any CSS colour; takes precedence over `tone`.
|
|
14
|
+
* @property {AppIconTone|null} [tone=null] Categorical identity colour from the theme's tone palette,
|
|
15
|
+
* drawn with its `--zx-color-tone-<tone>-solid` fill. Without `color` or `tone` the icon takes the accent.
|
|
10
16
|
* @property {number|string} [size=36] Edge length in pixels or any CSS length.
|
|
11
17
|
* @property {number|string} [iconSize='52%'] Glyph size.
|
|
12
18
|
* @property {string|null} [label=null] Accessible image label; null makes the icon decorative.
|
|
@@ -28,6 +34,7 @@ export class AppIcon extends Component {
|
|
|
28
34
|
static defaults = {
|
|
29
35
|
icon: null,
|
|
30
36
|
color: null,
|
|
37
|
+
tone: null,
|
|
31
38
|
size: 36,
|
|
32
39
|
iconSize: '52%',
|
|
33
40
|
label: null,
|
|
@@ -80,6 +87,9 @@ export class AppIcon extends Component {
|
|
|
80
87
|
this.el.style.setProperty('--zx-app-icon-glyph-size', glyphSize);
|
|
81
88
|
if (isCssColor(state.color)) this.el.style.setProperty('--zx-app-icon-color', String(state.color));
|
|
82
89
|
else this.el.style.removeProperty('--zx-app-icon-color');
|
|
90
|
+
// An inline colour outranks the tone rule in the stylesheet, which is what makes `color` win.
|
|
91
|
+
if (APP_ICON_TONES.includes(state.tone)) this.el.dataset.tone = state.tone;
|
|
92
|
+
else delete this.el.dataset.tone;
|
|
83
93
|
this.el.dataset.glass = normalizeGlass(state.glass);
|
|
84
94
|
this.el.dataset.shape = normalizeShape(state.shape);
|
|
85
95
|
this.el.toggleAttribute('data-selected', Boolean(state.selected));
|
|
@@ -34,6 +34,16 @@
|
|
|
34
34
|
.zx-app-rail[data-orientation="horizontal"] .zx-app-rail__list { flex-direction: row; }
|
|
35
35
|
.zx-app-rail__row { display: flex; }
|
|
36
36
|
|
|
37
|
+
/* Where a section of the tree ends on a rail: a short rule, since a rail has no room for a heading. */
|
|
38
|
+
.zx-app-rail__separator {
|
|
39
|
+
flex: none;
|
|
40
|
+
align-self: center;
|
|
41
|
+
background: var(--zx-color-border-subtle);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.zx-app-rail[data-orientation="vertical"] .zx-app-rail__separator { inline-size: var(--zx-space-4); block-size: 1px; margin-block: var(--zx-space-1); }
|
|
45
|
+
.zx-app-rail[data-orientation="horizontal"] .zx-app-rail__separator { inline-size: 1px; block-size: var(--zx-space-4); margin-inline: var(--zx-space-1); }
|
|
46
|
+
|
|
37
47
|
.zx-app-rail__item {
|
|
38
48
|
position: relative;
|
|
39
49
|
display: inline-grid;
|
|
@@ -133,6 +143,15 @@
|
|
|
133
143
|
line-height: 1.3;
|
|
134
144
|
}
|
|
135
145
|
|
|
146
|
+
/* A section inside a flyout keeps its heading, in the same quiet caption as the panel's title. */
|
|
147
|
+
.zx-app-rail__flyout-section {
|
|
148
|
+
padding: var(--zx-space-2) var(--zx-app-rail-pad-x) var(--zx-space-1);
|
|
149
|
+
color: var(--zx-color-text-muted);
|
|
150
|
+
font-size: var(--zx-text-xs);
|
|
151
|
+
font-weight: var(--zx-weight-semibold);
|
|
152
|
+
line-height: 1.3;
|
|
153
|
+
}
|
|
154
|
+
|
|
136
155
|
.zx-app-rail__flyout-list {
|
|
137
156
|
display: grid;
|
|
138
157
|
gap: var(--zx-app-rail-row-gap);
|
|
@@ -113,7 +113,9 @@
|
|
|
113
113
|
single icon keeps the column on every row so the labels stay in one line down the list. Each
|
|
114
114
|
list answers for its own rows only — a branch of plain labels under iconned parents drops the
|
|
115
115
|
column without taking it from the parents. */
|
|
116
|
-
.zx-app-sidebar__list:not(:has(> .zx-app-sidebar__row > .zx-app-sidebar__item .zx-app-sidebar__item-icon
|
|
116
|
+
.zx-app-sidebar__list:not(:has(> .zx-app-sidebar__row > .zx-app-sidebar__item .zx-app-sidebar__item-icon,
|
|
117
|
+
> .zx-app-sidebar__section > .zx-app-sidebar__section-list > .zx-app-sidebar__row > .zx-app-sidebar__item .zx-app-sidebar__item-icon)),
|
|
118
|
+
.zx-app-sidebar__section-list:not(:has(> .zx-app-sidebar__row > .zx-app-sidebar__item .zx-app-sidebar__item-icon)),
|
|
117
119
|
.zx-app-sidebar__sublist:not(:has(> .zx-app-sidebar__row > .zx-app-sidebar__item .zx-app-sidebar__item-icon)) {
|
|
118
120
|
--zx-app-sidebar-icon: 0px;
|
|
119
121
|
--zx-app-sidebar-item-gap: 0px;
|
|
@@ -169,6 +171,43 @@
|
|
|
169
171
|
|
|
170
172
|
.zx-app-sidebar__list > .zx-app-sidebar__row:first-child { margin-block-start: 0; }
|
|
171
173
|
|
|
174
|
+
/*
|
|
175
|
+
* Sections. A heading over rows that stay at its own level: not a branch, never collapsed, never
|
|
176
|
+
* focused. Sections are separated by the group gap, like the groups a branch opens, and the
|
|
177
|
+
* heading is the same quiet sentence-case caption a flyout uses for its title.
|
|
178
|
+
*/
|
|
179
|
+
.zx-app-sidebar__section { list-style: none; }
|
|
180
|
+
|
|
181
|
+
.zx-app-sidebar__section + .zx-app-sidebar__section,
|
|
182
|
+
.zx-app-sidebar__section + .zx-app-sidebar__row,
|
|
183
|
+
.zx-app-sidebar__row + .zx-app-sidebar__section {
|
|
184
|
+
margin-block-start: var(--zx-app-sidebar-group-gap);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.zx-app-sidebar__section-header {
|
|
188
|
+
display: flex;
|
|
189
|
+
align-items: center;
|
|
190
|
+
justify-content: space-between;
|
|
191
|
+
gap: var(--zx-space-2);
|
|
192
|
+
min-block-size: calc(var(--zx-control-height) - var(--zx-space-1));
|
|
193
|
+
padding-inline: var(--zx-app-sidebar-pad-x) var(--zx-space-1);
|
|
194
|
+
color: var(--zx-color-text-muted);
|
|
195
|
+
font-size: var(--zx-text-xs);
|
|
196
|
+
font-weight: var(--zx-weight-semibold);
|
|
197
|
+
line-height: 1.3;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.zx-app-sidebar__section-label { min-inline-size: 0; overflow-wrap: break-word; }
|
|
201
|
+
.zx-app-sidebar__section-actions { display: inline-flex; flex: none; align-items: center; gap: var(--zx-space-1); }
|
|
202
|
+
|
|
203
|
+
.zx-app-sidebar__section-list {
|
|
204
|
+
display: grid;
|
|
205
|
+
gap: var(--zx-app-sidebar-row-gap);
|
|
206
|
+
margin: 0;
|
|
207
|
+
padding: 0;
|
|
208
|
+
list-style: none;
|
|
209
|
+
}
|
|
210
|
+
|
|
172
211
|
.zx-app-sidebar__item {
|
|
173
212
|
position: relative;
|
|
174
213
|
display: grid;
|
|
@@ -294,7 +333,165 @@
|
|
|
294
333
|
}
|
|
295
334
|
.zx-app-sidebar__footer[hidden] { display: none; }
|
|
296
335
|
|
|
297
|
-
.zx-app-sidebar__rail-header { display: grid; gap: var(--zx-space-1); }
|
|
336
|
+
.zx-app-sidebar__rail-header { display: grid; gap: var(--zx-space-1); justify-items: center; }
|
|
337
|
+
|
|
338
|
+
/*
|
|
339
|
+
* The modules layout: the module strip beside a panel of one module's menu. Both share the
|
|
340
|
+
* sidebar's chrome surface; the subtle rule between them is the one line tone cannot draw, since
|
|
341
|
+
* they are the same tone.
|
|
342
|
+
*/
|
|
343
|
+
.zx-app-sidebar__modules {
|
|
344
|
+
display: flex;
|
|
345
|
+
min-inline-size: 0;
|
|
346
|
+
min-block-size: 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.zx-app-sidebar[data-side="right"] .zx-app-sidebar__modules { flex-direction: row-reverse; }
|
|
350
|
+
|
|
351
|
+
.zx-app-sidebar__strip.zx-module-bar { background: transparent; }
|
|
352
|
+
.zx-app-sidebar__modules > .zx-app-sidebar__strip { border-inline-end: 1px solid var(--zx-color-border-subtle); }
|
|
353
|
+
.zx-app-sidebar[data-side="right"] .zx-app-sidebar__modules > .zx-app-sidebar__strip {
|
|
354
|
+
border-inline-end: 0;
|
|
355
|
+
border-inline-start: 1px solid var(--zx-color-border-subtle);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.zx-app-sidebar[data-layout="modules"][data-orientation="horizontal"] > .zx-app-sidebar__strip { inline-size: 100%; }
|
|
359
|
+
|
|
360
|
+
/* The foot of the strip: the one expand/collapse control, then what the application put there.
|
|
361
|
+
With names beside the tiles it lines up with their tiles rather than sitting centred. */
|
|
362
|
+
.zx-app-sidebar__strip-foot {
|
|
363
|
+
display: grid;
|
|
364
|
+
justify-items: center;
|
|
365
|
+
gap: var(--zx-space-2);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.zx-app-sidebar__strip[data-labels="beside"] .zx-app-sidebar__strip-foot {
|
|
369
|
+
justify-items: stretch;
|
|
370
|
+
/* The toggle's centre on the tiles' centre: list inset + row inset, less the footer's own pad. */
|
|
371
|
+
padding-inline-start: calc(var(--zx-space-1) + var(--zx-space-2) - var(--zx-module-bar-pad)
|
|
372
|
+
+ (var(--zx-module-bar-tile) - var(--zx-control-height)) / 2);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* With names printed the strip's head spans the column, like the rows under it. */
|
|
376
|
+
.zx-app-sidebar__strip[data-labels="beside"] .zx-app-sidebar__rail-header { justify-items: stretch; }
|
|
377
|
+
|
|
378
|
+
.zx-app-sidebar__presentation {
|
|
379
|
+
display: inline-grid;
|
|
380
|
+
justify-self: center;
|
|
381
|
+
gap: 2px;
|
|
382
|
+
border-radius: var(--zx-radius-md);
|
|
383
|
+
background: var(--zx-color-bg-hover);
|
|
384
|
+
padding: 2px;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/* Named strip: the three options in a row at the start of the foot; icon strip: a column. */
|
|
388
|
+
.zx-app-sidebar__strip[data-labels="beside"] .zx-app-sidebar__presentation {
|
|
389
|
+
grid-auto-flow: column;
|
|
390
|
+
justify-self: start;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.zx-app-sidebar__presentation-option {
|
|
394
|
+
display: grid;
|
|
395
|
+
place-items: center;
|
|
396
|
+
inline-size: var(--zx-space-6);
|
|
397
|
+
block-size: var(--zx-space-6);
|
|
398
|
+
border: 0;
|
|
399
|
+
border-radius: var(--zx-radius-sm);
|
|
400
|
+
background: transparent;
|
|
401
|
+
padding: 0;
|
|
402
|
+
color: var(--zx-color-text-muted);
|
|
403
|
+
cursor: pointer;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.zx-app-sidebar__presentation-option:hover { color: var(--zx-color-text); }
|
|
407
|
+
|
|
408
|
+
/* The chosen presentation is where you are: the surface lifted out of the track, full text colour. */
|
|
409
|
+
.zx-app-sidebar__presentation-option[aria-checked="true"] {
|
|
410
|
+
background: var(--zx-color-bg-surface);
|
|
411
|
+
box-shadow: 0 0 0 1px var(--zx-color-border-subtle);
|
|
412
|
+
color: var(--zx-color-text);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.zx-app-sidebar__presentation-option:focus-visible {
|
|
416
|
+
outline-color: transparent;
|
|
417
|
+
box-shadow: var(--zx-focus-ring);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/*
|
|
421
|
+
* The pictogram: a window with its navigation drawn in it — a module strip, wide when it is named,
|
|
422
|
+
* and a side menu when it shows. Drawn from boxes in the text colour, so it needs no icon set and
|
|
423
|
+
* follows the theme, forced colours included.
|
|
424
|
+
*/
|
|
425
|
+
.zx-app-sidebar__presentation-glyph {
|
|
426
|
+
display: flex;
|
|
427
|
+
gap: 1px;
|
|
428
|
+
box-sizing: border-box;
|
|
429
|
+
inline-size: 16px;
|
|
430
|
+
block-size: 12px;
|
|
431
|
+
border: 1.5px solid currentColor;
|
|
432
|
+
border-radius: 2px;
|
|
433
|
+
padding: 1px;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.zx-app-sidebar__presentation-strip,
|
|
437
|
+
.zx-app-sidebar__presentation-panel {
|
|
438
|
+
border-radius: 1px;
|
|
439
|
+
background: currentColor;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.zx-app-sidebar__presentation-strip { flex: 0 0 2px; }
|
|
443
|
+
.zx-app-sidebar__presentation-panel { flex: 0 0 4px; opacity: .5; }
|
|
444
|
+
.zx-app-sidebar__presentation-glyph[data-presentation="expanded"] > .zx-app-sidebar__presentation-strip { flex-basis: 4px; }
|
|
445
|
+
.zx-app-sidebar__presentation-glyph[data-presentation="collapsed"] > .zx-app-sidebar__presentation-panel { display: none; }
|
|
446
|
+
|
|
447
|
+
@media (forced-colors: active) {
|
|
448
|
+
.zx-app-sidebar__presentation-option[aria-checked="true"] {
|
|
449
|
+
background: Highlight;
|
|
450
|
+
color: HighlightText;
|
|
451
|
+
forced-color-adjust: none;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.zx-app-sidebar__panel {
|
|
456
|
+
display: grid;
|
|
457
|
+
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
458
|
+
inline-size: min(14rem, 100vw - var(--zx-control-height) * 3);
|
|
459
|
+
min-block-size: 0;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.zx-app-sidebar__panel-title {
|
|
463
|
+
color: var(--zx-color-text);
|
|
464
|
+
font-size: var(--zx-text-md);
|
|
465
|
+
font-weight: var(--zx-weight-semibold);
|
|
466
|
+
line-height: 1.3;
|
|
467
|
+
overflow-wrap: break-word;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/* One scroller for the module's lead content, its menu, and its own content, so a long menu and
|
|
471
|
+
a long list under it read as one column. The nav loses its own scroll box inside it. */
|
|
472
|
+
.zx-app-sidebar__panel-body {
|
|
473
|
+
display: grid;
|
|
474
|
+
/* Rows take their content's height and the body scrolls; a row the grid could shrink would
|
|
475
|
+
draw the menu under the content beneath it. */
|
|
476
|
+
grid-auto-rows: max-content;
|
|
477
|
+
align-content: start;
|
|
478
|
+
min-block-size: 0;
|
|
479
|
+
overflow: auto;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
.zx-app-sidebar__panel-body > .zx-app-sidebar__nav { overflow: visible; min-block-size: auto; }
|
|
483
|
+
.zx-app-sidebar__panel-body > [hidden] { display: none; }
|
|
484
|
+
|
|
485
|
+
.zx-app-sidebar__panel-lead {
|
|
486
|
+
display: grid;
|
|
487
|
+
gap: var(--zx-space-2);
|
|
488
|
+
padding: var(--zx-space-1) var(--zx-space-3) 0;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.zx-app-sidebar__panel-content {
|
|
492
|
+
min-inline-size: 0;
|
|
493
|
+
padding: 0 var(--zx-app-sidebar-gutter) var(--zx-space-3);
|
|
494
|
+
}
|
|
298
495
|
|
|
299
496
|
/*
|
|
300
497
|
* The minimized rail. Only the presentation changes; the same vocabulary applies — the neutral
|
|
@@ -379,9 +576,13 @@
|
|
|
379
576
|
.zx-app-sidebar__rail .zx-app-rail__item:active { transform: scale(.985); }
|
|
380
577
|
|
|
381
578
|
.zx-app-sidebar__expanded,
|
|
382
|
-
.zx-app-sidebar__rail
|
|
579
|
+
.zx-app-sidebar__rail,
|
|
580
|
+
.zx-app-sidebar__panel { animation: zx-app-sidebar-mode var(--zx-dur-base) var(--zx-ease); }
|
|
383
581
|
|
|
384
582
|
.zx-app-sidebar__sublist[data-branch-motion="expand"] { animation: zx-app-sidebar-branch var(--zx-dur-base) var(--zx-ease); }
|
|
583
|
+
|
|
584
|
+
/* The panel's content cross-fades when it switches module; the width never animates. */
|
|
585
|
+
.zx-app-sidebar__panel-body[data-module-motion="enter"] { animation: zx-app-sidebar-mode var(--zx-dur-base) var(--zx-ease); }
|
|
385
586
|
}
|
|
386
587
|
|
|
387
588
|
@keyframes zx-app-sidebar-mode {
|