@timmo001/groundwork-ui 0.5.0 → 0.6.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/custom-elements.json +427 -9
- package/package.json +1 -1
- package/src/gw-alert.ts +4 -0
- package/src/gw-app-bar.ts +106 -42
- package/src/gw-badge.ts +11 -2
- package/src/gw-banner.ts +4 -0
- package/src/gw-card.ts +6 -3
- package/src/gw-chip.ts +3 -0
- package/src/gw-command-menu.ts +7 -3
- package/src/gw-dialog.ts +15 -5
- package/src/gw-dot.ts +2 -0
- package/src/gw-expansion.ts +7 -2
- package/src/gw-facts.ts +13 -5
- package/src/gw-gauge.ts +11 -5
- package/src/gw-meter.ts +17 -4
- package/src/gw-notification-center.ts +14 -3
- package/src/gw-notification.ts +2 -0
- package/src/gw-option-list.ts +26 -5
- package/src/gw-page-header.ts +7 -3
- package/src/gw-popover.ts +14 -4
- package/src/gw-section-title.ts +3 -1
- package/src/gw-segmented.ts +2 -1
- package/src/gw-skeleton.ts +3 -1
- package/src/gw-spinner.ts +5 -1
- package/src/gw-theme-picker.ts +145 -40
- package/src/gw-toast.ts +3 -1
package/package.json
CHANGED
package/src/gw-alert.ts
CHANGED
|
@@ -23,6 +23,10 @@ import { base, type Tone } from "./styles.js";
|
|
|
23
23
|
* @slot actions - Buttons beside the message.
|
|
24
24
|
*
|
|
25
25
|
* @csspart alert - The alert.
|
|
26
|
+
*
|
|
27
|
+
* @cssprop --gw-tone - The icon color, for a tone of your own. `tone` sets it.
|
|
28
|
+
* @cssprop --gw-tone-fill - The background. `tone` sets it.
|
|
29
|
+
* @cssprop --gw-tone-border - The border. `tone` sets it.
|
|
26
30
|
*/
|
|
27
31
|
export class GwAlert extends GwElement {
|
|
28
32
|
static override properties = {
|
package/src/gw-app-bar.ts
CHANGED
|
@@ -13,21 +13,20 @@ const menuIcon = "M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z";
|
|
|
13
13
|
const closeIcon =
|
|
14
14
|
"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z";
|
|
15
15
|
|
|
16
|
-
/** Below this width the nav moves into a menu. */
|
|
17
|
-
const menuBelow = 600;
|
|
18
|
-
|
|
19
16
|
/**
|
|
20
17
|
* A site or app header pinned to the top of the page, with a brand, nav
|
|
21
18
|
* links and actions, full width with its content kept to the content width.
|
|
22
19
|
* It's transparent at first, then gets a blurred surface and a bottom border
|
|
23
20
|
* once the page scrolls, or once the element
|
|
24
21
|
* `reveal-after` names scrolls out of view, such as a hero. With
|
|
25
|
-
* `reveal-after` the brand stays hidden until then, so a
|
|
26
|
-
* hero hands over to the small one in the bar.
|
|
22
|
+
* `reveal-after` the brand stays hidden, taking no room, until then, so a
|
|
23
|
+
* large logo in the hero hands over to the small one in the bar. The nav
|
|
24
|
+
* slides over as it opens.
|
|
27
25
|
*
|
|
28
26
|
* `overlay` lays it over the top of the page rather than taking room, for a
|
|
29
|
-
* page that opens with a hero. Below 600px wide
|
|
30
|
-
* opened from a button, which closes on Esc, a
|
|
27
|
+
* page that opens with a hero. Below `menu-below`, 600px wide by default,
|
|
28
|
+
* the nav moves into a menu opened from a button, which closes on Esc, a
|
|
29
|
+
* click outside or a link. Raise it when the nav and actions need more room.
|
|
31
30
|
*
|
|
32
31
|
* @element gw-app-bar
|
|
33
32
|
* @summary A header pinned to the top, floating once the page scrolls.
|
|
@@ -35,6 +34,8 @@ const menuBelow = 600;
|
|
|
35
34
|
* @attr {string} reveal-after - A CSS selector for the element, such as a hero, to scroll past before the bar floats and the brand shows.
|
|
36
35
|
* @attr {boolean} overlay - Lays the bar over the top of the page instead of taking room.
|
|
37
36
|
* @attr {boolean} floating - Whether it floats. Set by the bar as the page scrolls.
|
|
37
|
+
* @attr {number} menu-below - The viewport width in pixels below which the nav moves into a menu. Defaults to `600`.
|
|
38
|
+
* @attr {boolean} collapsed - Whether the nav is in the menu. Set by the bar from `menu-below`.
|
|
38
39
|
* @attr {boolean} menu-open - Whether the nav menu is open on narrow screens.
|
|
39
40
|
* @attr {string} menu-label - The menu button's accessible name. Defaults to `Menu`.
|
|
40
41
|
*
|
|
@@ -43,7 +44,9 @@ const menuBelow = 600;
|
|
|
43
44
|
* @slot actions - Icon links and buttons at the end.
|
|
44
45
|
*
|
|
45
46
|
* @csspart bar - The bar.
|
|
47
|
+
* @csspart brand - The brand's container.
|
|
46
48
|
* @csspart nav - The nav links' container, the menu panel on narrow screens.
|
|
49
|
+
* @csspart actions - The actions' container.
|
|
47
50
|
*
|
|
48
51
|
* @fires {Event} toggle - When the nav menu opens or closes.
|
|
49
52
|
*/
|
|
@@ -54,6 +57,8 @@ export class GwAppBar extends GwElement {
|
|
|
54
57
|
floating: { type: "boolean", reflect: true },
|
|
55
58
|
menuOpen: { type: "boolean", attribute: "menu-open", reflect: true },
|
|
56
59
|
menuLabel: { attribute: "menu-label" },
|
|
60
|
+
menuBelow: { type: "number", attribute: "menu-below" },
|
|
61
|
+
collapsed: { type: "boolean", reflect: true },
|
|
57
62
|
} as const;
|
|
58
63
|
|
|
59
64
|
static override styles = [
|
|
@@ -97,24 +102,43 @@ export class GwAppBar extends GwElement {
|
|
|
97
102
|
backdrop-filter: blur(12px) saturate(1.4);
|
|
98
103
|
}
|
|
99
104
|
|
|
105
|
+
/* A one-column grid, so a hidden brand can fold its width to nothing
|
|
106
|
+
and the nav slides over as it opens, rather than leaving a gap */
|
|
100
107
|
.brand {
|
|
101
|
-
display:
|
|
108
|
+
display: grid;
|
|
102
109
|
flex: none;
|
|
110
|
+
grid-template-columns: 1fr;
|
|
103
111
|
align-items: center;
|
|
104
112
|
transition:
|
|
113
|
+
grid-template-columns var(--gw-motion-slow) var(--gw-motion-easing),
|
|
114
|
+
margin var(--gw-motion-slow) var(--gw-motion-easing),
|
|
105
115
|
opacity var(--gw-motion-normal) var(--gw-motion-easing),
|
|
106
116
|
translate var(--gw-motion-normal) var(--gw-motion-easing);
|
|
107
117
|
}
|
|
108
118
|
|
|
119
|
+
.brand > slot {
|
|
120
|
+
display: flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
min-width: 0;
|
|
123
|
+
overflow: clip;
|
|
124
|
+
overflow-clip-margin: calc(
|
|
125
|
+
var(--gw-focus-width) + var(--gw-focus-offset)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
109
129
|
:host([reveal-after]:not([floating])) .brand {
|
|
130
|
+
grid-template-columns: 0fr;
|
|
131
|
+
margin-inline-end: calc(var(--gw-space-3) * -1);
|
|
110
132
|
pointer-events: none;
|
|
111
133
|
visibility: hidden;
|
|
112
134
|
opacity: 0;
|
|
113
135
|
translate: 0 -0.25rem;
|
|
114
136
|
transition:
|
|
137
|
+
grid-template-columns var(--gw-motion-slow) var(--gw-motion-easing),
|
|
138
|
+
margin var(--gw-motion-slow) var(--gw-motion-easing),
|
|
115
139
|
opacity var(--gw-motion-normal) var(--gw-motion-easing),
|
|
116
140
|
translate var(--gw-motion-normal) var(--gw-motion-easing),
|
|
117
|
-
visibility var(--gw-motion-
|
|
141
|
+
visibility var(--gw-motion-slow) allow-discrete;
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
.nav {
|
|
@@ -152,37 +176,37 @@ export class GwAppBar extends GwElement {
|
|
|
152
176
|
background: var(--gw-color-fill-neutral-hovered);
|
|
153
177
|
}
|
|
154
178
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
/* Below menu-below, which sets collapsed, the nav folds into a menu */
|
|
180
|
+
:host([collapsed]) .menu {
|
|
181
|
+
display: inline-grid;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
:host([collapsed]) .nav {
|
|
185
|
+
position: absolute;
|
|
186
|
+
inset-block-start: 100%;
|
|
187
|
+
inset-inline: 0;
|
|
188
|
+
flex-direction: column;
|
|
189
|
+
gap: var(--gw-space-0-5);
|
|
190
|
+
align-items: stretch;
|
|
191
|
+
padding: var(--gw-space-2)
|
|
192
|
+
max(var(--gw-space-3), (100% - var(--gw-content-width)) / 2);
|
|
193
|
+
visibility: hidden;
|
|
194
|
+
background: var(--gw-color-surface-default);
|
|
195
|
+
border-block-end: max(var(--gw-border-width), 1px) solid
|
|
196
|
+
var(--gw-color-border-quiet);
|
|
197
|
+
box-shadow: var(--gw-shadow-m);
|
|
198
|
+
opacity: 0;
|
|
199
|
+
translate: 0 -0.5rem;
|
|
200
|
+
transition:
|
|
201
|
+
opacity var(--gw-motion-fast) var(--gw-motion-easing),
|
|
202
|
+
translate var(--gw-motion-normal) var(--gw-motion-easing),
|
|
203
|
+
visibility var(--gw-motion-normal) allow-discrete;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
:host([collapsed][menu-open]) .nav {
|
|
207
|
+
visibility: visible;
|
|
208
|
+
opacity: 1;
|
|
209
|
+
translate: 0 0;
|
|
186
210
|
}
|
|
187
211
|
`,
|
|
188
212
|
];
|
|
@@ -192,6 +216,18 @@ export class GwAppBar extends GwElement {
|
|
|
192
216
|
declare floating: boolean;
|
|
193
217
|
declare menuOpen: boolean;
|
|
194
218
|
declare menuLabel: string;
|
|
219
|
+
/** The viewport width in pixels below which the nav moves into a menu. */
|
|
220
|
+
declare menuBelow: number;
|
|
221
|
+
/** Whether the nav is in the menu. Set by the bar from `menuBelow`. */
|
|
222
|
+
declare collapsed: boolean;
|
|
223
|
+
|
|
224
|
+
#narrow: MediaQueryList | undefined;
|
|
225
|
+
|
|
226
|
+
readonly #onNarrow = () => {
|
|
227
|
+
this.collapsed = this.#narrow?.matches === true;
|
|
228
|
+
|
|
229
|
+
if (!this.collapsed) this.toggleMenu(false);
|
|
230
|
+
};
|
|
195
231
|
|
|
196
232
|
readonly #menuIcon = createIcon(menuIcon);
|
|
197
233
|
|
|
@@ -214,10 +250,23 @@ export class GwAppBar extends GwElement {
|
|
|
214
250
|
this.floating = false;
|
|
215
251
|
this.menuOpen = false;
|
|
216
252
|
this.menuLabel = "Menu";
|
|
253
|
+
this.menuBelow = 600;
|
|
254
|
+
this.collapsed = false;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Follows the viewport across `menuBelow`, setting `collapsed`. */
|
|
258
|
+
#watchWidth() {
|
|
259
|
+
this.#narrow?.removeEventListener("change", this.#onNarrow);
|
|
260
|
+
this.#narrow = window.matchMedia(
|
|
261
|
+
`(max-width: ${(Number(this.menuBelow) || 600) - 0.02}px)`,
|
|
262
|
+
);
|
|
263
|
+
this.#narrow.addEventListener("change", this.#onNarrow);
|
|
264
|
+
this.#onNarrow();
|
|
217
265
|
}
|
|
218
266
|
|
|
219
267
|
override connectedCallback() {
|
|
220
268
|
super.connectedCallback();
|
|
269
|
+
this.#watchWidth();
|
|
221
270
|
document.addEventListener("keydown", this.#onKeydown);
|
|
222
271
|
document.addEventListener("pointerdown", this.#onOutside, true);
|
|
223
272
|
|
|
@@ -232,6 +281,8 @@ export class GwAppBar extends GwElement {
|
|
|
232
281
|
|
|
233
282
|
override disconnectedCallback() {
|
|
234
283
|
this.#unwatch();
|
|
284
|
+
this.#narrow?.removeEventListener("change", this.#onNarrow);
|
|
285
|
+
this.#narrow = undefined;
|
|
235
286
|
document.removeEventListener("keydown", this.#onKeydown);
|
|
236
287
|
document.removeEventListener("pointerdown", this.#onOutside, true);
|
|
237
288
|
super.disconnectedCallback();
|
|
@@ -317,10 +368,19 @@ export class GwAppBar extends GwElement {
|
|
|
317
368
|
h(
|
|
318
369
|
"div",
|
|
319
370
|
{ class: "bar", part: "bar" },
|
|
320
|
-
|
|
371
|
+
// The menu button leads, so a revealed brand opens beside it
|
|
321
372
|
this.#menu,
|
|
373
|
+
h(
|
|
374
|
+
"div",
|
|
375
|
+
{ class: "brand", part: "brand" },
|
|
376
|
+
h("slot", { name: "brand" }),
|
|
377
|
+
),
|
|
322
378
|
this.#nav,
|
|
323
|
-
h(
|
|
379
|
+
h(
|
|
380
|
+
"div",
|
|
381
|
+
{ class: "actions", part: "actions" },
|
|
382
|
+
h("slot", { name: "actions" }),
|
|
383
|
+
),
|
|
324
384
|
),
|
|
325
385
|
);
|
|
326
386
|
}
|
|
@@ -331,6 +391,10 @@ export class GwAppBar extends GwElement {
|
|
|
331
391
|
setIconPath(this.#menuIcon, this.menuOpen ? closeIcon : menuIcon);
|
|
332
392
|
|
|
333
393
|
if (changed.has("revealAfter") && this.isConnected) this.#watch();
|
|
394
|
+
|
|
395
|
+
if (changed.has("menuBelow") && this.#narrow !== undefined) {
|
|
396
|
+
this.#watchWidth();
|
|
397
|
+
}
|
|
334
398
|
}
|
|
335
399
|
}
|
|
336
400
|
|
package/src/gw-badge.ts
CHANGED
|
@@ -27,6 +27,10 @@ import { base, createIcon, setIconPath, type Tone } from "./styles.js";
|
|
|
27
27
|
* @slot - The value.
|
|
28
28
|
*
|
|
29
29
|
* @csspart badge - The badge.
|
|
30
|
+
* @csspart label - The label above the value.
|
|
31
|
+
* @csspart value - The value.
|
|
32
|
+
*
|
|
33
|
+
* @cssprop --gw-tone - The icon's color, for a tone of your own. `tone` sets it.
|
|
30
34
|
*/
|
|
31
35
|
export class GwBadge extends GwElement {
|
|
32
36
|
static override properties = {
|
|
@@ -113,7 +117,7 @@ export class GwBadge extends GwElement {
|
|
|
113
117
|
|
|
114
118
|
readonly #iconSkeleton = h("gw-skeleton-icon");
|
|
115
119
|
|
|
116
|
-
readonly #label = h("span", { class: "label" });
|
|
120
|
+
readonly #label = h("span", { class: "label", part: "label" });
|
|
117
121
|
|
|
118
122
|
readonly #skeleton = h("gw-skeleton-text", {
|
|
119
123
|
style: "--gw-skeleton-width: 3rem",
|
|
@@ -138,7 +142,12 @@ export class GwBadge extends GwElement {
|
|
|
138
142
|
"span",
|
|
139
143
|
{ class: "info" },
|
|
140
144
|
this.#label,
|
|
141
|
-
h(
|
|
145
|
+
h(
|
|
146
|
+
"span",
|
|
147
|
+
{ class: "content", part: "value" },
|
|
148
|
+
this.#skeleton,
|
|
149
|
+
this.#value,
|
|
150
|
+
),
|
|
142
151
|
),
|
|
143
152
|
);
|
|
144
153
|
root.append(this.#badge);
|
package/src/gw-banner.ts
CHANGED
|
@@ -27,6 +27,10 @@ import { base, type Tone } from "./styles.js";
|
|
|
27
27
|
* @slot actions - One button, opening what it's about.
|
|
28
28
|
*
|
|
29
29
|
* @csspart bar - The bar.
|
|
30
|
+
*
|
|
31
|
+
* @cssprop --gw-tone - The text and icon color, for a tone of your own. `tone` sets it.
|
|
32
|
+
* @cssprop --gw-tone-fill - The background. `tone` sets it.
|
|
33
|
+
* @cssprop --gw-tone-border - The border. `tone` sets it.
|
|
30
34
|
*/
|
|
31
35
|
export class GwBanner extends GwElement {
|
|
32
36
|
static override properties = {
|
package/src/gw-card.ts
CHANGED
|
@@ -28,6 +28,9 @@ import { base } from "./styles.js";
|
|
|
28
28
|
* @slot actions - Buttons beside the heading.
|
|
29
29
|
*
|
|
30
30
|
* @csspart card - The card's surface.
|
|
31
|
+
* @csspart header - The row with the heading and actions.
|
|
32
|
+
* @csspart heading - The heading.
|
|
33
|
+
* @csspart body - The content.
|
|
31
34
|
*/
|
|
32
35
|
export class GwCard extends GwElement {
|
|
33
36
|
static override properties = {
|
|
@@ -107,14 +110,14 @@ export class GwCard extends GwElement {
|
|
|
107
110
|
|
|
108
111
|
readonly #header = h(
|
|
109
112
|
"header",
|
|
110
|
-
{},
|
|
111
|
-
h("h2", {}, this.#title, this.#titleSkeleton),
|
|
113
|
+
{ part: "header" },
|
|
114
|
+
h("h2", { part: "heading" }, this.#title, this.#titleSkeleton),
|
|
112
115
|
h("slot", { name: "actions" }),
|
|
113
116
|
);
|
|
114
117
|
|
|
115
118
|
readonly #skeleton = h("gw-skeleton-lines");
|
|
116
119
|
|
|
117
|
-
readonly #body = h("div", { class: "body" }, h("slot"));
|
|
120
|
+
readonly #body = h("div", { class: "body", part: "body" }, h("slot"));
|
|
118
121
|
|
|
119
122
|
#card: HTMLElement = h("section", { class: "card", part: "card" });
|
|
120
123
|
|
package/src/gw-chip.ts
CHANGED
|
@@ -24,6 +24,9 @@ import { base, createIcon, setIconPath, type Tone } from "./styles.js";
|
|
|
24
24
|
* @slot icon - An icon before the text, in place of `icon`.
|
|
25
25
|
*
|
|
26
26
|
* @csspart chip - The chip.
|
|
27
|
+
*
|
|
28
|
+
* @cssprop --gw-tone-fill - The tint, for a tone of your own. `tone` sets it.
|
|
29
|
+
* @cssprop --gw-tone-border - The border. `tone` sets it.
|
|
27
30
|
*/
|
|
28
31
|
export class GwChip extends GwElement {
|
|
29
32
|
static override properties = {
|
package/src/gw-command-menu.ts
CHANGED
|
@@ -28,6 +28,10 @@ const sheetBelow = 600;
|
|
|
28
28
|
* @attr {string} shortcut - The key that opens it with Cmd or Ctrl, such as `mod+k`, or `none`. Defaults to `mod+k`.
|
|
29
29
|
* @attr {boolean} open - Whether it shows.
|
|
30
30
|
*
|
|
31
|
+
* @csspart dialog - The menu's surface.
|
|
32
|
+
* @csspart list - The `gw-option-list` of commands.
|
|
33
|
+
* @csspart footer - The row of key hints.
|
|
34
|
+
*
|
|
31
35
|
* @fires {CustomEvent<{ value: string }>} pick - When a command is picked, with its `value` in `detail`.
|
|
32
36
|
*/
|
|
33
37
|
export class GwCommandMenu extends GwElement {
|
|
@@ -150,15 +154,15 @@ export class GwCommandMenu extends GwElement {
|
|
|
150
154
|
declare shortcut: string;
|
|
151
155
|
declare open: boolean;
|
|
152
156
|
|
|
153
|
-
readonly #list = h("gw-option-list", { search: true });
|
|
157
|
+
readonly #list = h("gw-option-list", { search: true, part: "list" });
|
|
154
158
|
|
|
155
159
|
readonly #dialog = h(
|
|
156
160
|
"dialog",
|
|
157
|
-
{},
|
|
161
|
+
{ part: "dialog" },
|
|
158
162
|
this.#list,
|
|
159
163
|
h(
|
|
160
164
|
"footer",
|
|
161
|
-
{ "aria-hidden": "true" },
|
|
165
|
+
{ part: "footer", "aria-hidden": "true" },
|
|
162
166
|
h("span", {}, h("kbd", {}, "↑"), " ", h("kbd", {}, "↓"), " to move"),
|
|
163
167
|
h("span", {}, h("kbd", {}, "Enter"), " to pick"),
|
|
164
168
|
h("span", {}, h("kbd", {}, "Esc"), " to close"),
|
package/src/gw-dialog.ts
CHANGED
|
@@ -28,6 +28,12 @@ const closeIcon =
|
|
|
28
28
|
* @slot - The content.
|
|
29
29
|
* @slot actions - Buttons; one with a `value` closes it with that value.
|
|
30
30
|
*
|
|
31
|
+
* @csspart dialog - The dialog's surface.
|
|
32
|
+
* @csspart header - The row with the heading and close button.
|
|
33
|
+
* @csspart heading - The heading.
|
|
34
|
+
* @csspart body - The content.
|
|
35
|
+
* @csspart footer - The actions row.
|
|
36
|
+
*
|
|
31
37
|
* @fires {Event} close - When it closes; `returnValue` holds the button's value.
|
|
32
38
|
*/
|
|
33
39
|
export class GwDialog extends GwElement {
|
|
@@ -139,9 +145,13 @@ export class GwDialog extends GwElement {
|
|
|
139
145
|
this.open = false;
|
|
140
146
|
}
|
|
141
147
|
|
|
142
|
-
readonly #heading = h("h2", { id: "heading" });
|
|
148
|
+
readonly #heading = h("h2", { id: "heading", part: "heading" });
|
|
143
149
|
|
|
144
|
-
readonly #footer = h(
|
|
150
|
+
readonly #footer = h(
|
|
151
|
+
"footer",
|
|
152
|
+
{ part: "footer" },
|
|
153
|
+
h("slot", { name: "actions" }),
|
|
154
|
+
);
|
|
145
155
|
|
|
146
156
|
readonly #closeButton = h(
|
|
147
157
|
"gw-button",
|
|
@@ -158,9 +168,9 @@ export class GwDialog extends GwElement {
|
|
|
158
168
|
|
|
159
169
|
readonly #dialog = h(
|
|
160
170
|
"dialog",
|
|
161
|
-
{ "aria-labelledby": "heading" },
|
|
162
|
-
h("header", {}, this.#heading, this.#closeButton),
|
|
163
|
-
h("div", { class: "body" }, h("slot")),
|
|
171
|
+
{ "aria-labelledby": "heading", part: "dialog" },
|
|
172
|
+
h("header", { part: "header" }, this.#heading, this.#closeButton),
|
|
173
|
+
h("div", { class: "body", part: "body" }, h("slot")),
|
|
164
174
|
this.#footer,
|
|
165
175
|
);
|
|
166
176
|
|
package/src/gw-dot.ts
CHANGED
|
@@ -17,6 +17,8 @@ import { base, type Tone } from "./styles.js";
|
|
|
17
17
|
* @attr {"neutral"|"accent"|"info"|"success"|"warning"|"danger"|"important"} tone - The color. Defaults to `neutral`.
|
|
18
18
|
* @attr {string} label - What it means, for assistive technology.
|
|
19
19
|
* @attr {boolean} pulse - Pulses, for something live.
|
|
20
|
+
*
|
|
21
|
+
* @cssprop --gw-tone - The color, for a tone of your own. `tone` sets it.
|
|
20
22
|
*/
|
|
21
23
|
export class GwDot extends GwElement {
|
|
22
24
|
static override properties = {
|
package/src/gw-expansion.ts
CHANGED
|
@@ -25,6 +25,8 @@ import { base } from "./styles.js";
|
|
|
25
25
|
*
|
|
26
26
|
* @csspart details - The native `<details>`.
|
|
27
27
|
* @csspart summary - The summary row.
|
|
28
|
+
* @csspart heading - The heading.
|
|
29
|
+
* @csspart description - The line under the heading.
|
|
28
30
|
* @csspart content - The content's wrapper.
|
|
29
31
|
*
|
|
30
32
|
* @fires {Event} toggle - When it opens or closes.
|
|
@@ -169,9 +171,12 @@ export class GwExpansion extends GwElement {
|
|
|
169
171
|
declare description: string;
|
|
170
172
|
declare open: boolean;
|
|
171
173
|
|
|
172
|
-
readonly #heading = h("span", { class: "heading" });
|
|
174
|
+
readonly #heading = h("span", { class: "heading", part: "heading" });
|
|
173
175
|
|
|
174
|
-
readonly #description = h("span", {
|
|
176
|
+
readonly #description = h("span", {
|
|
177
|
+
class: "description",
|
|
178
|
+
part: "description",
|
|
179
|
+
});
|
|
175
180
|
|
|
176
181
|
readonly #details = h(
|
|
177
182
|
"details",
|
package/src/gw-facts.ts
CHANGED
|
@@ -28,6 +28,10 @@ const skeletonWidths = ["60%", "40%", "75%", "50%", "65%"];
|
|
|
28
28
|
* @attr {Fact[]} items - The pairs, as JSON.
|
|
29
29
|
* @attr {boolean} loading - Shows skeleton pairs, keeping any labels already known.
|
|
30
30
|
* @attr {number} rows - How many skeleton pairs while loading. Defaults to 4.
|
|
31
|
+
*
|
|
32
|
+
* @csspart list - The description list.
|
|
33
|
+
* @csspart label - Each label.
|
|
34
|
+
* @csspart value - Each value.
|
|
31
35
|
*/
|
|
32
36
|
export class GwFacts extends GwElement {
|
|
33
37
|
static override properties = {
|
|
@@ -69,7 +73,7 @@ export class GwFacts extends GwElement {
|
|
|
69
73
|
declare loading: boolean;
|
|
70
74
|
declare rows: number;
|
|
71
75
|
|
|
72
|
-
readonly #list = h("dl");
|
|
76
|
+
readonly #list = h("dl", { part: "list" });
|
|
73
77
|
|
|
74
78
|
#rendered = false;
|
|
75
79
|
|
|
@@ -97,13 +101,13 @@ export class GwFacts extends GwElement {
|
|
|
97
101
|
...Array.from({ length: count }, (_, index) => [
|
|
98
102
|
h(
|
|
99
103
|
"dt",
|
|
100
|
-
{},
|
|
104
|
+
{ part: "label" },
|
|
101
105
|
items[index]?.label ??
|
|
102
106
|
h("gw-skeleton-text", { style: "--gw-skeleton-width: 5rem" }),
|
|
103
107
|
),
|
|
104
108
|
h(
|
|
105
109
|
"dd",
|
|
106
|
-
{},
|
|
110
|
+
{ part: "value" },
|
|
107
111
|
h("gw-skeleton-text", {
|
|
108
112
|
style: `--gw-skeleton-width: ${skeletonWidths[index % skeletonWidths.length]}`,
|
|
109
113
|
}),
|
|
@@ -114,8 +118,12 @@ export class GwFacts extends GwElement {
|
|
|
114
118
|
this.#list.removeAttribute("aria-busy");
|
|
115
119
|
this.#list.replaceChildren(
|
|
116
120
|
...items.flatMap((item) => [
|
|
117
|
-
h("dt", {}, item.label),
|
|
118
|
-
h(
|
|
121
|
+
h("dt", { part: "label" }, item.label),
|
|
122
|
+
h(
|
|
123
|
+
"dd",
|
|
124
|
+
{ part: "value" },
|
|
125
|
+
loaded ? h("span", {}, item.value) : item.value,
|
|
126
|
+
),
|
|
119
127
|
]),
|
|
120
128
|
);
|
|
121
129
|
}
|
package/src/gw-gauge.ts
CHANGED
|
@@ -76,6 +76,12 @@ const circle = (className: string) => {
|
|
|
76
76
|
* @attr {boolean} inverted - Lower is worse, such as for a battery.
|
|
77
77
|
* @attr {boolean} loading - Pulses the track and shows a skeleton for the reading.
|
|
78
78
|
*
|
|
79
|
+
* @csspart dial - The dial, with the arc and the reading.
|
|
80
|
+
* @csspart value - The reading's number.
|
|
81
|
+
* @csspart unit - The unit after it.
|
|
82
|
+
* @csspart label - What it measures.
|
|
83
|
+
* @csspart caption - The line under the label.
|
|
84
|
+
*
|
|
79
85
|
* @cssprop --gw-gauge-size - The dial's width. Defaults to `8.5rem`.
|
|
80
86
|
* @cssprop --gw-gauge-color - The arc's color, overriding the thresholds.
|
|
81
87
|
*/
|
|
@@ -208,11 +214,11 @@ export class GwGauge extends GwElement {
|
|
|
208
214
|
|
|
209
215
|
readonly #fill = circle("fill");
|
|
210
216
|
|
|
211
|
-
readonly #dial = h("div", { class: "dial", role: "meter" });
|
|
217
|
+
readonly #dial = h("div", { class: "dial", part: "dial", role: "meter" });
|
|
212
218
|
|
|
213
|
-
readonly #value = h("span", { class: "value" });
|
|
219
|
+
readonly #value = h("span", { class: "value", part: "value" });
|
|
214
220
|
|
|
215
|
-
readonly #unit = h("span", { class: "unit" });
|
|
221
|
+
readonly #unit = h("span", { class: "unit", part: "unit" });
|
|
216
222
|
|
|
217
223
|
readonly #shown = h("span", { class: "shown" }, this.#value, this.#unit);
|
|
218
224
|
|
|
@@ -220,9 +226,9 @@ export class GwGauge extends GwElement {
|
|
|
220
226
|
style: "--gw-skeleton-width: 2em",
|
|
221
227
|
});
|
|
222
228
|
|
|
223
|
-
readonly #label = h("span", { class: "label" });
|
|
229
|
+
readonly #label = h("span", { class: "label", part: "label" });
|
|
224
230
|
|
|
225
|
-
readonly #caption = h("span", { class: "caption" });
|
|
231
|
+
readonly #caption = h("span", { class: "caption", part: "caption" });
|
|
226
232
|
|
|
227
233
|
readonly #captionSkeleton = h("gw-skeleton-text", {
|
|
228
234
|
style: "--gw-skeleton-width: 5rem",
|
package/src/gw-meter.ts
CHANGED
|
@@ -26,6 +26,11 @@ import { base, type Tone } from "./styles.js";
|
|
|
26
26
|
* @attr {string} display - The value as shown, such as `42 GB`. Defaults to a percentage.
|
|
27
27
|
* @attr {"neutral"|"accent"|"info"|"success"|"warning"|"danger"|"important"} tone - A fixed color, overriding `high` and `critical`.
|
|
28
28
|
* @attr {boolean} loading - Pulses the track and shows a skeleton for the value.
|
|
29
|
+
*
|
|
30
|
+
* @csspart top - The row with the label and value.
|
|
31
|
+
* @csspart value - The value as shown.
|
|
32
|
+
* @csspart track - The bar's track.
|
|
33
|
+
* @csspart fill - The filled part of the bar.
|
|
29
34
|
*/
|
|
30
35
|
export class GwMeter extends GwElement {
|
|
31
36
|
static override properties = {
|
|
@@ -93,7 +98,7 @@ export class GwMeter extends GwElement {
|
|
|
93
98
|
declare tone: Tone | undefined;
|
|
94
99
|
declare loading: boolean;
|
|
95
100
|
|
|
96
|
-
readonly #top = h("div", { class: "top" });
|
|
101
|
+
readonly #top = h("div", { class: "top", part: "top" });
|
|
97
102
|
|
|
98
103
|
readonly #label = h("span");
|
|
99
104
|
|
|
@@ -101,15 +106,23 @@ export class GwMeter extends GwElement {
|
|
|
101
106
|
style: "--gw-skeleton-width: 6rem",
|
|
102
107
|
});
|
|
103
108
|
|
|
104
|
-
readonly #value = h("span", {
|
|
109
|
+
readonly #value = h("span", {
|
|
110
|
+
class: "value",
|
|
111
|
+
part: "value",
|
|
112
|
+
"aria-hidden": "true",
|
|
113
|
+
});
|
|
105
114
|
|
|
106
115
|
readonly #valueSkeleton = h("gw-skeleton-text", {
|
|
107
116
|
style: "--gw-skeleton-width: 2.5rem",
|
|
108
117
|
});
|
|
109
118
|
|
|
110
|
-
readonly #fill = h("div", { class: "fill" });
|
|
119
|
+
readonly #fill = h("div", { class: "fill", part: "fill" });
|
|
111
120
|
|
|
112
|
-
readonly #track = h(
|
|
121
|
+
readonly #track = h(
|
|
122
|
+
"div",
|
|
123
|
+
{ class: "track", part: "track", role: "meter" },
|
|
124
|
+
this.#fill,
|
|
125
|
+
);
|
|
113
126
|
|
|
114
127
|
readonly #bar = h("gw-skeleton", { class: "bar" });
|
|
115
128
|
|
|
@@ -29,6 +29,10 @@ const emptyIcon =
|
|
|
29
29
|
*
|
|
30
30
|
* @slot - The `gw-notification` cards.
|
|
31
31
|
*
|
|
32
|
+
* @csspart header - The row with the heading and Clear all.
|
|
33
|
+
* @csspart heading - The heading.
|
|
34
|
+
* @csspart list - The list of cards.
|
|
35
|
+
*
|
|
32
36
|
* @fires {Event} clear - When Clear all is pressed.
|
|
33
37
|
*/
|
|
34
38
|
export class GwNotificationCenter extends GwElement {
|
|
@@ -75,7 +79,7 @@ export class GwNotificationCenter extends GwElement {
|
|
|
75
79
|
|
|
76
80
|
declare heading: string;
|
|
77
81
|
|
|
78
|
-
readonly #heading = h("h2");
|
|
82
|
+
readonly #heading = h("h2", { part: "heading" });
|
|
79
83
|
|
|
80
84
|
readonly #clear = h(
|
|
81
85
|
"gw-button",
|
|
@@ -83,7 +87,11 @@ export class GwNotificationCenter extends GwElement {
|
|
|
83
87
|
"Clear all",
|
|
84
88
|
);
|
|
85
89
|
|
|
86
|
-
readonly #list = h(
|
|
90
|
+
readonly #list = h(
|
|
91
|
+
"div",
|
|
92
|
+
{ class: "list", part: "list", role: "list" },
|
|
93
|
+
h("slot"),
|
|
94
|
+
);
|
|
87
95
|
|
|
88
96
|
readonly #empty = h(
|
|
89
97
|
"gw-empty-state",
|
|
@@ -138,7 +146,10 @@ export class GwNotificationCenter extends GwElement {
|
|
|
138
146
|
this.#clear.addEventListener("click", () => {
|
|
139
147
|
this.clear();
|
|
140
148
|
});
|
|
141
|
-
root.append(
|
|
149
|
+
root.append(
|
|
150
|
+
h("header", { part: "header" }, this.#heading, this.#clear),
|
|
151
|
+
this.#body,
|
|
152
|
+
);
|
|
142
153
|
}
|
|
143
154
|
|
|
144
155
|
protected override update() {
|
package/src/gw-notification.ts
CHANGED
|
@@ -34,6 +34,8 @@ const closeIcon =
|
|
|
34
34
|
*
|
|
35
35
|
* @csspart card - The card.
|
|
36
36
|
*
|
|
37
|
+
* @cssprop --gw-tone - The icon's color, for a tone of your own. `tone` sets it.
|
|
38
|
+
*
|
|
37
39
|
* @fires {Event} dismiss - When the close button is pressed. Cancel it to keep the card.
|
|
38
40
|
*/
|
|
39
41
|
export class GwNotification extends GwElement {
|