@zeyos/zx 4.1.0 → 4.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 +61 -0
- package/DESIGN-SYSTEM.md +33 -3
- package/README.md +17 -5
- package/dist/types/components/app-icon/app-icon.d.ts +8 -1
- package/dist/types/components/aurora/aurora.d.ts +72 -0
- package/dist/types/components/calendar/calendar-model.d.ts +202 -0
- package/dist/types/components/calendar/calendar.d.ts +500 -0
- package/dist/types/components/card-view/card-view.d.ts +303 -0
- package/dist/types/components/card-view/record-card.d.ts +242 -0
- package/dist/types/components/kanban-view/kanban-view.d.ts +572 -0
- package/dist/types/components/table/table.d.ts +120 -31
- package/dist/types/components/table-view/table-view.d.ts +192 -0
- package/dist/types/components/view/record-view.d.ts +464 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/zeyos/calendar.d.ts +91 -0
- package/dist/types/zeyos/icons.d.ts +19 -3
- package/dist/types/zeyos/index.d.ts +4 -0
- package/dist/types/zeyos/legacy-saved-views.d.ts +66 -0
- package/dist/types/zeyos/saved-views.d.ts +331 -0
- package/dist/types/zeyos/view.d.ts +305 -0
- package/dist/zx-zeyos.esm.js +4627 -1460
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +2492 -410
- package/dist/zx.esm.js +4891 -115
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +4891 -115
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +1702 -191
- package/docs/llms.md +207 -20
- package/docs/llms.txt +16 -6
- package/package.json +1 -1
- package/src/components/app-icon/app-icon.css +140 -30
- package/src/components/app-icon/app-icon.js +32 -5
- package/src/components/app-rail/app-rail.css +11 -2
- package/src/components/app-sidebar/app-sidebar.css +11 -2
- package/src/components/aurora/aurora.css +143 -0
- package/src/components/aurora/aurora.js +146 -0
- package/src/components/avatar/avatar.css +1 -1
- package/src/components/button/button.css +34 -2
- package/src/components/calendar/calendar-model.js +402 -0
- package/src/components/calendar/calendar.css +567 -0
- package/src/components/calendar/calendar.js +1524 -0
- package/src/components/card/card.css +25 -3
- package/src/components/card-view/card-view.css +389 -0
- package/src/components/card-view/card-view.js +527 -0
- package/src/components/card-view/record-card.js +392 -0
- package/src/components/context-menu/context-menu.css +2 -2
- package/src/components/date-picker/date-picker.css +15 -3
- package/src/components/datebox/date-range-box.css +15 -2
- package/src/components/datebox/datebox.css +16 -3
- package/src/components/dropdown/dropdown.css +15 -3
- package/src/components/kanban-view/kanban-view.css +216 -0
- package/src/components/kanban-view/kanban-view.js +1228 -0
- package/src/components/launcher/launcher.css +18 -5
- package/src/components/master-panel/master-panel.css +14 -3
- package/src/components/menu-button/menu-button.css +2 -2
- package/src/components/message/message.css +15 -10
- package/src/components/modal/modal.css +15 -3
- package/src/components/navigation-bar/navigation-bar.css +17 -5
- package/src/components/panel/panel.css +10 -2
- package/src/components/select/select.css +20 -4
- package/src/components/sheet/sheet.css +4 -1
- package/src/components/table/table.css +80 -4
- package/src/components/table/table.js +322 -37
- package/src/components/table-view/table-view.css +18 -0
- package/src/components/table-view/table-view.js +347 -0
- package/src/components/tag-picker/tag-picker.css +15 -3
- package/src/components/tooltip/tooltip.css +15 -3
- package/src/components/view/record-view.css +114 -0
- package/src/components/view/record-view.js +770 -0
- package/src/index.js +15 -0
- package/src/zeyos/calendar.js +115 -0
- package/src/zeyos/icons.js +15 -8
- package/src/zeyos/index.js +13 -0
- package/src/zeyos/launcher.js +2 -2
- package/src/zeyos/legacy-saved-views.js +155 -0
- package/src/zeyos/saved-views.js +815 -0
- package/src/zeyos/table.js +3 -1
- package/src/zeyos/view.js +543 -0
- package/styles/icons.css +3 -10
- package/styles/tokens/semantic.css +74 -2
- package/styles/zx.css +6 -0
package/docs/llms.md
CHANGED
|
@@ -75,11 +75,19 @@ Keep the 600 stop at 4.5:1 or better against white and the 400 stop at 4.5:1 aga
|
|
|
75
75
|
|
|
76
76
|
The theme studio treats those stable IDs as complete recipes: selecting a preset also changes its
|
|
77
77
|
density, neutral tint, radius, control height, base text size, font stack, and material strength.
|
|
78
|
-
Its **Material** control is CSS-first (`Flat`, `Glass`, or `Deep glass`)
|
|
79
|
-
|
|
78
|
+
Its **Material** control is CSS-first (`Flat`, `Glass`, or `Deep glass`). Aurora is the independent
|
|
79
|
+
ambient canvas layer; material controls how surfaces respond to that light. The shared recipe
|
|
80
|
+
applies to AppIcons, ordinary controls, persistent chrome, raised cards, and every transient overlay: Dropdown, ContextMenu,
|
|
81
|
+
MenuButton, AccountMenu, AppRail flyouts, Select, TagPicker, date pickers, tooltips, column menus,
|
|
82
|
+
and toasts use `--zx-color-overlay-surface`; Launcher, Modal, Dialog, and overlay Sheets use the
|
|
83
|
+
more opaque `--zx-color-overlay-panel`. A docked Sheet is layout rather than
|
|
84
|
+
an overlay and becomes opaque, as do dense data surfaces. Glass and Deep glass progressively raise
|
|
85
|
+
translucency, blur, highlights, and elevation; reduced-transparency preferences restore solid
|
|
86
|
+
surfaces.
|
|
80
87
|
|
|
81
88
|
Define a product theme by overriding **semantic** tokens under a `[data-zx-theme="name"]` selector:
|
|
82
|
-
`--zx-color-bg-page/surface/raised/control/hover/selected`, `--zx-color-
|
|
89
|
+
`--zx-color-bg-page/surface/raised/control/hover/selected`, `--zx-color-glass-chrome/surface`,
|
|
90
|
+
`--zx-color-overlay-surface/panel/border`, `--zx-color-border(-strong/-control)`,
|
|
83
91
|
`--zx-color-text(-muted/-placeholder)`, `--zx-color-accent(-hover)/on-accent`,
|
|
84
92
|
`--zx-color-danger/warning/success/info(+ -bg)`, `--zx-focus-ring`, `--zx-control-height/-radius`,
|
|
85
93
|
`--zx-space-*`, `--zx-radius-*`, `--zx-text-*`. Never use tier-1 palette tokens (`--zx-gray-*`,
|
|
@@ -119,8 +127,10 @@ bundles `@zeyos/client`; the application owns client creation, authentication, a
|
|
|
119
127
|
```js
|
|
120
128
|
import { createZeyosClient } from '@zeyos/client';
|
|
121
129
|
import {
|
|
122
|
-
connect,
|
|
130
|
+
connect, createLegacySavedViewTransport, createSavedViewRegistry,
|
|
131
|
+
dataFilterStateToFilters, legacySavedViewRequest, zeyosForm, zeyosSelect, zeyosTable, zeyosView
|
|
123
132
|
} from '/assets/zx-zeyos.esm.js';
|
|
133
|
+
import { CardView, TableView } from '/assets/zx.esm.js';
|
|
124
134
|
|
|
125
135
|
const client = createZeyosClient({ platform, auth });
|
|
126
136
|
const api = connect(client, { locale: 'en-GB' });
|
|
@@ -138,6 +148,17 @@ const editor = zeyosForm(client, 'transactions', {
|
|
|
138
148
|
});
|
|
139
149
|
await editor.load(transactionId);
|
|
140
150
|
await editor.save();
|
|
151
|
+
|
|
152
|
+
const records = zeyosView(client, 'transactions', TableView, {
|
|
153
|
+
fields: ['transactionnum', 'account', 'date', 'netamount', 'status'],
|
|
154
|
+
savedViews: {
|
|
155
|
+
transport: savedViewTransport,
|
|
156
|
+
scope: { userId: currentUserId, workspaceId: currentWorkspaceId }
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
await records.ready; // restores a compatible default before the first list request
|
|
160
|
+
await records.load();
|
|
161
|
+
await records.saveView({ name: 'My open invoices', setDefault: true });
|
|
141
162
|
```
|
|
142
163
|
|
|
143
164
|
- `connect(client, { onError, locale })` returns `{client, list, get, create, update, reportError}`;
|
|
@@ -154,6 +175,21 @@ await editor.save();
|
|
|
154
175
|
`{table, load(), setSearch(), setFilters(), loadMore(), count, page, hasMore, destroy()}`. Columns
|
|
155
176
|
come from schema metadata, sorting uses `sortMode:'server'`, and page zero replaces rows while
|
|
156
177
|
later pages append them using server `limit`/`offset` and `count`.
|
|
178
|
+
- `buildZeyosViewConfig(client, resource, opts)` resolves one schema to shared `ViewField[]`, a
|
|
179
|
+
complete projection, and view options. `zeyosView(client, resource, CardView|TableView|KanbanView,
|
|
180
|
+
opts)` returns `{view, load(), setSearch(), setFilters(), loadMore(), count, page, hasMore,
|
|
181
|
+
savedViews, ready, restoreDefault(), captureView(), saveView(), applyView(), destroy()}` with
|
|
182
|
+
paging and server sort. Title, preview, group, column, and swim-lane fields stay in the projection
|
|
183
|
+
even when hidden. Without `savedViews`, the host may persist `view.getViewState()` directly.
|
|
184
|
+
- `createSavedViewRegistry(transport, {userId,workspaceId,resource})` coordinates private named
|
|
185
|
+
Table/Card/Kanban configurations as one versioned, atomically replaced document. Entries capture
|
|
186
|
+
component state plus filters/search and an explicit presentation type, never records, selection,
|
|
187
|
+
pages, callbacks, or DOM. Duplicate names, defaults, migration, type mismatch, failed writes, and
|
|
188
|
+
teardown are explicit. `workspaceId:null` addresses ZeyOS's base workspace.
|
|
189
|
+
- `createLegacySavedViewTransport(request)` reuses the authenticated `fields`, `fields_save`, and
|
|
190
|
+
`fields_remove` endpoints through one reserved, namespaced `userfields` record.
|
|
191
|
+
`legacySavedViewRequest(PG.load.bind(PG))` is the optional Promise bridge for a legacy host. The
|
|
192
|
+
scope's `userId` is intentionally not sent to the endpoint; the server session remains authority.
|
|
157
193
|
|
|
158
194
|
Field mapping is schema-driven: entity/FK → async `zxselect`; enum/list → `optionlist` or native
|
|
159
195
|
`select`; indexed `date` bigint → `date`; other date/time bigints → `datetime`; money/price/numeric
|
|
@@ -194,8 +230,8 @@ registerModules({ tickets: '#f04639', 'my-fork': { label: 'My Fork', icon: 'zeyo
|
|
|
194
230
|
- `moduleIcon(name, {size, label, standard})` → the bare glyph; `standard: true` uses the stock
|
|
195
231
|
Font Awesome fallback, for pages on a kit without the ZeyOS uploads.
|
|
196
232
|
- `moduleChip(name, {size, iconSize, label, title, standard})` → `<span class="zx-module-icon">`
|
|
197
|
-
with
|
|
198
|
-
|
|
233
|
+
with a centred white glyph on the module colour. `moduleGlyphColor(hex)` remains available as a
|
|
234
|
+
separate contrast helper for non-AppIcon integrations that deliberately choose their foreground.
|
|
199
235
|
- `moduleInfo`/`moduleColor`/`moduleIconName`/`moduleKeys`/`normalizeModuleName` read the config.
|
|
200
236
|
Module, entity, and API resource names are all accepted, case-insensitively, with dots and
|
|
201
237
|
underscores normalized: `'transactions.billing'`, `'invoices'`, and `'Transactions Billing'` all
|
|
@@ -453,25 +489,34 @@ permissions, recent-history/cache policy, and the route or command ultimately in
|
|
|
453
489
|
<!-- doc:app-icon -->
|
|
454
490
|
### AppIcon — application identity
|
|
455
491
|
|
|
456
|
-
A fixed-size, product-agnostic application
|
|
492
|
+
A fixed-size, product-agnostic application identity. It keeps glyph geometry stable in launchers,
|
|
457
493
|
sidebars, entity results, and recent-item rows while identity colour and material remain explicit
|
|
458
494
|
options rather than application globals.
|
|
459
495
|
|
|
460
496
|
- **Options** — `icon` (bundled name, Node, or lazy renderer), `color`, `size: 36`,
|
|
461
|
-
`iconSize: '52%'`, `label`, `badge`, `selected: false`, `
|
|
497
|
+
`iconSize: '52%'`, `label`, `badge`, `selected: false`, `shape: 'tile'|'circle'`,
|
|
498
|
+
`glass: false|'subtle'|'strong'`, and
|
|
462
499
|
additional `class` names.
|
|
463
500
|
- **Methods** — `set(partialOptions)` updates the existing root; `destroy()` restores an enhanced
|
|
464
501
|
target. `appIcon(options)` is the element-returning convenience factory.
|
|
465
502
|
- **ZeyOS preset** — import `zeyosAppIcon(module, options)` from `@zeyos/zx/zeyos`. Every current
|
|
466
503
|
ZeyOS application/module has a canonical colour and icon mapping in `src/zeyos/modules.js`;
|
|
467
|
-
entity names and aliases resolve through the same catalogue. `
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
504
|
+
entity names and aliases resolve through the same catalogue. `zeyosAppIcon()` defaults to a
|
|
505
|
+
circular application vessel; `moduleChip()` deliberately keeps a compact tile for entity and
|
|
506
|
+
record identity. An application may call `useZeyosIcons()` for the existing custom glyph kit or
|
|
507
|
+
inject an offline `icon` override; Zx never loads a network asset automatically.
|
|
508
|
+
- **Shape and material** — core `AppIcon` keeps the backward-compatible `tile` default. Application
|
|
509
|
+
launchers and rails use `circle`; entity rows, recent records, badges, and tables use `tile`.
|
|
510
|
+
Subtle glass uses a quiet colour bloom, rim, reflection, and shadow without per-icon backdrop
|
|
511
|
+
blur; strong glass increases those material cues without changing geometry.
|
|
512
|
+
`prefers-reduced-transparency` receives a solid surface. Glyphs remain crisp white and
|
|
513
|
+
geometrically centred in either built-in SVG or Font Awesome form. Enabled interactive hosts
|
|
514
|
+
respond through rim, light, and shadow without translating the icon; decorative and disabled
|
|
515
|
+
identities do not imply clickability.
|
|
516
|
+
- **Accessibility** — on an owned identity surface, a non-empty `label` gives the root
|
|
517
|
+
`role="img"`; otherwise it is decorative. When AppIcon enhances a button or link, it preserves
|
|
518
|
+
that control's native role and uses `label` only as its accessible name. The badge is visual
|
|
519
|
+
supplementary status, so include its meaning in `label` when it matters.
|
|
475
520
|
<!-- /doc -->
|
|
476
521
|
|
|
477
522
|
<!-- doc:avatar -->
|
|
@@ -751,8 +796,8 @@ messages rather than the page, and uses the translucent glass surface tokens wit
|
|
|
751
796
|
<!-- doc:modal -->
|
|
752
797
|
### Modal
|
|
753
798
|
|
|
754
|
-
Thin overlay on the native `<dialog>` element. The
|
|
755
|
-
focus returns to the opener on close.
|
|
799
|
+
Thin overlay on the native `<dialog>` element. The surface uses the shared, reading-sized overlay
|
|
800
|
+
panel material; the backdrop uses `--zx-color-bg-backdrop`, and focus returns to the opener on close.
|
|
756
801
|
|
|
757
802
|
- **Options** — `content`, `width: 'auto'`, `closable: true`, `lightDismiss: false`,
|
|
758
803
|
`destroyOnClose: false`.
|
|
@@ -780,7 +825,8 @@ Structured modal: a header with title and close button, a body, and footer butto
|
|
|
780
825
|
Edge-anchored surface — a `Dialog` attached to one side of the viewport instead of floating in the
|
|
781
826
|
middle. One primitive covers both side sheets and mobile drawers, which differ mainly in the edge they take, so
|
|
782
827
|
`side` replaces what would otherwise be two components. Inherits the whole Dialog anatomy: title,
|
|
783
|
-
footer buttons, switchable views, and
|
|
828
|
+
footer buttons, switchable views, focus restoration, and the reading-sized overlay panel material.
|
|
829
|
+
When a Dock adopts it, the Sheet becomes an opaque layout surface instead.
|
|
784
830
|
|
|
785
831
|
- **Options** — `side: 'end'` (`'start' | 'end' | 'top' | 'bottom'`, logical), `modal: true`
|
|
786
832
|
(`true | 'trap-focus' | false`), `backdrop: 'dim'` (`'dim' | 'blur' | 'none'`), `size: null`
|
|
@@ -969,7 +1015,7 @@ range select.
|
|
|
969
1015
|
`hierarchy: false|{parentId, column?, expanded?}`. Locale, currency, unit, and decimals may be
|
|
970
1016
|
row callbacks; values remain numbers in row data while display formatting is locale-aware.
|
|
971
1017
|
- **Methods** — `setData()`, `addData()`, `updateRow(id,row)`, `removeRow(id)`, `getRow(id)`,
|
|
972
|
-
`getData()`, `empty()`, `setSort(id,dir)`, `getSelection()`, `setSelection(ids)`,
|
|
1018
|
+
`getData()`, `empty()`, `setSort(id,dir)`, `getSort()`, `clearSort()`, `getSelection()`, `setSelection(ids)`,
|
|
973
1019
|
`clearSelection()`, `setLoading(bool)` (busy/skeleton state — dims rows, shows an indeterminate
|
|
974
1020
|
top bar, sets `aria-busy`, and is cleared by the next `setData`).
|
|
975
1021
|
- **Events** — `rowclick {row, id, index, event}`, `rowdblclick`, `sort {id, dir}`,
|
|
@@ -1049,6 +1095,82 @@ range select.
|
|
|
1049
1095
|
- **Column visibility** — `columnVisibility: true` renders a chooser; `hiddenColumns` seeds it.
|
|
1050
1096
|
`getVisibleColumns()`, `getHiddenColumns()`, `setColumnVisible()`, and `toggleColumn()` preserve
|
|
1051
1097
|
caller column order and never allow the final visible column to disappear.
|
|
1098
|
+
- **Column order** — `columnReorder: true` adds up/down buttons to the chooser and ArrowUp/
|
|
1099
|
+
ArrowDown support while a column option is focused. `getColumns()`, `setColumns()`,
|
|
1100
|
+
`getColumnOrder()`, `setColumnOrder()`, and `moveColumn()` reconcile stale saved IDs and keep
|
|
1101
|
+
hidden/sorted state attached to stable column IDs. `columnorderchange {order}` fires after a
|
|
1102
|
+
user or non-silent programmatic change.
|
|
1103
|
+
<!-- /doc -->
|
|
1104
|
+
|
|
1105
|
+
<!-- doc:table-view -->
|
|
1106
|
+
### TableView and the shared RecordView contract
|
|
1107
|
+
|
|
1108
|
+
`TableView` is the record-oriented entry point above the lower-level `Table`. It extends
|
|
1109
|
+
`RecordView` and composes one complete `Table`, so editing, hierarchy, growing, row movement,
|
|
1110
|
+
responsive stacking, loading, and advanced table events remain available through `getTable()`.
|
|
1111
|
+
|
|
1112
|
+
- **Shared fields** — every view accepts `fields: [{id,label,get?,render?,sortValue?,sortable?,
|
|
1113
|
+
visible?,duplicate?,type?,view?}]`. Primitive rendered values become text; an explicit Node is
|
|
1114
|
+
adopted. `field.view.table` carries Table-only column keys without changing CardView or KanbanView.
|
|
1115
|
+
- **Shared options** — `data`, `recordId: 'ID'`, `sort`, `sortMode: 'local'|'server'`,
|
|
1116
|
+
`selectable: false|'single'|'multi'`, `selection`, `fieldOrder`, `hiddenFields`,
|
|
1117
|
+
`fieldControls: true`, and `emptyText`. At least one field remains visible.
|
|
1118
|
+
- **Shared methods** — `setData()`, `addData()`, `updateRecord()`, `removeRecord()`, `getRecord()`,
|
|
1119
|
+
`getData()`, field getters/order/visibility methods, `setSort()`/`getSort()`, selection methods,
|
|
1120
|
+
`setLoading()`, `getViewState()`, and `setViewState()`.
|
|
1121
|
+
- **Portable state** — `{version:1,fieldOrder,hiddenFields,sort}` is JSON-safe configuration only.
|
|
1122
|
+
Records, selection, DOM nodes, rendered values, and callbacks are never serialized. A state from
|
|
1123
|
+
one record view may seed another; unknown fields are ignored and new fields append.
|
|
1124
|
+
- **TableView composition** — `table: {...}` forwards every advanced Table option, while shared
|
|
1125
|
+
fields/data/id/sort/selection/visibility/order win on overlaps. `getTable()` returns the composed
|
|
1126
|
+
instance. Row events become shared `recordclick`/`recorddblclick` details.
|
|
1127
|
+
- **Events** — `recordclick`, `recorddblclick`, `datachange`, `selectionchange`, `sortchange`,
|
|
1128
|
+
`fieldvisibilitychange`, `fieldorderchange`, and `statechange {state,reason}`.
|
|
1129
|
+
<!-- /doc -->
|
|
1130
|
+
|
|
1131
|
+
<!-- doc:card-view -->
|
|
1132
|
+
### CardView
|
|
1133
|
+
|
|
1134
|
+
A responsive semantic record collection using the same fields, records, sort, selection, and
|
|
1135
|
+
portable state as TableView and KanbanView.
|
|
1136
|
+
|
|
1137
|
+
- **Options** — the shared RecordView options plus `titleField`, `subtitleField`, `preview`,
|
|
1138
|
+
`previewAlt`, `link`, `actions`, `groupBy`, `groupOrder`, `minCardWidth`, `maxColumns`,
|
|
1139
|
+
`variant: 'outlined'|'raised'|'filled'`, `loadingCount`, `headingLevel`, and `label`.
|
|
1140
|
+
- **Cards** — each record is a focusable `<li>` with a native title link, separate secondary
|
|
1141
|
+
actions, optional native multi-select checkbox, labelled metadata, and `aria-selected` state.
|
|
1142
|
+
Title/subtitle fields are not duplicated in metadata unless their field sets `duplicate:true`.
|
|
1143
|
+
- **Media and URLs** — `preview` accepts a field ID or callback returning an image URL,
|
|
1144
|
+
`{src,alt,fit}`, Node, or null. Executable/non-image schemes are rejected and image failures show
|
|
1145
|
+
a stable fallback. Title/action links are normalized; `_blank` links receive `noopener`.
|
|
1146
|
+
- **Grouping and layout** — `groupBy` is a field ID or callback; `groupOrder` may deliberately show
|
|
1147
|
+
empty groups. Cards reflow through container queries and may cap columns without viewport logic.
|
|
1148
|
+
- **Interaction** — Enter activates a focused card; Space toggles selection. Links, actions,
|
|
1149
|
+
selection controls, and selected text do not also activate the card. `recordaction` adds the
|
|
1150
|
+
resolved action to the shared event set.
|
|
1151
|
+
<!-- /doc -->
|
|
1152
|
+
|
|
1153
|
+
<!-- doc:kanban-view -->
|
|
1154
|
+
### KanbanView
|
|
1155
|
+
|
|
1156
|
+
A semantic record board with explicit or data-derived columns, optional swim lanes, shared record
|
|
1157
|
+
cards, advisory work-in-progress limits, and equivalent pointer/programmatic/keyboard movement.
|
|
1158
|
+
|
|
1159
|
+
- **Options** — the shared RecordView options plus `columnBy`, `columns`, `swimlaneBy`,
|
|
1160
|
+
`swimlanes`, card title/subtitle/preview/link/actions, `moveMode: 'local'|'external'`,
|
|
1161
|
+
`columnOrder`, `swimlaneOrder`, collapsed IDs, `showCounts`, `showEmptyColumns`, `variant`, and
|
|
1162
|
+
`label`. Column/lane descriptors use stable `id`, `label`, optional stored `value`, and `accept`;
|
|
1163
|
+
columns may also declare an advisory `limit`.
|
|
1164
|
+
- **Methods** — configure/get/move columns and swim lanes, collapse either axis, and
|
|
1165
|
+
`moveRecord(id,{column?,lane?,index?})`. Board-specific order/collapse joins the common view
|
|
1166
|
+
state; record order, movement history, and selection do not.
|
|
1167
|
+
- **Movement boundary** — `recordmove {record,id,from,to,column,swimlane,limitExceeded}` is
|
|
1168
|
+
cancelable and fires before a commit/request. `accept` is a hard eligibility gate; WIP is visual
|
|
1169
|
+
advice. Local mode clones the moved record and never mutates host data. External mode emits only,
|
|
1170
|
+
for server validation and optimistic rollback owned by ZeyOS.
|
|
1171
|
+
- **Keyboard** — focus the move handle; Enter/Space grabs or drops, Escape cancels, Left/Right
|
|
1172
|
+
chooses a column, Up/Down chooses a bucket-relative position, and Alt+Up/Down chooses a swim
|
|
1173
|
+
lane. A polite live region announces every target and result. Native drag is an enhancement.
|
|
1052
1174
|
<!-- /doc -->
|
|
1053
1175
|
|
|
1054
1176
|
<!-- doc:grid -->
|
|
@@ -1100,6 +1222,47 @@ code, so future adapters do not change the public `Chart` API.
|
|
|
1100
1222
|
for assistive technology; `'visible'` makes exact values part of the interface.
|
|
1101
1223
|
<!-- /doc -->
|
|
1102
1224
|
|
|
1225
|
+
<!-- doc:calendar -->
|
|
1226
|
+
### Calendar
|
|
1227
|
+
|
|
1228
|
+
A dependency-free scheduling surface for operational events. One component owns agenda, day,
|
|
1229
|
+
week, month, and year views; local-time range math; timed collision columns; multi-day lanes;
|
|
1230
|
+
loading and empty states; pointer range selection; and equivalent pointer/keyboard move and resize
|
|
1231
|
+
interactions. Visible ranges use an exclusive `end`, so `dateschange` can be passed directly to a
|
|
1232
|
+
windowed loader.
|
|
1233
|
+
|
|
1234
|
+
- **Options** — `events`, `date`, `view: 'month'`, `views: ['agenda','day','week','month','year']`,
|
|
1235
|
+
`locale`, `weekStart: 1`, `weekNumbers: true`, `workweek: false`, `agendaDays: 14`,
|
|
1236
|
+
`slotDuration: 30`, `slotMinTime: 0`, `slotMaxTime: 1440`, `scrollTime: 480`, `eventLimit: 3`,
|
|
1237
|
+
`selectable: false`, `editable: false`, `eventStartEditable`, `eventDurationEditable`,
|
|
1238
|
+
`optimistic: true`, `nowIndicator: true`, `now`, `disabled`, and `renderEvent(event)`.
|
|
1239
|
+
- **Event input** — generic records default to `{id,title,start,end,allDay,color,location,editable,
|
|
1240
|
+
durationEditable}`. Every field has a string-or-function reader (`eventId`, `eventTitle`,
|
|
1241
|
+
`eventStart`, …); numeric dates use `dateUnit: 'milliseconds'|'seconds'`. Inputs are normalized
|
|
1242
|
+
atomically, duplicate IDs and inverted intervals throw, Dates are copied, text is never parsed as
|
|
1243
|
+
HTML, and suspicious CSS colour strings are ignored.
|
|
1244
|
+
- **Methods** — `getEvents()`, `setEvents()`, `addEvent()`, `updateEvent()`, `removeEvent()`,
|
|
1245
|
+
`getDate()`, `setDate()`, `getView()`, `setView()`, `prev()`, `next()`, `today()`,
|
|
1246
|
+
`setLoading()`, `focusEvent()`, `destroy()`.
|
|
1247
|
+
- **Events** — `dateschange {view,start,end}`, `viewchange {view,oldView}`, `eventclick`,
|
|
1248
|
+
`eventdblclick`, `dateclick {date,allDay,view}`, `select {start,end,allDay,view}`,
|
|
1249
|
+
`new {date,view}`, `moreclick {date,count}`, `eventschange {events}`, and cancelable
|
|
1250
|
+
`eventchange {event,oldEvent,action,delta,jsEvent,revert}`.
|
|
1251
|
+
- **Persistence** — `optimistic: true` updates local events before `eventchange`; call the
|
|
1252
|
+
idempotent, version-guarded `detail.revert()` if persistence fails. With `optimistic: false`, the
|
|
1253
|
+
component stays controlled: it emits the proposal without changing data, and the application
|
|
1254
|
+
applies an accepted response through `updateEvent()` or `setEvents()`. Zx does not send requests.
|
|
1255
|
+
- **Keyboard** — time slots and date grids use arrow-key navigation, Home/End, PageUp/PageDown,
|
|
1256
|
+
Enter/Space activation, and roving focus. On an editable event, Space grabs it, arrows propose a
|
|
1257
|
+
slot/day move (or change the focused resize grip), Space drops, and Escape cancels. Live status
|
|
1258
|
+
text announces the edit and its proposed times.
|
|
1259
|
+
- **ZeyOS binding** — `zeyosCalendar()` maps current appointment occurrence rows (`ID`, `name`,
|
|
1260
|
+
`location`, `color`, `datefrom`, `dateto`, and association text). `calendarEventToZeyosPatch()`
|
|
1261
|
+
returns the base `ID` with Unix-second dates. The current server already expands recurrence into
|
|
1262
|
+
the requested window; recurrence rules, DAV synchronization, permissions, and routes therefore
|
|
1263
|
+
remain in ZeyOS instead of being reimplemented in core.
|
|
1264
|
+
<!-- /doc -->
|
|
1265
|
+
|
|
1103
1266
|
<!-- doc:data-filter -->
|
|
1104
1267
|
### DataFilter
|
|
1105
1268
|
|
|
@@ -1403,6 +1566,30 @@ so buttons and links in its action, content, and footer regions remain valid sib
|
|
|
1403
1566
|
container query when the card itself becomes narrow.
|
|
1404
1567
|
<!-- /doc -->
|
|
1405
1568
|
|
|
1569
|
+
<!-- doc:aurora -->
|
|
1570
|
+
### Aurora
|
|
1571
|
+
|
|
1572
|
+
A decorative, CSS-driven ambient light field for an existing application surface. Aurora enhances
|
|
1573
|
+
the target in place: it does not wrap, replace, or relocate the surface's content, and it does not
|
|
1574
|
+
own routing, overlays, or interaction. Its gradients sit behind the target's children, so raised
|
|
1575
|
+
Cards and other Liquid Glass surfaces can pick up the underlying colour naturally.
|
|
1576
|
+
|
|
1577
|
+
- **Options** — `preset: 'source'|'confluence'|'horizon'|'diagonal'|'edge'|'curtain'`,
|
|
1578
|
+
`colors: []` (zero to four concrete CSS colours),
|
|
1579
|
+
`intensity: 'subtle'|'balanced'|'vivid'`.
|
|
1580
|
+
- **Methods** — `setPreset(preset)`, `setColors(colors)`, `setIntensity(intensity)`.
|
|
1581
|
+
- **Palette** — an empty list uses semantic accent, info, success, and warning colours. One colour
|
|
1582
|
+
fills all four fields; two alternate; three repeat the second colour in the fourth field; four
|
|
1583
|
+
map directly. Network/image-bearing CSS values and palettes longer than four are rejected.
|
|
1584
|
+
- **Geometry** — Source starts at the leading chrome; Confluence meets from the corners; Horizon
|
|
1585
|
+
forms a shallow top band; Diagonal crosses the surface; Edge preserves a neutral centre; Curtain
|
|
1586
|
+
descends as four elongated fields. All use ordinary CSS gradients without animation.
|
|
1587
|
+
- **Lifecycle** — `destroy()` removes an owned root or restores every original attribute and child
|
|
1588
|
+
of an enhanced target. Content is never rebuilt when a setter changes the effect.
|
|
1589
|
+
- **Accessibility** — the light field is pointer-transparent and purely decorative. Forced-colour
|
|
1590
|
+
and reduced-transparency preferences remove it entirely.
|
|
1591
|
+
<!-- /doc -->
|
|
1592
|
+
|
|
1406
1593
|
<!-- doc:panel -->
|
|
1407
1594
|
### Panel / MasterPanel
|
|
1408
1595
|
|
package/docs/llms.txt
CHANGED
|
@@ -21,21 +21,26 @@ exports and as `window.zx.*`.
|
|
|
21
21
|
- [Contributor contract](https://github.com/zeyos/zx/blob/main/AGENTS.md): conventions for editing component source (token rules, render-time state, listeners, ARIA/APG).
|
|
22
22
|
|
|
23
23
|
## Components
|
|
24
|
-
- Inputs
|
|
25
|
-
`Toggle`, `Search`,
|
|
24
|
+
- Inputs: `button()`, `buttonGroup()`, `badge()`/`badgeGroup()`, `CheckButton`,
|
|
25
|
+
`Toggle`, `Search`,
|
|
26
26
|
`Select` (APG combobox; `filter: false|'local'|async`; priority, status, permission, and
|
|
27
27
|
`Select.entity()` presets), `Checklist`, `TagPicker` (icon/color identity), `NumberField`, `Rating`, `Slider`,
|
|
28
28
|
`copyButton()`/`CopyInput`, `DatePicker`, `MonthPicker`, `TimePicker`,
|
|
29
29
|
`Datebox`/`DateTimeBox`, `DateRangePicker`/`DateRangeBox`, `Timebox`.
|
|
30
30
|
- Overlays: `Message` (toasts/inline/progress), `Modal`, `Dialog` (+ `alert`/`confirm`/`prompt` Promises), `Sheet` (edge-anchored Dialog; `side`, `modal: true|'trap-focus'|false`, `backdrop`, `snap` detents, swipe-to-dismiss), `SheetStack` (drill-down; `stack`/`cascade`), `Dropdown`, `MenuButton`, `ContextMenu` (right-click; `selector` for per-row menus), `Tooltip`/`tooltip()`/`describe()`.
|
|
31
31
|
- Data: `Table` (sortable, selectable, sticky header, opt-in inline cell/row editing, row reorder,
|
|
32
|
-
column visibility), `
|
|
33
|
-
`
|
|
32
|
+
column visibility), shared `RecordView` state through `TableView`, `CardView`, and `KanbanView`,
|
|
33
|
+
`Grid` with single-click editing and `Grid.BillingItems()`, engine-neutral
|
|
34
|
+
`Chart` with injected `ChartJsAdapter`, `Calendar` (agenda/day/week/month/year, pointer/keyboard
|
|
35
|
+
drag and resize, `optimistic: true|false`), backend-neutral nested `Filter`, simple client-side
|
|
34
36
|
`DataFilter`, `Pagination` (+ pure `paginationRange()`), `TreeView` (APG tree),
|
|
35
37
|
`Finder` (Miller columns).
|
|
36
38
|
- Forms: `Form`, `Fieldset`, `Questionnaire` (guided one-question-at-a-time flow with branching), `Field` (type registry), `ValueList`, `MultiValueEditor`, `FieldUpload`.
|
|
37
39
|
- Layout: `stack()`/`grid()`/`aspect()` (spacing, an intrinsically reflowing grid, a fixed-ratio
|
|
38
|
-
box), `Groupbox`, `Card` (media/title link/actions/footer), `
|
|
40
|
+
box), `Groupbox`, `Card` (media/title link/actions/footer), `AppIcon` (generic tile geometry;
|
|
41
|
+
circular `zeyosAppIcon()` application presets and compact `moduleChip()` identities),
|
|
42
|
+
`Aurora` (one- to four-colour ambient
|
|
43
|
+
canvas light; shared material roles govern chrome and overlays), `Avatar`, `Panel` (header/footer action
|
|
39
44
|
buttons), `MasterPanel`, `Tabbox`
|
|
40
45
|
(`variant: 'divided'|'bracket'|'line'|'segmented'`), `NavigationBar`, `AppSidebar` (expanded and
|
|
41
46
|
minimized vertical states plus horizontal rail layouts), `AccountMenu`, `Launcher`,
|
|
@@ -47,11 +52,16 @@ exports and as `window.zx.*`.
|
|
|
47
52
|
- Helpers: `formatNumber`/`formatCurrency`/`formatPercent`/`formatFileSize`/`formatRelativeTime` (locale-aware, cached `Intl`), `debounce`/`throttle`, `groupBy`/`sortBy`/`uniqueBy`, `escapeRegExp`/`highlightMatch`, `storage()` (namespaced JSON, degrades to memory), `toCsv`/`downloadBlob`/`copyToClipboard`, `truncate()`/`isTruncated()` (line clamp with the full value on hover).
|
|
48
53
|
|
|
49
54
|
## Theming
|
|
50
|
-
Load `zx.css` once; set `data-zx-theme` (`light`|`dark`|`auto`) and `data-zx-density` (`cozy`|`compact`) on any ancestor. Define a product theme by overriding semantic `--zx-color-*` / `--zx-control-*` tokens under `[data-zx-theme="name"]`. The theme studio controls accent, neutral tint, density, font, type size, radius, control height, and CSS-first glass material. Never use tier-1 palette tokens or raw color literals in application CSS.
|
|
55
|
+
Load `zx.css` once; set `data-zx-theme` (`light`|`dark`|`auto`) and `data-zx-density` (`cozy`|`compact`) on any ancestor. Define a product theme by overriding semantic `--zx-color-*` / `--zx-control-*` tokens under `[data-zx-theme="name"]`. The theme studio controls accent, neutral tint, density, font, type size, radius, control height, and CSS-first glass material. Compact menus, pickers, tooltips, column menus, and toasts share a floating overlay material; Launcher, Modal, Dialog, and overlay Sheets share a more opaque panel material. Docked Sheets and dense data surfaces remain opaque. Never use tier-1 palette tokens or raw color literals in application CSS.
|
|
51
56
|
|
|
52
57
|
## Talking to ZeyOS
|
|
53
58
|
Use the dedicated ZeyOS client library **`@zeyos/client`** (`npm install @zeyos/client`) for ZeyOS business data: `createZeyosClient({ platform, auth })`, typed `client.api.list/get/create/update<Resource>` over the full OpenAPI surface, and `normalizeListResult`. Zx accepts the client by injection and does not bundle it. See the `website/layouts/zeyos-invoices.layout.js` layout for a Zx-components-on-@zeyos/client reference. Zx also ships a minimal `Http`/`zeyosService` for ad-hoc in-app `remotecall`, but `@zeyos/client` is the recommended default.
|
|
54
59
|
|
|
60
|
+
The optional `./zeyos` entry maps schemas into all three record views. `SavedViewRegistry` adds
|
|
61
|
+
private named configurations scoped by authenticated user, workspace/fork (including null for the
|
|
62
|
+
base workspace), and resource through an injected atomic transport. The compatibility transport
|
|
63
|
+
reuses ZeyOS `userfields`; records, selection, pages, callbacks, and DOM are never persisted.
|
|
64
|
+
|
|
55
65
|
## Installing
|
|
56
66
|
`npm install @zeyos/zx`. Entry points: `.` (components), `./zeyos` (ZeyOS binding), `./zx.css`
|
|
57
67
|
(styles), and `./global` (classic script tag). Docs: https://zx.zeyos.com
|
package/package.json
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
--zx-app-icon-size: 36px;
|
|
3
3
|
--zx-app-icon-glyph-size: 52%;
|
|
4
4
|
--zx-app-icon-color: var(--zx-color-accent);
|
|
5
|
+
--zx-app-icon-core: color-mix(in srgb, var(--zx-app-icon-color) var(--zx-app-icon-core-strength), var(--zx-color-app-icon-shade));
|
|
6
|
+
--zx-app-icon-rim: color-mix(in srgb, var(--zx-app-icon-color) var(--zx-app-icon-rim-strength), var(--zx-app-icon-rim-base));
|
|
7
|
+
--zx-app-icon-bloom: color-mix(in srgb, var(--zx-app-icon-color) var(--zx-app-icon-bloom-strength), transparent);
|
|
8
|
+
--zx-app-icon-specular: color-mix(in srgb, var(--zx-color-glass-highlight-strong) var(--zx-app-icon-specular-strength), transparent);
|
|
9
|
+
--zx-app-icon-halo: 0 0 var(--zx-app-icon-halo-size) color-mix(in srgb, var(--zx-app-icon-color) var(--zx-app-icon-halo-strength), transparent);
|
|
10
|
+
--zx-app-icon-selected-ring: color-mix(in srgb, var(--zx-app-icon-color) 54%, transparent);
|
|
5
11
|
position: relative;
|
|
6
12
|
isolation: isolate;
|
|
7
13
|
display: inline-grid;
|
|
@@ -9,71 +15,134 @@
|
|
|
9
15
|
flex: none;
|
|
10
16
|
inline-size: var(--zx-app-icon-size);
|
|
11
17
|
block-size: var(--zx-app-icon-size);
|
|
12
|
-
overflow:
|
|
13
|
-
border:
|
|
14
|
-
|
|
15
|
-
background: var(--zx-app-icon-color);
|
|
16
|
-
box-shadow: var(--zx-app-icon-shadow);
|
|
17
|
-
color: var(--zx-app-icon-glyph, var(--zx-color-text-invert));
|
|
18
|
+
overflow: visible;
|
|
19
|
+
border-radius: max(var(--zx-radius-sm), calc(var(--zx-app-icon-size) * .12));
|
|
20
|
+
color: var(--zx-app-icon-glyph, var(--zx-color-app-icon-glyph));
|
|
18
21
|
font-size: var(--zx-app-icon-size);
|
|
19
22
|
vertical-align: middle;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
.zx-app-icon[data-
|
|
23
|
-
|
|
25
|
+
.zx-app-icon[data-shape="circle"] {
|
|
26
|
+
border-radius: var(--zx-radius-full);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.zx-app-icon__surface {
|
|
30
|
+
position: absolute;
|
|
31
|
+
z-index: 0;
|
|
32
|
+
inset: 0;
|
|
33
|
+
display: grid;
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
place-items: center;
|
|
36
|
+
border: 1px solid var(--zx-app-icon-rim);
|
|
37
|
+
border-radius: inherit;
|
|
38
|
+
background: var(--zx-app-icon-core);
|
|
39
|
+
box-shadow: var(--zx-app-icon-shadow);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.zx-app-icon[data-glass="subtle"] .zx-app-icon__surface,
|
|
43
|
+
.zx-app-icon[data-glass="strong"] .zx-app-icon__surface {
|
|
24
44
|
background:
|
|
25
|
-
|
|
26
|
-
|
|
45
|
+
radial-gradient(112% 92% at 50% 122%, var(--zx-app-icon-bloom), transparent 64%),
|
|
46
|
+
var(--zx-app-icon-core);
|
|
47
|
+
-webkit-backdrop-filter: none;
|
|
48
|
+
backdrop-filter: none;
|
|
27
49
|
}
|
|
28
50
|
|
|
29
|
-
.zx-app-icon[data-glass="strong"] {
|
|
30
|
-
|
|
51
|
+
.zx-app-icon[data-glass="strong"] .zx-app-icon__surface {
|
|
52
|
+
box-shadow: var(--zx-app-icon-shadow-hover), var(--zx-app-icon-halo);
|
|
31
53
|
}
|
|
32
54
|
|
|
33
|
-
.zx-app-icon[data-glass="none"] {
|
|
34
|
-
border-color: var(--zx-color-border);
|
|
55
|
+
.zx-app-icon[data-glass="none"] .zx-app-icon__surface {
|
|
56
|
+
border-color: color-mix(in srgb, var(--zx-app-icon-color) 62%, var(--zx-color-border));
|
|
57
|
+
background: color-mix(in srgb, var(--zx-app-icon-color) 72%, var(--zx-color-app-icon-shade));
|
|
35
58
|
box-shadow: none;
|
|
36
59
|
}
|
|
37
60
|
|
|
38
61
|
.zx-app-icon[data-glass="none"] .zx-app-icon__shine { display: none; }
|
|
62
|
+
.zx-app-icon[data-glass="none"] .zx-app-icon__surface::after { display: none; }
|
|
39
63
|
|
|
40
|
-
.zx-app-icon[data-selected] {
|
|
41
|
-
outline:
|
|
42
|
-
box-shadow: 0 0 0
|
|
64
|
+
.zx-app-icon[data-selected] .zx-app-icon__surface {
|
|
65
|
+
outline: none;
|
|
66
|
+
box-shadow: 0 0 0 1px var(--zx-color-bg-page),
|
|
67
|
+
0 0 0 3px var(--zx-app-icon-selected-ring),
|
|
68
|
+
var(--zx-app-icon-shadow-hover),
|
|
69
|
+
var(--zx-app-icon-halo);
|
|
43
70
|
}
|
|
44
71
|
|
|
45
72
|
.zx-app-icon__shine {
|
|
46
73
|
position: absolute;
|
|
47
|
-
z-index:
|
|
48
|
-
inset:
|
|
49
|
-
block-size:
|
|
50
|
-
border-radius:
|
|
51
|
-
background: linear-gradient(
|
|
52
|
-
|
|
74
|
+
z-index: 1;
|
|
75
|
+
inset: 2px 18% auto;
|
|
76
|
+
block-size: 1px;
|
|
77
|
+
border-radius: var(--zx-radius-full);
|
|
78
|
+
background: linear-gradient(90deg, transparent, var(--zx-app-icon-specular), transparent);
|
|
79
|
+
opacity: .72;
|
|
80
|
+
pointer-events: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.zx-app-icon[data-glass="strong"] .zx-app-icon__shine { opacity: .9; }
|
|
84
|
+
|
|
85
|
+
.zx-app-icon__surface::after {
|
|
86
|
+
content: "";
|
|
87
|
+
position: absolute;
|
|
88
|
+
z-index: 1;
|
|
89
|
+
inset: 0;
|
|
90
|
+
border-radius: inherit;
|
|
91
|
+
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--zx-color-glass-highlight) 56%, transparent);
|
|
92
|
+
opacity: .56;
|
|
53
93
|
pointer-events: none;
|
|
54
94
|
}
|
|
55
95
|
|
|
56
96
|
.zx-app-icon__glyph {
|
|
57
|
-
|
|
97
|
+
position: absolute;
|
|
98
|
+
z-index: 2;
|
|
99
|
+
inset-block-start: 50%;
|
|
100
|
+
inset-inline-start: 50%;
|
|
101
|
+
display: grid;
|
|
58
102
|
place-items: center;
|
|
59
103
|
inline-size: var(--zx-app-icon-glyph-size);
|
|
60
104
|
block-size: var(--zx-app-icon-glyph-size);
|
|
105
|
+
margin: 0;
|
|
106
|
+
padding: 0;
|
|
61
107
|
font-size: var(--zx-app-icon-glyph-size);
|
|
62
108
|
line-height: 1;
|
|
63
|
-
filter:
|
|
109
|
+
filter: none;
|
|
110
|
+
transform: translate(-50%, -50%);
|
|
64
111
|
}
|
|
65
112
|
|
|
66
113
|
.zx-app-icon__glyph > .zx-icon,
|
|
67
114
|
.zx-app-icon__glyph > svg,
|
|
68
115
|
.zx-app-icon__glyph > i {
|
|
116
|
+
display: grid;
|
|
117
|
+
place-items: center;
|
|
69
118
|
inline-size: 1em;
|
|
70
119
|
block-size: 1em;
|
|
120
|
+
margin: 0;
|
|
121
|
+
color: inherit;
|
|
122
|
+
font-size: 1em;
|
|
123
|
+
line-height: 1;
|
|
124
|
+
text-align: center;
|
|
125
|
+
vertical-align: middle;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.zx-app-icon__glyph > i::before {
|
|
129
|
+
display: block;
|
|
130
|
+
line-height: 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.zx-app-icon__glyph svg [fill]:not([fill="none"]) {
|
|
134
|
+
fill: currentColor;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.zx-app-icon__glyph svg [stroke]:not([stroke="none"]) {
|
|
138
|
+
stroke: currentColor;
|
|
71
139
|
}
|
|
72
140
|
|
|
73
141
|
.zx-app-icon__badge {
|
|
74
142
|
position: absolute;
|
|
75
|
-
|
|
76
|
-
inset-
|
|
143
|
+
z-index: 3;
|
|
144
|
+
inset-block-start: -3px;
|
|
145
|
+
inset-inline-end: -3px;
|
|
77
146
|
display: grid;
|
|
78
147
|
place-items: center;
|
|
79
148
|
min-inline-size: 14px;
|
|
@@ -88,18 +157,59 @@
|
|
|
88
157
|
line-height: 1;
|
|
89
158
|
}
|
|
90
159
|
|
|
160
|
+
.zx-app-icon:is(a, button, [role="button"]):not(:disabled):not([aria-disabled="true"]):hover .zx-app-icon__surface,
|
|
161
|
+
:is(a, button, [role="button"]):not(:disabled):not([aria-disabled="true"]):hover .zx-app-icon__surface {
|
|
162
|
+
border-color: color-mix(in srgb, var(--zx-app-icon-color) 76%, var(--zx-color-glass-highlight-strong));
|
|
163
|
+
box-shadow: var(--zx-app-icon-shadow-hover), var(--zx-app-icon-halo);
|
|
164
|
+
filter: brightness(1.06) saturate(1.04);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.zx-app-icon:is(a, button, [role="button"]):not(:disabled):not([aria-disabled="true"]):focus-visible .zx-app-icon__surface,
|
|
168
|
+
:is(a, button, [role="button"]):not(:disabled):not([aria-disabled="true"]):focus-visible .zx-app-icon__surface {
|
|
169
|
+
outline: none;
|
|
170
|
+
box-shadow: var(--zx-focus-ring), var(--zx-app-icon-shadow-hover), var(--zx-app-icon-halo);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
174
|
+
.zx-app-icon__surface {
|
|
175
|
+
transition: border-color var(--zx-dur-fast) var(--zx-ease),
|
|
176
|
+
box-shadow var(--zx-dur-fast) var(--zx-ease),
|
|
177
|
+
filter var(--zx-dur-fast) var(--zx-ease);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
91
181
|
@media (prefers-reduced-transparency: reduce) {
|
|
92
|
-
.zx-app-icon[data-glass="strong"] {
|
|
93
|
-
background: var(--zx-app-icon-
|
|
182
|
+
.zx-app-icon[data-glass="strong"] .zx-app-icon__surface {
|
|
183
|
+
background: var(--zx-app-icon-core);
|
|
184
|
+
-webkit-backdrop-filter: none;
|
|
185
|
+
backdrop-filter: none;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.zx-app-icon[data-glass="subtle"] .zx-app-icon__surface {
|
|
189
|
+
background: var(--zx-app-icon-core);
|
|
190
|
+
-webkit-backdrop-filter: none;
|
|
94
191
|
backdrop-filter: none;
|
|
95
192
|
}
|
|
96
193
|
}
|
|
97
194
|
|
|
98
195
|
@media (forced-colors: active) {
|
|
99
|
-
.zx-app-
|
|
196
|
+
.zx-app-icon__surface {
|
|
100
197
|
border-color: ButtonText;
|
|
101
198
|
background: ButtonFace;
|
|
102
199
|
color: ButtonText;
|
|
103
200
|
box-shadow: none;
|
|
201
|
+
filter: none;
|
|
202
|
+
transform: none;
|
|
203
|
+
-webkit-backdrop-filter: none;
|
|
204
|
+
backdrop-filter: none;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.zx-app-icon__surface::after,
|
|
208
|
+
.zx-app-icon__shine { display: none; }
|
|
209
|
+
|
|
210
|
+
.zx-app-icon__badge {
|
|
211
|
+
border-color: Canvas;
|
|
212
|
+
background: Highlight;
|
|
213
|
+
color: HighlightText;
|
|
104
214
|
}
|
|
105
215
|
}
|