@timmo001/groundwork-ui 0.5.0 → 0.7.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 +641 -27
- package/package.json +1 -1
- package/src/fields.ts +32 -6
- package/src/gw-alert.ts +4 -0
- package/src/gw-app-bar.ts +106 -42
- package/src/gw-badge.ts +40 -20
- package/src/gw-banner.ts +4 -0
- package/src/gw-button.ts +8 -24
- package/src/gw-card.ts +102 -6
- package/src/gw-chip.ts +29 -7
- 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-input.ts +7 -0
- package/src/gw-menu-button.ts +17 -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 +21 -8
- package/src/gw-select.ts +7 -0
- package/src/gw-setting-row.ts +21 -5
- 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/src/styles.ts +25 -0
package/package.json
CHANGED
package/src/fields.ts
CHANGED
|
@@ -70,12 +70,37 @@ export const fieldStyles = css`
|
|
|
70
70
|
fill: currentColor;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/* Sizes run xs to xl through --gw-field-scale, around 1 for medium, and
|
|
74
|
+
the control's height follows the theme's density too */
|
|
75
|
+
:where(gw-input, gw-select)[size="xs"] {
|
|
76
|
+
--gw-field-scale: 0.6;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
:where(gw-input, gw-select)[size="small"] {
|
|
80
|
+
--gw-field-scale: 0.8;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
:where(gw-input, gw-select)[size="large"] {
|
|
84
|
+
--gw-field-scale: 1.2;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
:where(gw-input, gw-select)[size="xl"] {
|
|
88
|
+
--gw-field-scale: 1.4;
|
|
89
|
+
}
|
|
90
|
+
|
|
73
91
|
:where(gw-input, gw-select) :where(input, .gw-select-trigger) {
|
|
92
|
+
--gw-field-size: var(--gw-field-scale, 1);
|
|
93
|
+
--gw-icon-size: calc(
|
|
94
|
+
1.25rem * var(--gw-field-size) * var(--gw-control-scale, 1)
|
|
95
|
+
);
|
|
96
|
+
|
|
74
97
|
width: 100%;
|
|
75
|
-
min-height:
|
|
76
|
-
|
|
98
|
+
min-height: calc(
|
|
99
|
+
2.5rem * var(--gw-field-size) * var(--gw-control-scale, 1)
|
|
100
|
+
);
|
|
101
|
+
padding: 0 calc(var(--gw-space-3) * var(--gw-field-size));
|
|
77
102
|
font: inherit;
|
|
78
|
-
font-size: var(--gw-font-size-s);
|
|
103
|
+
font-size: calc(var(--gw-font-size-s) * var(--gw-field-size));
|
|
79
104
|
color: var(--gw-color-text-strong);
|
|
80
105
|
background: var(--gw-color-surface-lower);
|
|
81
106
|
border: var(--gw-border-width) solid var(--gw-color-border-normal);
|
|
@@ -87,9 +112,9 @@ export const fieldStyles = css`
|
|
|
87
112
|
room around it that turns over while the list is open */
|
|
88
113
|
gw-select .gw-select-trigger {
|
|
89
114
|
display: flex;
|
|
90
|
-
gap: var(--gw-space-2);
|
|
115
|
+
gap: calc(var(--gw-space-2) * var(--gw-field-size));
|
|
91
116
|
align-items: center;
|
|
92
|
-
padding-inline-end: var(--gw-space-3);
|
|
117
|
+
padding-inline-end: calc(var(--gw-space-3) * var(--gw-field-size));
|
|
93
118
|
text-align: start;
|
|
94
119
|
cursor: pointer;
|
|
95
120
|
}
|
|
@@ -110,7 +135,8 @@ export const fieldStyles = css`
|
|
|
110
135
|
|
|
111
136
|
gw-select[inline-label] .gw-select-trigger {
|
|
112
137
|
width: auto;
|
|
113
|
-
padding-inline: var(--gw-space-4) var(--gw-
|
|
138
|
+
padding-inline: calc(var(--gw-space-4) * var(--gw-field-size))
|
|
139
|
+
calc(var(--gw-space-3) * var(--gw-field-size));
|
|
114
140
|
border-radius: var(--gw-radius-pill);
|
|
115
141
|
}
|
|
116
142
|
|
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
|
@@ -7,7 +7,13 @@
|
|
|
7
7
|
import { GwElement, css, h, setAttribute } from "./element.js";
|
|
8
8
|
import "./gw-skeleton.js";
|
|
9
9
|
import { fadeIn } from "./motion.js";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
base,
|
|
12
|
+
controlSizes,
|
|
13
|
+
createIcon,
|
|
14
|
+
setIconPath,
|
|
15
|
+
type Tone,
|
|
16
|
+
} from "./styles.js";
|
|
11
17
|
|
|
12
18
|
/**
|
|
13
19
|
* A pill with an icon, a value and an optional small label above it. The
|
|
@@ -21,12 +27,18 @@ import { base, createIcon, setIconPath, type Tone } from "./styles.js";
|
|
|
21
27
|
* @attr {string} icon - SVG path data for the icon.
|
|
22
28
|
* @attr {string} label - A small label above the value.
|
|
23
29
|
* @attr {"neutral"|"accent"|"info"|"success"|"warning"|"danger"|"important"} tone - The icon's color. Defaults to `accent`.
|
|
24
|
-
* @attr {"small"|"medium"} size - The size. Defaults to `medium`.
|
|
30
|
+
* @attr {"xs"|"small"|"medium"|"large"|"xl"} size - The size, around 36px tall at medium. Defaults to `medium`.
|
|
25
31
|
* @attr {boolean} loading - Shows a skeleton for the value, and the icon if it has none.
|
|
26
32
|
*
|
|
27
33
|
* @slot - The value.
|
|
28
34
|
*
|
|
29
35
|
* @csspart badge - The badge.
|
|
36
|
+
* @csspart label - The label above the value.
|
|
37
|
+
* @csspart value - The value.
|
|
38
|
+
*
|
|
39
|
+
* @cssprop --gw-tone - The icon's color, for a tone of your own. `tone` sets it.
|
|
40
|
+
* @cssprop --gw-badge-scale - Scales the badge, around 1 for medium.
|
|
41
|
+
* @cssprop --gw-control-scale - Scales its height and icon with the theme's density. The theme sets it.
|
|
30
42
|
*/
|
|
31
43
|
export class GwBadge extends GwElement {
|
|
32
44
|
static override properties = {
|
|
@@ -39,6 +51,7 @@ export class GwBadge extends GwElement {
|
|
|
39
51
|
|
|
40
52
|
static override styles = [
|
|
41
53
|
base,
|
|
54
|
+
controlSizes("badge"),
|
|
42
55
|
css`
|
|
43
56
|
:host {
|
|
44
57
|
display: inline-flex;
|
|
@@ -46,17 +59,21 @@ export class GwBadge extends GwElement {
|
|
|
46
59
|
vertical-align: middle;
|
|
47
60
|
}
|
|
48
61
|
|
|
49
|
-
/* 36px tall, 12px padding, 8px between the 18px icon and
|
|
62
|
+
/* 36px tall at medium, 12px padding, 8px between the 18px icon and
|
|
63
|
+
the text */
|
|
50
64
|
.badge {
|
|
51
|
-
--gw-
|
|
65
|
+
--gw-size: var(--gw-badge-scale, 1);
|
|
66
|
+
--gw-scale: calc(var(--gw-size) * var(--gw-control-scale, 1));
|
|
67
|
+
--gw-icon-size: calc(1.125rem * var(--gw-scale));
|
|
52
68
|
|
|
53
69
|
display: inline-flex;
|
|
54
|
-
gap: var(--gw-space-2);
|
|
70
|
+
gap: calc(var(--gw-space-2) * var(--gw-size));
|
|
55
71
|
align-items: center;
|
|
56
72
|
box-sizing: border-box;
|
|
57
73
|
max-width: 100%;
|
|
58
|
-
height: 2.25rem;
|
|
59
|
-
padding: 0 var(--gw-space-4)
|
|
74
|
+
height: calc(2.25rem * var(--gw-scale));
|
|
75
|
+
padding: 0 calc(var(--gw-space-4) * var(--gw-size)) 0
|
|
76
|
+
calc(var(--gw-space-3) * var(--gw-size));
|
|
60
77
|
vertical-align: middle;
|
|
61
78
|
color: var(--gw-color-text-strong);
|
|
62
79
|
background: var(--gw-color-surface-raised);
|
|
@@ -64,14 +81,6 @@ export class GwBadge extends GwElement {
|
|
|
64
81
|
border-radius: var(--gw-radius-pill);
|
|
65
82
|
}
|
|
66
83
|
|
|
67
|
-
:host([size="small"]) .badge {
|
|
68
|
-
--gw-icon-size: 1rem;
|
|
69
|
-
|
|
70
|
-
gap: var(--gw-space-1);
|
|
71
|
-
height: 1.75rem;
|
|
72
|
-
padding: 0 var(--gw-space-3) 0 var(--gw-space-2);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
84
|
.icon {
|
|
76
85
|
color: var(--gw-tone, var(--gw-color-accent));
|
|
77
86
|
}
|
|
@@ -83,13 +92,19 @@ export class GwBadge extends GwElement {
|
|
|
83
92
|
}
|
|
84
93
|
|
|
85
94
|
.label {
|
|
86
|
-
font-size:
|
|
95
|
+
font-size: max(
|
|
96
|
+
var(--gw-font-size-2xs),
|
|
97
|
+
calc(var(--gw-font-size-2xs) * var(--gw-size))
|
|
98
|
+
);
|
|
87
99
|
line-height: 1.1;
|
|
88
100
|
color: var(--gw-color-text-secondary);
|
|
89
101
|
}
|
|
90
102
|
|
|
91
103
|
.content {
|
|
92
|
-
font-size:
|
|
104
|
+
font-size: max(
|
|
105
|
+
var(--gw-font-size-2xs),
|
|
106
|
+
calc(var(--gw-font-size-xs) * var(--gw-size))
|
|
107
|
+
);
|
|
93
108
|
font-weight: var(--gw-font-weight-strong);
|
|
94
109
|
line-height: 1.2;
|
|
95
110
|
white-space: nowrap;
|
|
@@ -104,7 +119,7 @@ export class GwBadge extends GwElement {
|
|
|
104
119
|
declare icon: string;
|
|
105
120
|
declare label: string;
|
|
106
121
|
declare tone: Tone;
|
|
107
|
-
declare size: "small" | "medium";
|
|
122
|
+
declare size: "xs" | "small" | "medium" | "large" | "xl";
|
|
108
123
|
declare loading: boolean;
|
|
109
124
|
|
|
110
125
|
readonly #badge = h("span", { class: "badge", part: "badge" });
|
|
@@ -113,7 +128,7 @@ export class GwBadge extends GwElement {
|
|
|
113
128
|
|
|
114
129
|
readonly #iconSkeleton = h("gw-skeleton-icon");
|
|
115
130
|
|
|
116
|
-
readonly #label = h("span", { class: "label" });
|
|
131
|
+
readonly #label = h("span", { class: "label", part: "label" });
|
|
117
132
|
|
|
118
133
|
readonly #skeleton = h("gw-skeleton-text", {
|
|
119
134
|
style: "--gw-skeleton-width: 3rem",
|
|
@@ -138,7 +153,12 @@ export class GwBadge extends GwElement {
|
|
|
138
153
|
"span",
|
|
139
154
|
{ class: "info" },
|
|
140
155
|
this.#label,
|
|
141
|
-
h(
|
|
156
|
+
h(
|
|
157
|
+
"span",
|
|
158
|
+
{ class: "content", part: "value" },
|
|
159
|
+
this.#skeleton,
|
|
160
|
+
this.#value,
|
|
161
|
+
),
|
|
142
162
|
),
|
|
143
163
|
);
|
|
144
164
|
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-button.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
7
|
import { GwElement, css, h, setAttribute } from "./element.js";
|
|
8
|
-
import { base, createIcon, setIconPath } from "./styles.js";
|
|
8
|
+
import { base, controlSizes, createIcon, setIconPath } from "./styles.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* A native button styled through `--gw-*` variables, so it follows the
|
|
@@ -46,6 +46,7 @@ import { base, createIcon, setIconPath } from "./styles.js";
|
|
|
46
46
|
* @csspart button - The native button or link, or the pill around a slotted link.
|
|
47
47
|
*
|
|
48
48
|
* @cssprop --gw-button-scale - Scales every dimension, around 1 for medium.
|
|
49
|
+
* @cssprop --gw-control-scale - Scales its height and icon with the theme's density. The theme sets it.
|
|
49
50
|
* @cssprop --gw-button-tone - The color, set by `variant`.
|
|
50
51
|
* @cssprop --gw-button-ink - The text color, when it differs from the tone.
|
|
51
52
|
*/
|
|
@@ -71,6 +72,7 @@ export class GwButton extends GwElement {
|
|
|
71
72
|
|
|
72
73
|
static override styles = [
|
|
73
74
|
base,
|
|
75
|
+
controlSizes("button"),
|
|
74
76
|
css`
|
|
75
77
|
:host {
|
|
76
78
|
--gw-button-tone: var(--gw-color-accent);
|
|
@@ -78,25 +80,6 @@ export class GwButton extends GwElement {
|
|
|
78
80
|
display: inline-block;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
/* Everything scales from --gw-button-scale, around a 40px medium
|
|
82
|
-
button: the presets give 24, 32, 48 and 56px, and an app can set any
|
|
83
|
-
value for a size between or beyond them */
|
|
84
|
-
:host([size="xs"]) {
|
|
85
|
-
--gw-button-scale: 0.6;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
:host([size="small"]) {
|
|
89
|
-
--gw-button-scale: 0.8;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
:host([size="large"]) {
|
|
93
|
-
--gw-button-scale: 1.2;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
:host([size="xl"]) {
|
|
97
|
-
--gw-button-scale: 1.4;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
83
|
:host([variant="neutral"]) {
|
|
101
84
|
--gw-button-tone: var(--gw-color-text-secondary);
|
|
102
85
|
--gw-button-ink: var(--gw-color-text-strong);
|
|
@@ -119,18 +102,19 @@ export class GwButton extends GwElement {
|
|
|
119
102
|
}
|
|
120
103
|
|
|
121
104
|
.button {
|
|
122
|
-
--gw-
|
|
105
|
+
--gw-size: var(--gw-button-scale, 1);
|
|
106
|
+
--gw-scale: calc(var(--gw-size) * var(--gw-control-scale, 1));
|
|
123
107
|
--gw-icon-size: calc(1.125rem * var(--gw-scale));
|
|
124
108
|
|
|
125
109
|
position: relative;
|
|
126
110
|
display: inline-flex;
|
|
127
|
-
gap: calc(var(--gw-space-2) * var(--gw-
|
|
111
|
+
gap: calc(var(--gw-space-2) * var(--gw-size));
|
|
128
112
|
align-items: center;
|
|
129
113
|
justify-content: center;
|
|
130
114
|
min-height: calc(2.5rem * var(--gw-scale));
|
|
131
|
-
padding: 0 calc(var(--gw-space-4) * var(--gw-
|
|
115
|
+
padding: 0 calc(var(--gw-space-4) * var(--gw-size));
|
|
132
116
|
font: inherit;
|
|
133
|
-
font-size: calc(var(--gw-font-size-s) * var(--gw-
|
|
117
|
+
font-size: calc(var(--gw-font-size-s) * var(--gw-size));
|
|
134
118
|
font-weight: var(--gw-font-weight-strong);
|
|
135
119
|
line-height: 1;
|
|
136
120
|
color: var(--gw-button-ink, var(--gw-button-tone));
|