@crowdstrike/glide-core 0.31.2 → 0.32.1
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/dist/accordion.js +12 -2
- package/dist/accordion.styles.js +7 -0
- package/dist/button.js +3 -0
- package/dist/dropdown.styles.js +26 -5
- package/dist/input.styles.js +21 -5
- package/dist/library/request-idle-callback.d.ts +1 -0
- package/dist/library/request-idle-callback.js +5 -0
- package/dist/link.d.ts +2 -0
- package/dist/link.js +39 -16
- package/dist/menu.d.ts +5 -1
- package/dist/menu.js +63 -19
- package/dist/menu.styles.js +0 -1
- package/dist/modal.styles.js +6 -2
- package/dist/popover.d.ts +6 -2
- package/dist/popover.js +58 -57
- package/dist/slider.js +1 -0
- package/dist/styles/variables.css +4 -0
- package/dist/textarea.styles.js +21 -2
- package/dist/tooltip.d.ts +4 -4
- package/dist/tooltip.js +14 -14
- package/package.json +40 -27
package/dist/accordion.js
CHANGED
@@ -65,6 +65,9 @@ let Accordion = class Accordion extends LitElement {
|
|
65
65
|
return;
|
66
66
|
}
|
67
67
|
if (isOpen && hasChanged) {
|
68
|
+
// Used in a conditional below to avoid dispatching a "toggle" event on first
|
69
|
+
// render when Accordion is open initially.
|
70
|
+
const hasUpdated = this.hasUpdated;
|
68
71
|
// Wait for `.summary` to re-render after the "active" class addition to
|
69
72
|
// prevent animation jank, especially in Firefox and Safari.
|
70
73
|
this.updateComplete.then(() => {
|
@@ -87,7 +90,7 @@ let Accordion = class Accordion extends LitElement {
|
|
87
90
|
easing: getComputedStyle(this.#defaultSlotElementRef.value).getPropertyValue('--private-easing'),
|
88
91
|
})
|
89
92
|
.addEventListener('finish', () => {
|
90
|
-
if (this.#detailsElementRef.value) {
|
93
|
+
if (this.#detailsElementRef.value && hasUpdated) {
|
91
94
|
this.dispatchEvent(new Event('toggle', { bubbles: true, composed: true }));
|
92
95
|
}
|
93
96
|
});
|
@@ -140,7 +143,10 @@ let Accordion = class Accordion extends LitElement {
|
|
140
143
|
|
141
144
|
<div class="label-container">
|
142
145
|
<slot
|
143
|
-
class
|
146
|
+
class=${classMap({
|
147
|
+
'prefix-icon-slot': true,
|
148
|
+
'slotted-content': this.hasPrefixIcon,
|
149
|
+
})}
|
144
150
|
name="prefix-icon"
|
145
151
|
@slotchange=${this.#onPrefixIconSlotChange}
|
146
152
|
${ref(this.#prefixIconSlotElementRef)}
|
@@ -199,14 +205,18 @@ let Accordion = class Accordion extends LitElement {
|
|
199
205
|
#prefixIconSlotElementRef;
|
200
206
|
#suffixIconsSlotElementRef;
|
201
207
|
#summaryElementRef;
|
208
|
+
/* v8 ignore start */
|
202
209
|
#onPrefixIconSlotChange() {
|
203
210
|
const assignedNodes = this.#prefixIconSlotElementRef.value?.assignedNodes();
|
204
211
|
this.hasPrefixIcon = Boolean(assignedNodes && assignedNodes.length > 0);
|
205
212
|
}
|
213
|
+
/* v8 ignore end */
|
214
|
+
/* v8 ignore start */
|
206
215
|
#onSuffixIconsSlotChange() {
|
207
216
|
const assignedNodes = this.#suffixIconsSlotElementRef.value?.assignedNodes();
|
208
217
|
this.hasSuffixIcons = Boolean(assignedNodes && assignedNodes.length > 0);
|
209
218
|
}
|
219
|
+
/* v8 ignore end */
|
210
220
|
#onSummaryClick(event) {
|
211
221
|
// Canceling it prevents `details` from immediately showing and hiding
|
212
222
|
// the default slot on open and close, letting us animate it when we're ready.
|
package/dist/accordion.styles.js
CHANGED
package/dist/button.js
CHANGED
@@ -153,10 +153,13 @@ let Button = class Button extends LitElement {
|
|
153
153
|
return;
|
154
154
|
}
|
155
155
|
}
|
156
|
+
/* v8 ignore start */
|
156
157
|
#onPrefixIconSlotChange() {
|
157
158
|
const assignedNodes = this.#prefixIconSlotElementRef.value?.assignedNodes();
|
158
159
|
this.hasPrefixIcon = Boolean(assignedNodes && assignedNodes.length > 0);
|
159
160
|
}
|
161
|
+
/* v8 ignore end */
|
162
|
+
/* v8 ignore start */
|
160
163
|
#onSuffixIconSlotChange() {
|
161
164
|
const assignedNodes = this.#suffixIconSlotElementRef.value?.assignedNodes();
|
162
165
|
this.hasSuffixIcon = Boolean(assignedNodes && assignedNodes.length > 0);
|
package/dist/dropdown.styles.js
CHANGED
@@ -54,8 +54,12 @@ export default [
|
|
54
54
|
padding-inline: var(--glide-core-spacing-base-sm);
|
55
55
|
text-align: start;
|
56
56
|
transition:
|
57
|
-
background-color
|
58
|
-
|
57
|
+
background-color var(--glide-core-duration-moderate-02)
|
58
|
+
var(--glide-core-animation-swoop),
|
59
|
+
border-color var(--glide-core-duration-moderate-02)
|
60
|
+
var(--glide-core-animation-swoop),
|
61
|
+
box-shadow var(--glide-core-duration-moderate-02)
|
62
|
+
var(--glide-core-animation-swoop);
|
59
63
|
user-select: none;
|
60
64
|
|
61
65
|
&.quiet:not(.multiple) {
|
@@ -67,6 +71,10 @@ export default [
|
|
67
71
|
min-inline-size: 3.75rem;
|
68
72
|
padding-block: 0;
|
69
73
|
padding-inline: var(--glide-core-spacing-base-sm);
|
74
|
+
|
75
|
+
.error {
|
76
|
+
border-color: var(--glide-core-color-advisory-stroke-error-primary);
|
77
|
+
}
|
70
78
|
}
|
71
79
|
|
72
80
|
&.disabled {
|
@@ -110,9 +118,21 @@ export default [
|
|
110
118
|
border-color: var(--glide-core-color-interactive-stroke-focus);
|
111
119
|
}
|
112
120
|
|
113
|
-
&:has(.primary-button:focus-visible, .input:focus-visible)
|
114
|
-
|
121
|
+
&:has(.primary-button:focus-visible, .input:focus-visible):not(
|
122
|
+
.readonly
|
123
|
+
) {
|
124
|
+
&:not(.error) {
|
115
125
|
border-color: var(--glide-core-color-interactive-stroke-focus);
|
126
|
+
box-shadow:
|
127
|
+
0 0 0 1px var(--glide-core-color-interactive-stroke-focus),
|
128
|
+
1px 1px 4px -1px var(--glide-core-color-interactive-stroke-focus);
|
129
|
+
}
|
130
|
+
|
131
|
+
&.error {
|
132
|
+
box-shadow:
|
133
|
+
0 0 0 1px var(--glide-core-color-advisory-stroke-error-primary),
|
134
|
+
1px 1px 4px -1px
|
135
|
+
var(--glide-core-color-advisory-stroke-error-primary);
|
116
136
|
}
|
117
137
|
}
|
118
138
|
}
|
@@ -359,7 +379,8 @@ export default [
|
|
359
379
|
inline-size: 100%;
|
360
380
|
max-inline-size: 21.875rem;
|
361
381
|
padding-inline: 0.625rem;
|
362
|
-
transition: background-color
|
382
|
+
transition: background-color var(--glide-core-duration-fast-02)
|
383
|
+
var(--glide-core-animation-swoop);
|
363
384
|
user-select: none;
|
364
385
|
white-space: nowrap;
|
365
386
|
|
package/dist/input.styles.js
CHANGED
@@ -46,11 +46,11 @@ export default [
|
|
46
46
|
display: flex;
|
47
47
|
min-inline-size: 3.75rem;
|
48
48
|
padding-inline: var(--glide-core-spacing-base-sm);
|
49
|
-
transition:
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
transition:
|
50
|
+
border-color var(--glide-core-duration-moderate-02)
|
51
|
+
var(--glide-core-animation-swoop),
|
52
|
+
box-shadow var(--glide-core-duration-moderate-02)
|
53
|
+
var(--glide-core-animation-swoop);
|
54
54
|
|
55
55
|
&:not(.disabled, .error, .readonly) {
|
56
56
|
&:hover,
|
@@ -65,6 +65,22 @@ export default [
|
|
65
65
|
border-color: var(--glide-core-color-advisory-stroke-error-primary);
|
66
66
|
}
|
67
67
|
|
68
|
+
&.focused:not(.readonly) {
|
69
|
+
&:not(.error) {
|
70
|
+
border-color: var(--glide-core-color-interactive-stroke-focus);
|
71
|
+
box-shadow:
|
72
|
+
0 0 0 1px var(--glide-core-color-interactive-stroke-focus),
|
73
|
+
1px 1px 4px -1px var(--glide-core-color-interactive-stroke-focus);
|
74
|
+
}
|
75
|
+
|
76
|
+
&.error {
|
77
|
+
box-shadow:
|
78
|
+
0 0 0 1px var(--glide-core-color-advisory-stroke-error-primary),
|
79
|
+
1px 1px 4px -1px
|
80
|
+
var(--glide-core-color-advisory-stroke-error-primary);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
68
84
|
/*
|
69
85
|
We had to resort to a class selector because there may be a bug in Chrome and Safari
|
70
86
|
with ":read-only": https://bugs.chromium.org/p/chromium/issues/detail?id=1519649
|
@@ -0,0 +1 @@
|
|
1
|
+
export default function (): Promise<unknown>;
|
package/dist/link.d.ts
CHANGED
@@ -9,6 +9,7 @@ declare global {
|
|
9
9
|
* @attr {boolean} [disabled=false]
|
10
10
|
* @attr {string} [download]
|
11
11
|
* @attr {string} [href]
|
12
|
+
* @attr {string} [rel]
|
12
13
|
* @attr {'_blank'|'_parent'|'_self'|'_top'} [target]
|
13
14
|
*
|
14
15
|
* @readonly
|
@@ -22,6 +23,7 @@ export default class Link extends LitElement {
|
|
22
23
|
disabled: boolean;
|
23
24
|
download?: string;
|
24
25
|
href?: string;
|
26
|
+
rel?: string;
|
25
27
|
target?: '_blank' | '_parent' | '_self' | '_top';
|
26
28
|
readonly version: string;
|
27
29
|
click(): void;
|
package/dist/link.js
CHANGED
@@ -19,6 +19,7 @@ import required from './library/required.js';
|
|
19
19
|
* @attr {boolean} [disabled=false]
|
20
20
|
* @attr {string} [download]
|
21
21
|
* @attr {string} [href]
|
22
|
+
* @attr {string} [rel]
|
22
23
|
* @attr {'_blank'|'_parent'|'_self'|'_top'} [target]
|
23
24
|
*
|
24
25
|
* @readonly
|
@@ -41,22 +42,41 @@ let Link = class Link extends LitElement {
|
|
41
42
|
this.#componentElementRef.value?.click();
|
42
43
|
}
|
43
44
|
render() {
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
45
|
+
// Lit-a11y also wants a keyboard listener on anything with a "click" listener and
|
46
|
+
// doesn't account for `role="link"`.
|
47
|
+
//
|
48
|
+
/* eslint-disable lit-a11y/click-events-have-key-events */
|
49
|
+
return this.disabled
|
50
|
+
? html `<span
|
51
|
+
aria-disabled="true"
|
52
|
+
class=${classMap({
|
53
|
+
component: true,
|
54
|
+
disabled: this.disabled,
|
55
|
+
})}
|
56
|
+
data-test="component"
|
57
|
+
role="link"
|
58
|
+
tabindex="0"
|
59
|
+
@click=${this.#onClick}
|
60
|
+
${ref(this.#componentElementRef)}
|
61
|
+
>
|
62
|
+
${this.label}
|
63
|
+
</span>`
|
64
|
+
: html `<a
|
65
|
+
class=${classMap({
|
66
|
+
component: true,
|
67
|
+
disabled: this.disabled,
|
68
|
+
href: Boolean(this.href),
|
69
|
+
})}
|
70
|
+
data-test="component"
|
71
|
+
download=${ifDefined(this.download)}
|
72
|
+
href=${ifDefined(this.href)}
|
73
|
+
rel=${ifDefined(this.rel)}
|
74
|
+
target=${ifDefined(this.target)}
|
75
|
+
@click=${this.#onClick}
|
76
|
+
${ref(this.#componentElementRef)}
|
77
|
+
>
|
78
|
+
${this.label}
|
79
|
+
</a>`;
|
60
80
|
}
|
61
81
|
#componentElementRef;
|
62
82
|
#onClick(event) {
|
@@ -79,6 +99,9 @@ __decorate([
|
|
79
99
|
__decorate([
|
80
100
|
property({ reflect: true })
|
81
101
|
], Link.prototype, "href", void 0);
|
102
|
+
__decorate([
|
103
|
+
property({ reflect: true })
|
104
|
+
], Link.prototype, "rel", void 0);
|
82
105
|
__decorate([
|
83
106
|
property({ reflect: true })
|
84
107
|
], Link.prototype, "target", void 0);
|
package/dist/menu.d.ts
CHANGED
@@ -8,7 +8,7 @@ declare global {
|
|
8
8
|
* @attr {boolean} [loading=false]
|
9
9
|
* @attr {number} [offset=4]
|
10
10
|
* @attr {boolean} [open=false]
|
11
|
-
* @attr {'bottom'|'left'|'right'|'top'|'bottom-start'|'bottom-end'|'left-start'|'left-end'|'right-start'|'right-end'|'top-start'|'top-end'} [placement='bottom-start']
|
11
|
+
* @attr {'bottom'|'left'|'right'|'top'|'bottom-start'|'bottom-end'|'left-start'|'left-end'|'right-start'|'right-end'|'top-start'|'top-end'} [placement='bottom-start'] - Menu will try to move itself to the opposite of this value if not doing so would result in overflow. For example, if "bottom" results in overflow Menu will try "top" but not "right" or "left".
|
12
12
|
*
|
13
13
|
* @readonly
|
14
14
|
* @attr {string} [version]
|
@@ -37,6 +37,10 @@ export default class Menu extends LitElement {
|
|
37
37
|
*/
|
38
38
|
get open(): boolean;
|
39
39
|
set open(isOpen: boolean);
|
40
|
+
/**
|
41
|
+
* Menu will try to move itself to the opposite of this value if not doing so would result in overflow.
|
42
|
+
* For example, if "bottom" results in overflow Menu will try "top" but not "right" or "left".
|
43
|
+
*/
|
40
44
|
placement: 'bottom' | 'left' | 'right' | 'top' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end' | 'top-start' | 'top-end';
|
41
45
|
privateOpenedViaKeyboard: boolean;
|
42
46
|
readonly version: string;
|
package/dist/menu.js
CHANGED
@@ -25,7 +25,7 @@ import uniqueId from './library/unique-id.js';
|
|
25
25
|
* @attr {boolean} [loading=false]
|
26
26
|
* @attr {number} [offset=4]
|
27
27
|
* @attr {boolean} [open=false]
|
28
|
-
* @attr {'bottom'|'left'|'right'|'top'|'bottom-start'|'bottom-end'|'left-start'|'left-end'|'right-start'|'right-end'|'top-start'|'top-end'} [placement='bottom-start']
|
28
|
+
* @attr {'bottom'|'left'|'right'|'top'|'bottom-start'|'bottom-end'|'left-start'|'left-end'|'right-start'|'right-end'|'top-start'|'top-end'} [placement='bottom-start'] - Menu will try to move itself to the opposite of this value if not doing so would result in overflow. For example, if "bottom" results in overflow Menu will try "top" but not "right" or "left".
|
29
29
|
*
|
30
30
|
* @readonly
|
31
31
|
* @attr {string} [version]
|
@@ -38,6 +38,10 @@ import uniqueId from './library/unique-id.js';
|
|
38
38
|
let Menu = class Menu extends LitElement {
|
39
39
|
constructor() {
|
40
40
|
super(...arguments);
|
41
|
+
/**
|
42
|
+
* Menu will try to move itself to the opposite of this value if not doing so would result in overflow.
|
43
|
+
* For example, if "bottom" results in overflow Menu will try "top" but not "right" or "left".
|
44
|
+
*/
|
41
45
|
this.placement = 'bottom-start';
|
42
46
|
// Used in `#show()` to open the active Option's tooltip when Menu is opened via
|
43
47
|
// keyboard. Unlike mouse users, keyboard users can't hover an Option to reveal
|
@@ -55,7 +59,7 @@ let Menu = class Menu extends LitElement {
|
|
55
59
|
// `#onComponentFocusOut()` to decide if Menu should close. Also used in
|
56
60
|
// `#onTargetAndDefaultSlotKeyDown()` to decide if we need to move focus.
|
57
61
|
this.#hasVoiceOverMovedFocusToOptionsOrAnOption = false;
|
58
|
-
// Set in `#
|
62
|
+
// Set in `#onDefaultSlotClick()`. Used in `#onDocumentClick()` to guard against
|
59
63
|
// Menu closing when any number of things that are not an Option are clicked. Those
|
60
64
|
// "click" events will be retargeted to Menu's host the moment they bubble out of
|
61
65
|
// Menu. So checking in `#onDocumentClick()` if the click's `event.target` came
|
@@ -224,7 +228,7 @@ let Menu = class Menu extends LitElement {
|
|
224
228
|
}
|
225
229
|
}
|
226
230
|
if (this.#defaultSlotElementRef.value) {
|
227
|
-
// `popover` so Options can break out of Modal or another
|
231
|
+
// `popover` so Options can break out of Modal or another element that has
|
228
232
|
// `overflow: hidden`. Elements with `popover` are positioned relative to the
|
229
233
|
// viewport. Thus Floating UI in addition to `popover` until anchor positioning is
|
230
234
|
// well supported.
|
@@ -294,7 +298,6 @@ let Menu = class Menu extends LitElement {
|
|
294
298
|
@keydown=${this.#onTargetAndDefaultSlotKeyDown}
|
295
299
|
@mousedown=${this.#onDefaultSlotMouseDown}
|
296
300
|
@mouseover=${this.#onDefaultSlotMouseOver}
|
297
|
-
@mouseup=${this.#onDefaultSlotMouseUp}
|
298
301
|
@private-disabled-change=${this.#onDefaultSlotDisabledChange}
|
299
302
|
@private-slot-change=${this.#onDefaultSlotSlotChange}
|
300
303
|
@toggle=${this.#onDefaultSlotToggle}
|
@@ -316,7 +319,7 @@ let Menu = class Menu extends LitElement {
|
|
316
319
|
// `#onComponentFocusOut()` to decide if Menu should close. Also used in
|
317
320
|
// `#onTargetAndDefaultSlotKeyDown()` to decide if we need to move focus.
|
318
321
|
#hasVoiceOverMovedFocusToOptionsOrAnOption;
|
319
|
-
// Set in `#
|
322
|
+
// Set in `#onDefaultSlotClick()`. Used in `#onDocumentClick()` to guard against
|
320
323
|
// Menu closing when any number of things that are not an Option are clicked. Those
|
321
324
|
// "click" events will be retargeted to Menu's host the moment they bubble out of
|
322
325
|
// Menu. So checking in `#onDocumentClick()` if the click's `event.target` came
|
@@ -494,6 +497,7 @@ let Menu = class Menu extends LitElement {
|
|
494
497
|
}
|
495
498
|
}
|
496
499
|
#onDefaultSlotClick(event) {
|
500
|
+
this.#isDefaultSlotClick = true;
|
497
501
|
// When the padding or border on the default slot of a sub-Menu is clicked, the
|
498
502
|
// event will be retargeted by the browser to the sub-Menu's parent Option.
|
499
503
|
//
|
@@ -607,9 +611,6 @@ let Menu = class Menu extends LitElement {
|
|
607
611
|
event.preventDefault();
|
608
612
|
}
|
609
613
|
}
|
610
|
-
#onDefaultSlotMouseUp() {
|
611
|
-
this.#isDefaultSlotClick = true;
|
612
|
-
}
|
613
614
|
#onDefaultSlotSlotChange() {
|
614
615
|
const wasActiveOptionRemoved = this.#optionElements?.every((option) => option !== this.#activeOption);
|
615
616
|
if (wasActiveOptionRemoved &&
|
@@ -1146,6 +1147,60 @@ let Menu = class Menu extends LitElement {
|
|
1146
1147
|
}
|
1147
1148
|
#show() {
|
1148
1149
|
this.#cleanUpFloatingUi?.();
|
1150
|
+
// Ideally, we wouldn't show the popover until after Floating UI has calculated its
|
1151
|
+
// position. But calling `showPopover()` changes the nature of how `top` and `left`
|
1152
|
+
// affect an element's position when the element's containing block is something
|
1153
|
+
// other than the document.
|
1154
|
+
//
|
1155
|
+
// Unlike non-popovers, popovers break out of containing blocks¹. So `top` and
|
1156
|
+
// `left` are always relative to the document. For non-popovers, however, `top`
|
1157
|
+
// and `left` are relative to the element's containing block.
|
1158
|
+
//
|
1159
|
+
// Imagine that Menu has a parent with `transform: scale(1)` and we let Floating UI
|
1160
|
+
// calculate the default slot's position before calling `showPopover()`. Floating
|
1161
|
+
// UI will correctly position the default slot relative to that parent. But, after
|
1162
|
+
// `showPopover()` is called, Floating UI will recalculate the default slot's
|
1163
|
+
// position and position it relative to the document.
|
1164
|
+
//
|
1165
|
+
// The problem is, during the time between when `showPopover()` is called and
|
1166
|
+
// Floating UI does its recalculation, the default slot will have a `top` and
|
1167
|
+
// `left` that were correct when it was positioned relative to its containing
|
1168
|
+
// block, but are now incorrect. So the default slot will, for a moment, be
|
1169
|
+
// positioned above or below where it should be.
|
1170
|
+
//
|
1171
|
+
// The recalculation and subsequent repositioning will happen so quickly that the
|
1172
|
+
// user won't see it. But, if the user's mouse happens to be on top of the default
|
1173
|
+
// slot while it's positioned incorrectly, then `#onDefaultSlotMouseOver()` will
|
1174
|
+
// be called and whatever Option the user's mouse is on will be activated. Floating
|
1175
|
+
// UI will finish its work, then default slot will become visible. But the wrong
|
1176
|
+
// Option will be active when Menu finally appears open.
|
1177
|
+
//
|
1178
|
+
// To reproduce the issue:
|
1179
|
+
//
|
1180
|
+
// 1. Move the `showPopover()` call below inside `computePosition().then()`.
|
1181
|
+
// 2. Go to Menu's Overview page in Storybook.
|
1182
|
+
// 3. Place your mouse just above Menu's target.
|
1183
|
+
// 4. Tab to Menu's target.
|
1184
|
+
// 5. Press Space to open Menu.
|
1185
|
+
//
|
1186
|
+
// Note how the second or third Option is active instead of the first.
|
1187
|
+
//
|
1188
|
+
// I've omitted a test for this because calling `sendKey({ press: 'Tab' })`
|
1189
|
+
// followed by `sendKey({ press: ' ' })`, after moving the mouse above Menu's
|
1190
|
+
// target, introduces just enough of a delay for Floating UI to complete its
|
1191
|
+
// recalculation, making the issue impossible to reproduce in a test.
|
1192
|
+
//
|
1193
|
+
// 1. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_display/Containing_block#identifying_the_containing_block
|
1194
|
+
this.#defaultSlotElementRef.value?.showPopover();
|
1195
|
+
if (this.#isSubMenu && this.#parentOption) {
|
1196
|
+
this.#parentOption.ariaExpanded = 'true';
|
1197
|
+
}
|
1198
|
+
else if (!this.#isSubMenu && this.#targetElement) {
|
1199
|
+
this.#targetElement.ariaExpanded = 'true';
|
1200
|
+
}
|
1201
|
+
if (this.#optionsElement && this.#activeOption?.id) {
|
1202
|
+
this.#optionsElement.ariaActivedescendant = this.#activeOption.id;
|
1203
|
+
}
|
1149
1204
|
if (this.#previouslyActiveOption &&
|
1150
1205
|
!this.#previouslyActiveOption.disabled &&
|
1151
1206
|
this.#optionsElement) {
|
@@ -1178,17 +1233,6 @@ let Menu = class Menu extends LitElement {
|
|
1178
1233
|
left: `${x}px`,
|
1179
1234
|
top: `${y}px`,
|
1180
1235
|
});
|
1181
|
-
if (this.#isSubMenu && this.#parentOption) {
|
1182
|
-
this.#parentOption.ariaExpanded = 'true';
|
1183
|
-
}
|
1184
|
-
else if (!this.#isSubMenu && this.#targetElement) {
|
1185
|
-
this.#targetElement.ariaExpanded = 'true';
|
1186
|
-
}
|
1187
|
-
this.#defaultSlotElementRef.value.showPopover();
|
1188
|
-
}
|
1189
|
-
if (this.#optionsElement && this.#activeOption?.id) {
|
1190
|
-
this.#optionsElement.ariaActivedescendant =
|
1191
|
-
this.#activeOption.id;
|
1192
1236
|
}
|
1193
1237
|
});
|
1194
1238
|
}
|
package/dist/menu.styles.js
CHANGED
@@ -35,7 +35,6 @@ export default [
|
|
35
35
|
padding-block-end: 0;
|
36
36
|
padding-block-start: var(--glide-core-spacing-base-xxxs);
|
37
37
|
padding-inline: var(--glide-core-spacing-base-xxxs);
|
38
|
-
position: absolute;
|
39
38
|
|
40
39
|
/*
|
41
40
|
This little hack replaces "padding-block-end", which the last option overlaps
|
package/dist/modal.styles.js
CHANGED
@@ -35,7 +35,9 @@ export default [
|
|
35
35
|
);
|
36
36
|
border: none;
|
37
37
|
border-radius: var(--glide-core-rounding-base-radius-sm);
|
38
|
-
box-shadow: var(--glide-core-effect-floating)
|
38
|
+
box-shadow: 0 var(--glide-core-color-effect-position-elevation-floating-y)
|
39
|
+
var(--glide-core-color-effect-blur-elevation-floating-blur)
|
40
|
+
var(--glide-core-color-effect-color-elevation-dialog);
|
39
41
|
font-family: var(--glide-core-typography-family-primary);
|
40
42
|
opacity: 0;
|
41
43
|
padding: 0;
|
@@ -70,7 +72,9 @@ export default [
|
|
70
72
|
|
71
73
|
&::backdrop {
|
72
74
|
backdrop-filter: blur(3px);
|
73
|
-
background-color:
|
75
|
+
background-color: var(
|
76
|
+
--glide-core-private-color-dialog-and-modal-surface-overlay
|
77
|
+
);
|
74
78
|
|
75
79
|
@media (prefers-reduced-motion: no-preference) {
|
76
80
|
animation: backdrop-fade-in 250ms;
|
package/dist/popover.d.ts
CHANGED
@@ -8,13 +8,13 @@ declare global {
|
|
8
8
|
* @attr {boolean} [disabled=false]
|
9
9
|
* @attr {number} [offset=4]
|
10
10
|
* @attr {boolean} [open=false]
|
11
|
-
* @attr {'bottom'|'left'|'right'|'top'} [placement]
|
11
|
+
* @attr {'bottom'|'left'|'right'|'top'} [placement] - Popover will try to move itself to the opposite of this value if not doing so would result in overflow. For example, if "bottom" results in overflow Popover will try "top" but not "right" or "left".
|
12
12
|
*
|
13
13
|
* @readonly
|
14
14
|
* @attr {string} [version]
|
15
15
|
*
|
16
16
|
* @slot {Element | string} - The content of the popover
|
17
|
-
* @slot {Element} [target] - The element to which
|
17
|
+
* @slot {Element} [target] - The element to which Popover will anchor. Can be any focusable element.
|
18
18
|
*
|
19
19
|
* @fires {Event} toggle
|
20
20
|
*/
|
@@ -37,6 +37,10 @@ export default class Popover extends LitElement {
|
|
37
37
|
*/
|
38
38
|
get open(): boolean;
|
39
39
|
set open(isOpen: boolean);
|
40
|
+
/**
|
41
|
+
* Popover will try to move itself to the opposite of this value if not doing so would result in overflow.
|
42
|
+
* For example, if "bottom" results in overflow Popover will try "top" but not "right" or "left".
|
43
|
+
*/
|
40
44
|
placement?: 'bottom' | 'left' | 'right' | 'top';
|
41
45
|
readonly version: string;
|
42
46
|
connectedCallback(): void;
|
package/dist/popover.js
CHANGED
@@ -19,13 +19,13 @@ import final from './library/final.js';
|
|
19
19
|
* @attr {boolean} [disabled=false]
|
20
20
|
* @attr {number} [offset=4]
|
21
21
|
* @attr {boolean} [open=false]
|
22
|
-
* @attr {'bottom'|'left'|'right'|'top'} [placement]
|
22
|
+
* @attr {'bottom'|'left'|'right'|'top'} [placement] - Popover will try to move itself to the opposite of this value if not doing so would result in overflow. For example, if "bottom" results in overflow Popover will try "top" but not "right" or "left".
|
23
23
|
*
|
24
24
|
* @readonly
|
25
25
|
* @attr {string} [version]
|
26
26
|
*
|
27
27
|
* @slot {Element | string} - The content of the popover
|
28
|
-
* @slot {Element} [target] - The element to which
|
28
|
+
* @slot {Element} [target] - The element to which Popover will anchor. Can be any focusable element.
|
29
29
|
*
|
30
30
|
* @fires {Event} toggle
|
31
31
|
*/
|
@@ -36,19 +36,26 @@ let Popover = class Popover extends LitElement {
|
|
36
36
|
this.effectivePlacement = this.placement ?? 'bottom';
|
37
37
|
this.#arrowElementRef = createRef();
|
38
38
|
this.#defaultSlotElementRef = createRef();
|
39
|
+
// Set in `#onArrowClick()`. Used in `#onDocumentClick()` to guard against closing
|
40
|
+
// Popover when the user accidentally clicks the arrow.
|
39
41
|
this.#isArrowClick = false;
|
42
|
+
// Set in `#onDefaultSlotClick()`. Used in `#onDocumentClick()` to guard against
|
43
|
+
// closing Popover when the user interacts with its default slot.
|
40
44
|
this.#isDefaultSlotClick = false;
|
41
45
|
this.#isDisabled = false;
|
42
46
|
this.#isOpen = false;
|
47
|
+
// Set in `#onTargetSlotClick()`. Used in `#onDocumentClick()` to guard against
|
48
|
+
// immediately closing Popover when it's opened via `onTargetSlotClick()`.
|
43
49
|
this.#isTargetSlotClick = false;
|
44
50
|
this.#popoverElementRef = createRef();
|
45
51
|
this.#targetSlotElementRef = createRef();
|
46
52
|
// An arrow function field instead of a method so `this` is closed over and
|
47
53
|
// set to the component instead of `document`.
|
48
54
|
this.#onDocumentClick = () => {
|
49
|
-
// Checking that
|
50
|
-
//
|
51
|
-
//
|
55
|
+
// Checking that `event.target` is equal to `this.#defaultSlotElementRef.value`
|
56
|
+
// would be simpler. But, when the default slot is inside of another web component,
|
57
|
+
// `event.target` will be that component instead.
|
58
|
+
//
|
52
59
|
// Same for `this.#isTargetSlotClick` and `this.#isArrowClick`.
|
53
60
|
if (this.#isDefaultSlotClick ||
|
54
61
|
this.#isTargetSlotClick ||
|
@@ -122,65 +129,34 @@ let Popover = class Popover extends LitElement {
|
|
122
129
|
}
|
123
130
|
connectedCallback() {
|
124
131
|
super.connectedCallback();
|
125
|
-
|
126
|
-
// 2. The user clicks the button.
|
127
|
-
// 3. The button's click handler is called and it sets `this.open` to `true`.
|
128
|
-
// 4. The "click" event bubbles up and is handled by `#onDocumentClick`.
|
129
|
-
// 5. That handler sets `open` to `false` because the click came from outside
|
130
|
-
// Popover.
|
131
|
-
// 6. Popover is opened then closed in the same frame and so never opens.
|
132
|
-
//
|
133
|
-
// `capture` ensures `#onDocumentClick` is called before #3, so the button click
|
134
|
-
// handler setting `open` to `true` isn't overwritten by this handler setting
|
135
|
-
// `open` to `false`.
|
136
|
-
document.addEventListener('click', this.#onDocumentClick, {
|
137
|
-
capture: true,
|
138
|
-
});
|
132
|
+
document.addEventListener('click', this.#onDocumentClick);
|
139
133
|
}
|
140
134
|
firstUpdated() {
|
141
135
|
if (this.#popoverElementRef.value) {
|
142
|
-
// `popover`
|
143
|
-
//
|
144
|
-
//
|
136
|
+
// `popover` so Popover can break out of Modal or another element that has
|
137
|
+
// `overflow: hidden`. Elements with `popover` are positioned relative to the
|
138
|
+
// viewport. Thus Floating UI in addition to `popover` until anchor positioning is
|
139
|
+
// well supported.
|
145
140
|
//
|
146
|
-
//
|
147
|
-
// of `popover` and doesn't
|
141
|
+
// "manual" is set here instead of in the template to circumvent Lit Analyzer,
|
142
|
+
// which isn't aware of `popover` and doesn't provide a way to disable its
|
143
|
+
// "no-unknown-attribute" rule.
|
148
144
|
//
|
149
|
-
// "auto"
|
150
|
-
//
|
151
|
-
//
|
152
|
-
// "auto" also automatically opens the popover when its target is clicked. We want
|
153
|
-
// it to remain closed when clicked when there are no menu options.
|
145
|
+
// "manual" instead of "auto" because the latter only allows one popover to be open
|
146
|
+
// at a time. And consumers may have other popovers that need to remain open while
|
147
|
+
// this popover is open.
|
154
148
|
this.#popoverElementRef.value.popover = 'manual';
|
155
149
|
}
|
156
150
|
if (this.open && !this.disabled) {
|
157
151
|
this.#show();
|
158
152
|
}
|
159
|
-
// Popover's "click" handler on `document` listens for clicks in the capture
|
160
|
-
// phase. There's a comment explaining why. `#isDefaultSlotclick` must be
|
161
|
-
// set before that handler is called so it has the information it needs
|
162
|
-
// to determine whether or not to close Popover. Same for `#isTargetSlotClick`
|
163
|
-
// and `#isArrowClick`.
|
164
|
-
this.#defaultSlotElementRef.value?.addEventListener('mouseup', () => {
|
165
|
-
this.#isDefaultSlotClick = true;
|
166
|
-
});
|
167
|
-
this.#targetSlotElementRef.value?.addEventListener('mouseup', () => {
|
168
|
-
this.#isTargetSlotClick = true;
|
169
|
-
});
|
170
|
-
this.#arrowElementRef.value?.addEventListener('mouseup', () => {
|
171
|
-
this.#isArrowClick = true;
|
172
|
-
});
|
173
|
-
this.#targetSlotElementRef.value?.addEventListener('keydown', (event) => {
|
174
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
175
|
-
this.#isTargetSlotClick = true;
|
176
|
-
}
|
177
|
-
});
|
178
153
|
}
|
179
154
|
render() {
|
180
|
-
// Lit-a11y
|
181
|
-
//
|
182
|
-
//
|
183
|
-
//
|
155
|
+
// Lit-a11y also wants a keyboard listener on anything with a "click" listener. The
|
156
|
+
// "click" listeners on the arrow and default slot, however, are for a specific
|
157
|
+
// purpose that Lit-a11y isn't aware of.
|
158
|
+
//
|
159
|
+
/* eslint-disable lit-a11y/click-events-have-key-events */
|
184
160
|
return html `
|
185
161
|
<div class="component">
|
186
162
|
<slot
|
@@ -193,7 +169,7 @@ let Popover = class Popover extends LitElement {
|
|
193
169
|
${ref(this.#targetSlotElementRef)}
|
194
170
|
>
|
195
171
|
<!--
|
196
|
-
The element to which
|
172
|
+
The element to which Popover will anchor. Can be any focusable element.
|
197
173
|
@type {Element}
|
198
174
|
-->
|
199
175
|
</slot>
|
@@ -213,6 +189,7 @@ let Popover = class Popover extends LitElement {
|
|
213
189
|
[this.effectivePlacement]: true,
|
214
190
|
})}
|
215
191
|
data-test="arrow"
|
192
|
+
@click=${this.#onArrowClick}
|
216
193
|
${ref(this.#arrowElementRef)}
|
217
194
|
>
|
218
195
|
${choose(this.effectivePlacement, [
|
@@ -225,6 +202,7 @@ let Popover = class Popover extends LitElement {
|
|
225
202
|
|
226
203
|
<slot
|
227
204
|
class="default-slot"
|
205
|
+
@click=${this.#onDefaultSlotClick}
|
228
206
|
${assertSlot()}
|
229
207
|
${ref(this.#defaultSlotElementRef)}
|
230
208
|
>
|
@@ -240,10 +218,16 @@ let Popover = class Popover extends LitElement {
|
|
240
218
|
#arrowElementRef;
|
241
219
|
#cleanUpFloatingUi;
|
242
220
|
#defaultSlotElementRef;
|
221
|
+
// Set in `#onArrowClick()`. Used in `#onDocumentClick()` to guard against closing
|
222
|
+
// Popover when the user accidentally clicks the arrow.
|
243
223
|
#isArrowClick;
|
224
|
+
// Set in `#onDefaultSlotClick()`. Used in `#onDocumentClick()` to guard against
|
225
|
+
// closing Popover when the user interacts with its default slot.
|
244
226
|
#isDefaultSlotClick;
|
245
227
|
#isDisabled;
|
246
228
|
#isOpen;
|
229
|
+
// Set in `#onTargetSlotClick()`. Used in `#onDocumentClick()` to guard against
|
230
|
+
// immediately closing Popover when it's opened via `onTargetSlotClick()`.
|
247
231
|
#isTargetSlotClick;
|
248
232
|
#offset;
|
249
233
|
#popoverElementRef;
|
@@ -258,14 +242,31 @@ let Popover = class Popover extends LitElement {
|
|
258
242
|
}
|
259
243
|
this.#cleanUpFloatingUi?.();
|
260
244
|
}
|
261
|
-
#
|
262
|
-
this
|
245
|
+
#onArrowClick() {
|
246
|
+
this.#isArrowClick = true;
|
247
|
+
}
|
248
|
+
#onDefaultSlotClick() {
|
249
|
+
this.#isDefaultSlotClick = true;
|
250
|
+
}
|
251
|
+
#onTargetSlotClick(event) {
|
252
|
+
this.#isTargetSlotClick = true;
|
253
|
+
// The timeout gives consumers a chance to cancel the event to prevent Popover
|
254
|
+
// from opening or closing.
|
255
|
+
setTimeout(() => {
|
256
|
+
if (!event.defaultPrevented) {
|
257
|
+
this.open = !this.open;
|
258
|
+
}
|
259
|
+
});
|
263
260
|
}
|
264
261
|
#onTargetSlotKeydown(event) {
|
262
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
263
|
+
this.#isTargetSlotClick = true;
|
264
|
+
return;
|
265
|
+
}
|
265
266
|
if (event.key === 'Escape') {
|
266
|
-
// Prevent Safari from leaving full screen.
|
267
|
-
event.preventDefault();
|
267
|
+
event.preventDefault(); // Prevent Safari from leaving full screen.
|
268
268
|
this.open = false;
|
269
|
+
return;
|
269
270
|
}
|
270
271
|
}
|
271
272
|
get #targetElement() {
|
package/dist/slider.js
CHANGED
@@ -345,6 +345,7 @@ let Slider = class Slider extends LitElement {
|
|
345
345
|
// input elements directly or via the handles. Exposing the
|
346
346
|
// track via keyboard wouldn't bring any real value in this
|
347
347
|
// instance.
|
348
|
+
//
|
348
349
|
/* eslint-disable lit-a11y/click-events-have-key-events */
|
349
350
|
return html `
|
350
351
|
<glide-core-private-label
|
@@ -137,6 +137,7 @@
|
|
137
137
|
--glide-core-color-effect-color-elevation-raised-1: #0000000d;
|
138
138
|
--glide-core-color-effect-color-elevation-raised-2: #00000026;
|
139
139
|
--glide-core-color-effect-color-elevation-floating: #00000040;
|
140
|
+
--glide-core-color-effect-color-elevation-dialog: #00000040;
|
140
141
|
--glide-core-color-effect-color-elevation-detail-panel: #adadad;
|
141
142
|
--glide-core-color-effect-color-scroll-shadow: #0000001a;
|
142
143
|
--glide-core-color-effect-position-elevation-floating-y: 0.25rem;
|
@@ -149,6 +150,7 @@
|
|
149
150
|
--glide-core-private-color-checkbox-icon-default--disabled: #d9d9d9;
|
150
151
|
--glide-core-private-color-radio-icon-default--disabled: #d9d9d9;
|
151
152
|
--glide-core-private-color-dialog-and-modal-surface-container: #ffffff;
|
153
|
+
--glide-core-private-color-dialog-and-modal-surface-overlay: #0000008c;
|
152
154
|
--glide-core-private-color-skeleton-loader-surface-linear-gradient-sides: #0000000d;
|
153
155
|
--glide-core-private-color-skeleton-loader-surface-linear-gradient-middle: #0000001a;
|
154
156
|
--glide-core-private-color-slider-and-scrollbar-surface-handle: #f0f0f0;
|
@@ -296,6 +298,7 @@
|
|
296
298
|
--glide-core-color-effect-color-elevation-raised-1: #ffffff00;
|
297
299
|
--glide-core-color-effect-color-elevation-raised-2: #ffffff00;
|
298
300
|
--glide-core-color-effect-color-elevation-floating: #14141459;
|
301
|
+
--glide-core-color-effect-color-elevation-dialog: #000000f2;
|
299
302
|
--glide-core-color-effect-color-elevation-detail-panel: #000000f2;
|
300
303
|
--glide-core-color-effect-color-scroll-shadow: #ffffff0d;
|
301
304
|
--glide-core-color-effect-position-elevation-floating-y: 0.75rem;
|
@@ -308,6 +311,7 @@
|
|
308
311
|
--glide-core-private-color-checkbox-icon-default--disabled: #434343;
|
309
312
|
--glide-core-private-color-radio-icon-default--disabled: #434343;
|
310
313
|
--glide-core-private-color-dialog-and-modal-surface-container: #292929;
|
314
|
+
--glide-core-private-color-dialog-and-modal-surface-overlay: #141414d9;
|
311
315
|
--glide-core-private-color-skeleton-loader-surface-linear-gradient-sides: #ffffff0d;
|
312
316
|
--glide-core-private-color-skeleton-loader-surface-linear-gradient-middle: #ffffff1a;
|
313
317
|
--glide-core-private-color-slider-and-scrollbar-surface-handle: #2c2c2c;
|
package/dist/textarea.styles.js
CHANGED
@@ -58,7 +58,11 @@ export default [
|
|
58
58
|
padding: var(--glide-core-spacing-base-xs)
|
59
59
|
var(--glide-core-spacing-base-sm);
|
60
60
|
resize: vertical;
|
61
|
-
transition:
|
61
|
+
transition:
|
62
|
+
border-color var(--glide-core-duration-moderate-02)
|
63
|
+
var(--glide-core-animation-swoop),
|
64
|
+
box-shadow var(--glide-core-duration-moderate-02)
|
65
|
+
var(--glide-core-animation-swoop);
|
62
66
|
|
63
67
|
/*
|
64
68
|
Because 'field-sizing: content' is used, it allows the
|
@@ -81,7 +85,22 @@ export default [
|
|
81
85
|
outline: none;
|
82
86
|
}
|
83
87
|
|
84
|
-
&:focus-visible
|
88
|
+
&:focus-visible:not([readonly]) {
|
89
|
+
&:not(.error) {
|
90
|
+
border-color: var(--glide-core-color-interactive-stroke-focus);
|
91
|
+
box-shadow:
|
92
|
+
0 0 0 1px var(--glide-core-color-interactive-stroke-focus),
|
93
|
+
1px 1px 4px -1px var(--glide-core-color-interactive-stroke-focus);
|
94
|
+
}
|
95
|
+
|
96
|
+
&.error {
|
97
|
+
box-shadow:
|
98
|
+
0 0 0 1px var(--glide-core-color-advisory-stroke-error-primary),
|
99
|
+
1px 1px 4px -1px
|
100
|
+
var(--glide-core-color-advisory-stroke-error-primary);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
85
104
|
&:hover {
|
86
105
|
border-color: var(--glide-core-color-interactive-stroke-primary--hover);
|
87
106
|
}
|
package/dist/tooltip.d.ts
CHANGED
@@ -11,7 +11,7 @@ declare global {
|
|
11
11
|
* @attr {boolean} [disabled=false]
|
12
12
|
* @attr {number} [offset=4]
|
13
13
|
* @attr {boolean} [open=false]
|
14
|
-
* @attr {'bottom'|'left'|'right'|'top'} [placement] -
|
14
|
+
* @attr {'bottom'|'left'|'right'|'top'} [placement] - Tooltip will try to move itself to the opposite of this value if not doing so would result in overflow. For example, if "bottom" results in overflow Tooltip will try "top" but not "right" or "left".
|
15
15
|
* @attr {boolean} [screenreader-hidden=false]
|
16
16
|
* @attr {string[]} [shortcut=[]]
|
17
17
|
*
|
@@ -19,7 +19,7 @@ declare global {
|
|
19
19
|
* @attr {string} [version]
|
20
20
|
*
|
21
21
|
* @slot {TooltipContainer} [private]
|
22
|
-
* @slot {Element} target - The element to which
|
22
|
+
* @slot {Element} target - The element to which Tooltip will anchor. Can be any interactive element with an implicit or explicit ARIA role.
|
23
23
|
*
|
24
24
|
* @fires {Event} toggle
|
25
25
|
*/
|
@@ -56,8 +56,8 @@ export default class Tooltip extends LitElement {
|
|
56
56
|
*/
|
57
57
|
set open(isOpen: boolean);
|
58
58
|
/**
|
59
|
-
*
|
60
|
-
*
|
59
|
+
* Tooltip will try to move itself to the opposite of this value if not doing so would result in overflow.
|
60
|
+
* For example, if "bottom" results in overflow Tooltip will try "top" but not "right" or "left".
|
61
61
|
*/
|
62
62
|
placement?: 'bottom' | 'left' | 'right' | 'top';
|
63
63
|
/**
|
package/dist/tooltip.js
CHANGED
@@ -23,7 +23,7 @@ import required from './library/required.js';
|
|
23
23
|
* @attr {boolean} [disabled=false]
|
24
24
|
* @attr {number} [offset=4]
|
25
25
|
* @attr {boolean} [open=false]
|
26
|
-
* @attr {'bottom'|'left'|'right'|'top'} [placement] -
|
26
|
+
* @attr {'bottom'|'left'|'right'|'top'} [placement] - Tooltip will try to move itself to the opposite of this value if not doing so would result in overflow. For example, if "bottom" results in overflow Tooltip will try "top" but not "right" or "left".
|
27
27
|
* @attr {boolean} [screenreader-hidden=false]
|
28
28
|
* @attr {string[]} [shortcut=[]]
|
29
29
|
*
|
@@ -31,7 +31,7 @@ import required from './library/required.js';
|
|
31
31
|
* @attr {string} [version]
|
32
32
|
*
|
33
33
|
* @slot {TooltipContainer} [private]
|
34
|
-
* @slot {Element} target - The element to which
|
34
|
+
* @slot {Element} target - The element to which Tooltip will anchor. Can be any interactive element with an implicit or explicit ARIA role.
|
35
35
|
*
|
36
36
|
* @fires {Event} toggle
|
37
37
|
*/
|
@@ -179,18 +179,18 @@ let Tooltip = class Tooltip extends LitElement {
|
|
179
179
|
}
|
180
180
|
firstUpdated() {
|
181
181
|
if (this.#tooltipElementRef.value) {
|
182
|
-
// `popover`
|
183
|
-
//
|
184
|
-
//
|
182
|
+
// `popover` so Tooltip can break out of Modal or another element that has
|
183
|
+
// `overflow: hidden`. Elements with `popover` are positioned relative to the
|
184
|
+
// viewport. Thus Floating UI in addition to `popover` until anchor positioning is
|
185
|
+
// well supported.
|
185
186
|
//
|
186
|
-
//
|
187
|
-
// of `popover` and doesn't
|
187
|
+
// "manual" is set here instead of in the template to circumvent Lit Analyzer,
|
188
|
+
// which isn't aware of `popover` and doesn't provide a way to disable its
|
189
|
+
// "no-unknown-attribute" rule.
|
188
190
|
//
|
189
|
-
// "auto"
|
190
|
-
//
|
191
|
-
//
|
192
|
-
// "auto" also automatically opens the popover when its target is clicked. We
|
193
|
-
// only want it to open on hover or focus.
|
191
|
+
// "manual" instead of "auto" because the latter only allows one popover to be open
|
192
|
+
// at a time. And consumers may have other popovers that need to remain open while
|
193
|
+
// this popover is open.
|
194
194
|
this.#tooltipElementRef.value.popover = 'manual';
|
195
195
|
}
|
196
196
|
if (this.open && !this.disabled) {
|
@@ -229,8 +229,8 @@ let Tooltip = class Tooltip extends LitElement {
|
|
229
229
|
${ref(this.#targetSlotElementRef)}
|
230
230
|
>
|
231
231
|
<!--
|
232
|
-
The element to which
|
233
|
-
Can be any element with an implicit or explicit ARIA role.
|
232
|
+
The element to which Tooltip will anchor.
|
233
|
+
Can be any interactive element with an implicit or explicit ARIA role.
|
234
234
|
|
235
235
|
@required
|
236
236
|
@type {Element}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@crowdstrike/glide-core",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.32.1",
|
4
4
|
"description": "A Web Component design system",
|
5
5
|
"author": "CrowdStrike UX Team",
|
6
6
|
"license": "Apache-2.0",
|
@@ -29,6 +29,7 @@
|
|
29
29
|
"!dist/eslint",
|
30
30
|
"!dist/figma",
|
31
31
|
"!dist/icons/storybook.*",
|
32
|
+
"!dist/playwright",
|
32
33
|
"!dist/storybook",
|
33
34
|
"!dist/stylelint",
|
34
35
|
"!dist/ts-morph"
|
@@ -58,6 +59,7 @@
|
|
58
59
|
"lit": "^3.2.1"
|
59
60
|
},
|
60
61
|
"devDependencies": {
|
62
|
+
"@axe-core/playwright": "^4.10.2",
|
61
63
|
"@changesets/changelog-github": "^0.5.0",
|
62
64
|
"@changesets/cli": "^2.27.10",
|
63
65
|
"@custom-elements-manifest/analyzer": "^0.10.4",
|
@@ -65,21 +67,28 @@
|
|
65
67
|
"@eslint/js": "^9.28.0",
|
66
68
|
"@figma/rest-api-spec": "^0.32.0",
|
67
69
|
"@html-eslint/eslint-plugin": "^0.41.0",
|
70
|
+
"@jridgewell/trace-mapping": "^0.3.29",
|
71
|
+
"@lit-labs/ssr": "^3.3.1",
|
68
72
|
"@open-wc/testing": "^4.0.0",
|
69
|
-
"@playwright/test": "^1.
|
73
|
+
"@playwright/test": "^1.54.2",
|
70
74
|
"@rollup/plugin-commonjs": "^28.0.2",
|
71
|
-
"@storybook/addon-actions": "^8.6.
|
72
|
-
"@storybook/addon-controls": "^8.6.
|
73
|
-
"@storybook/addon-docs": "^8.6.
|
74
|
-
"@storybook/addon-toolbars": "^8.6.
|
75
|
-
"@storybook/core-events": "^8.6.
|
76
|
-
"@storybook/manager-api": "^8.6.
|
77
|
-
"@storybook/preview-api": "^8.6.
|
78
|
-
"@storybook/theming": "^8.6.
|
79
|
-
"@storybook/
|
80
|
-
"@storybook/web-components
|
75
|
+
"@storybook/addon-actions": "^8.6.14",
|
76
|
+
"@storybook/addon-controls": "^8.6.14",
|
77
|
+
"@storybook/addon-docs": "^8.6.14",
|
78
|
+
"@storybook/addon-toolbars": "^8.6.14",
|
79
|
+
"@storybook/core-events": "^8.6.14",
|
80
|
+
"@storybook/manager-api": "^8.6.14",
|
81
|
+
"@storybook/preview-api": "^8.6.14",
|
82
|
+
"@storybook/theming": "^8.6.14",
|
83
|
+
"@storybook/types": "^8.6.14",
|
84
|
+
"@storybook/web-components": "^8.6.14",
|
85
|
+
"@storybook/web-components-vite": "^8.6.14",
|
81
86
|
"@stylistic/eslint-plugin": "^2.13.0",
|
87
|
+
"@types/convert-source-map": "^2.0.3",
|
82
88
|
"@types/eslint": "^8.56.12",
|
89
|
+
"@types/istanbul-lib-coverage": "^2.0.6",
|
90
|
+
"@types/istanbul-lib-report": "^3.0.3",
|
91
|
+
"@types/istanbul-reports": "^3.0.4",
|
83
92
|
"@types/mocha": "^10.0.10",
|
84
93
|
"@types/sinon": "^17.0.3",
|
85
94
|
"@typescript-eslint/rule-tester": "^8.33.0",
|
@@ -92,6 +101,7 @@
|
|
92
101
|
"@web/test-runner-playwright": "^0.11.0",
|
93
102
|
"chokidar-cli": "^3.0.0",
|
94
103
|
"comment-parser": "^1.4.1",
|
104
|
+
"convert-source-map": "^2.0.0",
|
95
105
|
"custom-elements-manifest": "^2.1.0",
|
96
106
|
"esbuild": "^0.25.0",
|
97
107
|
"eslint": "^9.31.0",
|
@@ -99,20 +109,26 @@
|
|
99
109
|
"eslint-plugin-import": "^2.31.0",
|
100
110
|
"eslint-plugin-lit": "^1.15.0",
|
101
111
|
"eslint-plugin-lit-a11y": "^4.1.4",
|
112
|
+
"eslint-plugin-playwright": "^2.2.2",
|
102
113
|
"eslint-plugin-sort-class-members": "^1.21.0",
|
103
114
|
"eslint-plugin-unicorn": "^60.0.0",
|
104
115
|
"globals": "^15.13.0",
|
105
116
|
"globby": "^14.0.2",
|
117
|
+
"http-server": "^14.1.1",
|
106
118
|
"husky": "^8.0.3",
|
107
119
|
"is-ci": "^4.1.0",
|
120
|
+
"istanbul-lib-coverage": "^3.2.2",
|
121
|
+
"istanbul-lib-report": "^3.0.1",
|
122
|
+
"istanbul-reports": "^3.1.7",
|
108
123
|
"lint-staged": "^15.2.11",
|
109
124
|
"lit": "^3.3.0",
|
110
125
|
"lit-analyzer": "^2.0.3",
|
126
|
+
"matcher": "^5.0.0",
|
111
127
|
"minify-literals": "^1.0.10",
|
112
128
|
"node-html-parser": "^7.0.1",
|
113
129
|
"npm-run-all2": "^7.0.2",
|
114
130
|
"per-env": "^1.0.2",
|
115
|
-
"playwright": "^1.
|
131
|
+
"playwright": "^1.54.2",
|
116
132
|
"postcss": "^8.5.6",
|
117
133
|
"postcss-lit": "^1.2.0",
|
118
134
|
"prettier": "^3.5.3",
|
@@ -120,10 +136,10 @@
|
|
120
136
|
"react-dom": "^19.1.0",
|
121
137
|
"rimraf": "^6.0.1",
|
122
138
|
"sinon": "^19.0.2",
|
123
|
-
"storybook": "^8.6.
|
139
|
+
"storybook": "^8.6.14",
|
124
140
|
"stylelint": "^16.21.1",
|
125
141
|
"stylelint-config-standard": "^36.0.1",
|
126
|
-
"stylelint-order": "^
|
142
|
+
"stylelint-order": "^7.0.0",
|
127
143
|
"stylelint-prettier": "^5.0.2",
|
128
144
|
"stylelint-use-logical": "^2.1.2",
|
129
145
|
"stylelint-use-nesting": "^6.0.0",
|
@@ -132,8 +148,8 @@
|
|
132
148
|
"tsx": "^4.19.2",
|
133
149
|
"typescript": "^5.8.3",
|
134
150
|
"typescript-eslint": "^8.33.0",
|
151
|
+
"v8-to-istanbul": "^9.3.0",
|
135
152
|
"vite": "^6.3.2",
|
136
|
-
"vitest": "^3.0.8",
|
137
153
|
"yocto-spinner": "^0.2.0"
|
138
154
|
},
|
139
155
|
"engines": {
|
@@ -150,7 +166,7 @@
|
|
150
166
|
"start:development:ts-morph:comment:tsx": "Remove `tsx` once Node.js type stripping is available.",
|
151
167
|
"start:production": "rimraf ./dist && pnpm start:production:cem-analyze && pnpm start:production:ts-morph && npm-run-all --aggregate-output --print-label --parallel start:production:typescript start:production:storybook start:production:esbuild",
|
152
168
|
"start:production:esbuild": "node ./esbuild.js",
|
153
|
-
"start:production:cem-analyze": "tsc --noCheck --outDir ./dist && NODE_OPTIONS=--no-warnings=ExperimentalWarning cem analyze --config ./custom-elements.config.js --quiet && git diff --quiet
|
169
|
+
"start:production:cem-analyze": "tsc --noCheck --outDir ./dist && NODE_OPTIONS=--no-warnings=ExperimentalWarning cem analyze --config ./custom-elements.config.js --quiet && git diff --quiet ./custom-elements.json || { echo ERROR: Uncommitted elements manifest changes. Run this command locally and commit the changes.; exit 1; }",
|
154
170
|
"start:production:figma:dev-resources": "tsx ./src/figma/dev-resources/run.ts",
|
155
171
|
"start:production:figma:variables": "tsx ./src/figma/variables/run.ts",
|
156
172
|
"start:production:storybook": "storybook build --config-dir .storybook --disable-telemetry --output-dir ./dist/storybook",
|
@@ -170,22 +186,19 @@
|
|
170
186
|
"lint:production:stylelint": "tsc --noCheck --outDir ./dist && stylelint '**/*.styles.ts' --custom-syntax postcss-lit --no-color",
|
171
187
|
"test": "per-env",
|
172
188
|
"test:development": "pnpm test:development:web-test-runner",
|
173
|
-
"test:development:playwright": "playwright test
|
174
|
-
"test:development:playwright:
|
175
|
-
"test:development:
|
176
|
-
"test:development:
|
189
|
+
"test:development:playwright": "npm-run-all --parallel test:development:playwright:coverage test:development:playwright:ui",
|
190
|
+
"test:development:playwright:coverage": "http-server ./dist/playwright/coverage-report --port 6008 --silent",
|
191
|
+
"test:development:playwright:ui": "playwright test --config ./src/playwright/playwright.config.ts --ui-port 6007 --update-snapshots --update-source-method=overwrite",
|
192
|
+
"test:development:playwright:update": "PLAYWRIGHT_SKIP_COVERAGE=true playwright test --config ./src/playwright/playwright.config.ts --quiet --project accessibility --update-snapshots --update-source-method=overwrite --workers 100%",
|
177
193
|
"test:development:web-test-runner": "web-test-runner --watch",
|
178
194
|
"test:production": "pnpm start:production:esbuild && npm-run-all --aggregate-output --print-label --parallel test:production:*",
|
179
|
-
"test:production:playwright
|
180
|
-
"test:production:playwright:
|
181
|
-
"test:production:playwright:visuals:comment": "Snapshots are ignored because this is meant to be only a quick smoke test telling us when we've written a test incorrectly.",
|
182
|
-
"test:production:vitest": "tsc --noCheck --outDir ./dist && vitest run --config ./vitest.config.js",
|
195
|
+
"test:production:playwright": "playwright test --config ./src/playwright/playwright.config.ts --grep 'is accessible|@eslint|@events|@forms|@keyboard|@miscellaneous|@mouse|@stylelint'",
|
196
|
+
"test:production:playwright:comment": "Used locally by developers and as a pre-push hook. Running every '@accessibility' test would take too long. So we only run the 'is accessible' test, which in many cases completes code coverage.",
|
183
197
|
"test:production:web-test-runner": "web-test-runner",
|
184
198
|
"typecheck": "per-env",
|
185
199
|
"typecheck:development": "tsc --erasableSyntaxOnly --outDir ./dist -w",
|
186
200
|
"typecheck:production": "tsc --erasableSyntaxOnly --outDir ./dist",
|
187
|
-
"postinstall": "is-ci || pnpm dlx playwright@1.
|
188
|
-
"postinstall:comment": "Not installing Chromium in CI every time we run `pnpm install` speeds up builds at the cost of having to also update Playwright's version in our workflows whenever we update Playwright here.",
|
201
|
+
"postinstall": "is-ci || pnpm dlx playwright@1.54.2 install --no-shell --with-deps chromium firefox webkit",
|
189
202
|
"release": "changeset publish"
|
190
203
|
}
|
191
204
|
}
|