@crowdstrike/glide-core 0.7.0 → 0.9.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/README.md +44 -5
- package/dist/accordion.test.basics.js +1 -0
- package/dist/accordion.test.events.js +1 -0
- package/dist/button-group.button.d.ts +14 -15
- package/dist/button-group.button.js +1 -1
- package/dist/button-group.button.styles.js +75 -52
- package/dist/button-group.button.test.basics.d.ts +1 -1
- package/dist/button-group.button.test.basics.js +84 -147
- package/dist/button-group.button.test.events.js +9 -67
- package/dist/button-group.button.test.focus.js +13 -0
- package/dist/button-group.button.test.interactions.d.ts +1 -0
- package/dist/button-group.button.test.interactions.js +42 -0
- package/dist/button-group.d.ts +7 -10
- package/dist/button-group.js +1 -1
- package/dist/button-group.stories.d.ts +1 -5
- package/dist/button-group.styles.js +18 -6
- package/dist/button-group.test.basics.js +114 -234
- package/dist/button-group.test.events.js +211 -263
- package/dist/button-group.test.focus.d.ts +1 -0
- package/dist/button-group.test.focus.js +39 -0
- package/dist/button-group.test.interactions.d.ts +1 -0
- package/dist/button-group.test.interactions.js +91 -0
- package/dist/button.test.basics.js +2 -1
- package/dist/button.test.events.js +1 -0
- package/dist/button.test.form.js +1 -0
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.styles.js +1 -1
- package/dist/checkbox-group.test.basics.js +2 -1
- package/dist/checkbox-group.test.events.js +5 -4
- package/dist/checkbox-group.test.focus.js +5 -3
- package/dist/checkbox-group.test.form.js +1 -0
- package/dist/checkbox-group.test.validity.js +1 -0
- package/dist/checkbox.d.ts +7 -1
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.styles.js +11 -3
- package/dist/checkbox.test.basics.js +1 -0
- package/dist/checkbox.test.events.js +5 -4
- package/dist/checkbox.test.focus.js +2 -2
- package/dist/checkbox.test.form.js +1 -0
- package/dist/{checkbox.test.states.js → checkbox.test.interactions.js} +25 -1
- package/dist/checkbox.test.validity.js +1 -0
- package/dist/drawer.js +1 -1
- package/dist/drawer.test.basics.js +1 -0
- package/dist/drawer.test.closing.js +1 -0
- package/dist/drawer.test.events.js +1 -0
- package/dist/drawer.test.methods.js +1 -0
- package/dist/dropdown.d.ts +6 -4
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.d.ts +7 -2
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.styles.js +13 -0
- package/dist/dropdown.option.test.basics.js +7 -3
- package/dist/dropdown.option.test.basics.multiple.js +1 -0
- package/dist/dropdown.option.test.basics.single.js +1 -0
- package/dist/dropdown.option.test.events.js +2 -1
- package/dist/dropdown.option.test.focus.js +1 -1
- package/dist/dropdown.option.test.interactions.multiple.js +2 -54
- package/dist/dropdown.option.test.interactions.single.js +52 -9
- package/dist/dropdown.styles.js +20 -19
- package/dist/dropdown.test.basics.filterable.js +1 -0
- package/dist/dropdown.test.basics.js +144 -2
- package/dist/dropdown.test.basics.multiple.js +6 -3
- package/dist/dropdown.test.basics.single.js +1 -1
- package/dist/dropdown.test.events.filterable.js +74 -0
- package/dist/dropdown.test.events.js +50 -160
- package/dist/dropdown.test.events.multiple.js +268 -10
- package/dist/dropdown.test.events.single.js +202 -4
- package/dist/dropdown.test.focus.filterable.js +9 -5
- package/dist/dropdown.test.focus.js +2 -1
- package/dist/dropdown.test.focus.multiple.js +1 -2
- package/dist/dropdown.test.focus.single.js +1 -1
- package/dist/dropdown.test.form.js +1 -0
- package/dist/dropdown.test.form.multiple.js +1 -0
- package/dist/dropdown.test.form.single.js +1 -0
- package/dist/dropdown.test.interactions.filterable.js +69 -11
- package/dist/dropdown.test.interactions.js +95 -5
- package/dist/dropdown.test.interactions.multiple.js +203 -6
- package/dist/dropdown.test.interactions.single.js +69 -6
- package/dist/dropdown.test.validity.js +1 -0
- package/dist/form-controls-layout.test.basics.js +2 -1
- package/dist/icon-button.test.basics.js +2 -1
- package/dist/icons/checked.d.ts +1 -1
- package/dist/icons/checked.js +1 -1
- package/dist/icons/magnifying-glass.js +1 -1
- package/dist/input.d.ts +0 -6
- package/dist/input.js +1 -1
- package/dist/input.styles.js +7 -2
- package/dist/input.test.basics.js +20 -5
- package/dist/input.test.events.js +5 -4
- package/dist/input.test.focus.js +5 -4
- package/dist/input.test.form.js +1 -0
- package/dist/input.test.translations.d.ts +1 -0
- package/dist/input.test.translations.js +38 -0
- package/dist/input.test.validity.js +134 -4
- package/dist/label.d.ts +1 -1
- package/dist/label.js +1 -1
- package/dist/label.styles.js +29 -20
- package/dist/label.test.basics.js +27 -24
- package/dist/library/expect-argument-error.js +1 -1
- package/dist/library/localize.d.ts +5 -1
- package/dist/library/ow.test.d.ts +2 -1
- package/dist/library/ow.test.js +8 -3
- package/dist/menu.button.test.basics.js +1 -0
- package/dist/menu.d.ts +3 -5
- package/dist/menu.js +1 -1
- package/dist/menu.link.test.basics.js +1 -0
- package/dist/menu.options.test.basics.js +3 -2
- package/dist/menu.styles.js +1 -15
- package/dist/menu.test.basics.d.ts +1 -2
- package/dist/menu.test.basics.js +23 -6
- package/dist/menu.test.events.d.ts +1 -0
- package/dist/menu.test.events.js +2 -1
- package/dist/menu.test.focus.d.ts +1 -0
- package/dist/menu.test.focus.js +14 -6
- package/dist/menu.test.interactions.js +213 -56
- package/dist/modal.icon-button.test.basics.js +2 -1
- package/dist/modal.js +1 -1
- package/dist/modal.styles.js +18 -13
- package/dist/modal.tertiary-icon.d.ts +0 -1
- package/dist/modal.tertiary-icon.js +1 -1
- package/dist/modal.tertiary-icon.test.basics.js +2 -1
- package/dist/modal.test.accessibility.js +1 -0
- package/dist/modal.test.basics.js +2 -1
- package/dist/modal.test.close.js +1 -0
- package/dist/modal.test.events.js +11 -10
- package/dist/modal.test.lock-scroll.js +1 -0
- package/dist/modal.test.methods.js +1 -0
- package/dist/modal.test.scrollbars.js +1 -0
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.styles.js +1 -1
- package/dist/radio-group.test.basics.js +1 -0
- package/dist/radio-group.test.events.js +1 -0
- package/dist/radio-group.test.focus.js +4 -3
- package/dist/radio-group.test.form.js +1 -0
- package/dist/radio-group.test.validity.js +1 -0
- package/dist/radio.d.ts +1 -0
- package/dist/radio.js +1 -1
- package/dist/radio.styles.js +33 -0
- package/dist/split-button.test.basics.js +1 -0
- package/dist/split-container.test.basics.js +5 -0
- package/dist/split-link.test.basics.js +1 -0
- package/dist/split-link.test.interactions.js +2 -1
- package/dist/styles/variables.css +1 -1
- package/dist/tab.d.ts +1 -3
- package/dist/tab.group.d.ts +3 -5
- package/dist/tab.group.js +1 -1
- package/dist/tab.group.styles.js +27 -13
- package/dist/tab.group.test.basics.js +8 -57
- package/dist/tab.group.test.interactions.d.ts +3 -0
- package/dist/tab.group.test.interactions.js +454 -0
- package/dist/tab.js +1 -1
- package/dist/tab.panel.d.ts +1 -0
- package/dist/tab.panel.js +1 -1
- package/dist/tab.panel.styles.js +11 -1
- package/dist/tab.styles.js +7 -68
- package/dist/tab.test.basics.js +0 -20
- package/dist/tabs.stories.d.ts +1 -2
- package/dist/tag.test.basics.js +3 -2
- package/dist/textarea.d.ts +0 -1
- package/dist/textarea.js +2 -2
- package/dist/textarea.stories.d.ts +3 -4
- package/dist/textarea.styles.js +14 -3
- package/dist/textarea.test.basics.js +81 -44
- package/dist/textarea.test.events.js +57 -41
- package/dist/textarea.test.form.js +1 -0
- package/dist/textarea.test.translations.d.ts +1 -0
- package/dist/textarea.test.translations.js +34 -0
- package/dist/textarea.test.validity.js +105 -20
- package/dist/toasts.js +1 -1
- package/dist/toasts.styles.js +8 -1
- package/dist/toasts.test.basics.js +20 -0
- package/dist/toggle.js +1 -1
- package/dist/toggle.test.basics.js +1 -0
- package/dist/toggle.test.events.js +1 -0
- package/dist/toggle.test.focus.js +1 -1
- package/dist/toggle.test.interactions.d.ts +1 -0
- package/dist/{toggle.test.states.js → toggle.test.interactions.js} +1 -0
- package/dist/tooltip.d.ts +7 -5
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +90 -25
- package/dist/tooltip.test.basics.js +39 -3
- package/dist/tooltip.test.interactions.js +137 -34
- package/dist/translations/en.js +1 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/ja.js +1 -1
- package/dist/tree.d.ts +0 -1
- package/dist/tree.item.d.ts +2 -3
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +0 -1
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.test.basics.js +1 -0
- package/dist/tree.js +1 -1
- package/dist/tree.test.basics.js +2 -1
- package/dist/tree.test.events.js +1 -1
- package/package.json +40 -29
- package/dist/drawer.test.floating-components.d.ts +0 -1
- package/dist/drawer.test.floating-components.js +0 -51
- package/dist/library/set-containing-block.d.ts +0 -15
- package/dist/library/set-containing-block.js +0 -1
- package/dist/modal.test.floating-components.js +0 -62
- /package/dist/{checkbox.test.states.d.ts → button-group.button.test.focus.d.ts} +0 -0
- /package/dist/{modal.test.floating-components.d.ts → checkbox.test.interactions.d.ts} +0 -0
- /package/dist/{toggle.test.states.d.ts → dropdown.test.events.filterable.d.ts} +0 -0
package/README.md
CHANGED
@@ -1,13 +1,21 @@
|
|
1
|
-
|
1
|
+
<p align="center">
|
2
|
+
<a href="https://glide-core.crowdstrike-ux.workers.dev">
|
3
|
+
<img src="https://github.com/CrowdStrike/glide-core/blob/main/.github/glide-core.png?raw=true" alt="Glide Core logo" width="300" />
|
4
|
+
</a>
|
5
|
+
</p>
|
6
|
+
|
7
|
+
<h1 align="center">The Glide Design System from CrowdStrike</h1>
|
8
|
+
|
9
|
+
<br>
|
2
10
|
|
3
11
|
This package contains Web Components built with [Lit](https://lit.dev/).
|
4
12
|
|
5
|
-
##
|
13
|
+
## Usage
|
6
14
|
|
7
|
-
### 1. Add Lit as
|
15
|
+
### 1. Add this package and Lit as dependencies
|
8
16
|
|
9
17
|
```bash
|
10
|
-
pnpm
|
18
|
+
pnpm install @crowdstrike/glide-core lit
|
11
19
|
```
|
12
20
|
|
13
21
|
### 2. Import the fonts and variables
|
@@ -29,7 +37,38 @@ import '@crowdstrike/glide-core/button.js';
|
|
29
37
|
<glide-core-button size="small">Button</glide-core-button>
|
30
38
|
```
|
31
39
|
|
32
|
-
##
|
40
|
+
## Development
|
41
|
+
|
42
|
+
### Contributing
|
43
|
+
|
44
|
+
Follow our [Contribution Guidelines](./CONTRIBUTING.md).
|
45
|
+
|
46
|
+
### Getting started
|
47
|
+
|
48
|
+
First you'll need to install the dependencies for the repository. We use [PNPM](https://pnpm.io). Run the following command from the root of the repository:
|
49
|
+
|
50
|
+
```bash
|
51
|
+
pnpm install
|
52
|
+
pnpm dlx playwright install
|
53
|
+
```
|
54
|
+
|
55
|
+
> [!NOTE]
|
56
|
+
>
|
57
|
+
> - If you have `ignore-scripts=true` in your `~/.npmrc`, you'll also need to run `pnpm prepare`, which will install some Git hooks for linting, formatting, typechecking, and testing.
|
58
|
+
> - We recommend using [Corepack](https://pnpm.io/installation#using-corepack) to help manage the version of `pnpm` installed in this repository; however, it is not a requirement.
|
59
|
+
|
60
|
+
### Running Storybook
|
61
|
+
|
62
|
+
Run the following command from the root of the repository:
|
63
|
+
|
64
|
+
```bash
|
65
|
+
pnpm start
|
66
|
+
```
|
67
|
+
|
68
|
+
After Storybook's build completes, your browser should navigate to the Storybook instance.
|
69
|
+
If this doesn't happen automatically, a URL will be shown in your terminal for you to browse to.
|
70
|
+
|
71
|
+
### Adding CSS Custom Properties
|
33
72
|
|
34
73
|
Glide Core uses scripts from [@crowdstrike/design-tokens](https://www.npmjs.com/package/@crowdstrike/design-tokens) to import variables from Figma and transform them into CSS custom properties.
|
35
74
|
This allows us to maintain a single source of truth for color, typography, spacing, etc.
|
@@ -1,33 +1,32 @@
|
|
1
|
-
import { LitElement
|
2
|
-
import type { ButtonGroupVariant } from './button-group.js';
|
1
|
+
import { LitElement } from 'lit';
|
3
2
|
declare global {
|
4
3
|
interface HTMLElementTagNameMap {
|
5
4
|
'glide-core-button-group-button': GlideCoreButtonGroupButton;
|
6
5
|
}
|
7
6
|
}
|
8
7
|
/**
|
9
|
-
* @description A button for use
|
8
|
+
* @description A button with a label and optional icon for use in a `<glide-core-button-group>`.
|
10
9
|
*
|
11
|
-
* @event change - Dispatched when
|
12
|
-
* @event input - Dispatched when
|
10
|
+
* @event change - Dispatched when the button is selected.
|
11
|
+
* @event input - Dispatched when the button is selected.
|
13
12
|
|
14
|
-
* @slot prefix -
|
15
|
-
* @slot -
|
13
|
+
* @slot prefix - An icon.
|
14
|
+
* @slot - A label.
|
16
15
|
*/
|
17
16
|
export default class GlideCoreButtonGroupButton extends LitElement {
|
18
17
|
#private;
|
19
18
|
static shadowRootOptions: ShadowRootInit;
|
20
19
|
static styles: import("lit").CSSResult[];
|
21
|
-
|
20
|
+
label?: string | undefined;
|
21
|
+
get selected(): boolean;
|
22
|
+
set selected(isSelected: boolean);
|
22
23
|
disabled: boolean;
|
23
|
-
value
|
24
|
-
|
25
|
-
|
24
|
+
value?: string | undefined;
|
25
|
+
privateOrientation: 'horizontal' | 'vertical';
|
26
|
+
privateVariant?: 'icon-only';
|
27
|
+
click(): void;
|
26
28
|
firstUpdated(): void;
|
27
29
|
focus(options?: FocusOptions): void;
|
28
30
|
render(): import("lit").TemplateResult<1>;
|
29
|
-
|
30
|
-
private isSingleButton;
|
31
|
-
private isTabbable;
|
32
|
-
private position;
|
31
|
+
private hasPrefixSlot;
|
33
32
|
}
|
@@ -1 +1 @@
|
|
1
|
-
var
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,i){var r,l=arguments.length,s=l<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,i);else for(var n=e.length-1;n>=0;n--)(r=e[n])&&(s=(l<3?r(s):l>3?r(t,o,s):r(t,o))||s);return l>3&&s&&Object.defineProperty(t,o,s),s};import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import ow,{owSlot}from"./library/ow.js";import styles from"./button-group.button.styles.js";let GlideCoreButtonGroupButton=class GlideCoreButtonGroupButton extends LitElement{constructor(){super(...arguments),this.label="",this.disabled=!1,this.value="",this.privateOrientation="horizontal",this.hasPrefixSlot=!1,this.#e=createRef(),this.#t=!1,this.#o=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}get selected(){return this.#t}set selected(e){this.#t=e,this.dispatchEvent(new Event("private-selected",{bubbles:!0}))}click(){this.#e.value?.click()}firstUpdated(){"icon-only"===this.privateVariant&&owSlot(this.#o.value)}focus(e){this.#e.value?.focus(e)}render(){return html`<div aria-checked="${this.selected}" aria-disabled="${this.disabled}" class="${classMap({component:!0,selected:this.selected,disabled:this.disabled,[this.privateOrientation]:!0,prefix:this.hasPrefixSlot,"icon-only":"icon-only"===this.privateVariant})}" role="radio" tabindex="${!this.selected||this.disabled?-1:0}" ${ref(this.#e)}><slot name="prefix" @slotchange="${this.#i}" ${ref(this.#o)}></slot><div class="${classMap({label:!0,"visually-hidden":"icon-only"===this.privateVariant})}">${this.label}</div></div>`}#e;#t;#o;#i(){ow(this.#o.value,ow.object.instanceOf(HTMLElement)),this.hasPrefixSlot=this.#o.value?.assignedNodes().length>0}};__decorate([property({reflect:!0})],GlideCoreButtonGroupButton.prototype,"label",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreButtonGroupButton.prototype,"selected",null),__decorate([property({type:Boolean,reflect:!0})],GlideCoreButtonGroupButton.prototype,"disabled",void 0),__decorate([property({reflect:!0})],GlideCoreButtonGroupButton.prototype,"value",void 0),__decorate([property()],GlideCoreButtonGroupButton.prototype,"privateOrientation",void 0),__decorate([property()],GlideCoreButtonGroupButton.prototype,"privateVariant",void 0),__decorate([state()],GlideCoreButtonGroupButton.prototype,"hasPrefixSlot",void 0),GlideCoreButtonGroupButton=__decorate([customElement("glide-core-button-group-button")],GlideCoreButtonGroupButton);export default GlideCoreButtonGroupButton;
|
@@ -1,9 +1,35 @@
|
|
1
1
|
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
|
2
|
+
:host(:first-of-type) {
|
3
|
+
.component {
|
4
|
+
&.horizontal {
|
5
|
+
border-end-start-radius: 0.6875rem;
|
6
|
+
border-start-start-radius: 0.6875rem;
|
7
|
+
}
|
8
|
+
|
9
|
+
&.vertical {
|
10
|
+
border-start-end-radius: 0.6875rem;
|
11
|
+
border-start-start-radius: 0.6875rem;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
:host(:last-of-type) {
|
17
|
+
.component {
|
18
|
+
&.horizontal {
|
19
|
+
border-end-end-radius: 0.6875rem;
|
20
|
+
border-start-end-radius: 0.6875rem;
|
21
|
+
}
|
22
|
+
|
23
|
+
&.vertical {
|
24
|
+
border-end-end-radius: 0.6875rem;
|
25
|
+
border-end-start-radius: 0.6875rem;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
2
30
|
.component {
|
3
31
|
align-items: center;
|
4
32
|
appearance: none;
|
5
|
-
border: none;
|
6
|
-
border-inline-end: 1px solid var(--glide-core-border-base-lighter);
|
7
33
|
cursor: pointer;
|
8
34
|
display: flex;
|
9
35
|
font-family: var(--glide-core-font-sans);
|
@@ -15,7 +41,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
|
|
15
41
|
line-height: 1;
|
16
42
|
min-block-size: 1.125rem;
|
17
43
|
min-inline-size: 5.1875rem;
|
18
|
-
outline: none;
|
19
44
|
padding-block: var(--glide-core-spacing-xs);
|
20
45
|
padding-inline: var(--glide-core-spacing-md);
|
21
46
|
transition-duration: 150ms;
|
@@ -24,66 +49,39 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
|
|
24
49
|
user-select: none;
|
25
50
|
white-space: nowrap;
|
26
51
|
|
27
|
-
|
28
|
-
|
29
|
-
padding: var(--glide-core-spacing-xs);
|
52
|
+
&:focus {
|
53
|
+
outline: none;
|
30
54
|
}
|
31
55
|
|
32
|
-
|
33
|
-
|
34
|
-
border-
|
35
|
-
|
56
|
+
&:focus-visible {
|
57
|
+
background-color: var(--glide-core-surface-selected);
|
58
|
+
border-color: var(--glide-core-border-focus);
|
59
|
+
color: var(--glide-core-color-white);
|
60
|
+
|
61
|
+
${focusOutline};
|
62
|
+
outline-offset: 2px;
|
36
63
|
|
37
|
-
|
38
|
-
|
64
|
+
/* Create a stacking context so the outline isn't obscured by other elements. */
|
65
|
+
transform: translateX(0);
|
39
66
|
}
|
40
67
|
|
41
|
-
&.
|
42
|
-
border-
|
68
|
+
&.horizontal {
|
69
|
+
border-inline-end: 1px solid var(--glide-core-border-base-lighter);
|
43
70
|
}
|
44
71
|
|
45
72
|
&.vertical {
|
46
|
-
border: none;
|
47
73
|
border-block-end: 1px solid var(--glide-core-border-base-lighter);
|
48
74
|
|
49
|
-
&.
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
&.last {
|
54
|
-
border-radius: 0 0 0.6875rem 0.6875rem;
|
75
|
+
&.prefix {
|
76
|
+
&:not(.icon-only) {
|
77
|
+
justify-content: flex-start;
|
78
|
+
}
|
55
79
|
}
|
56
80
|
}
|
57
81
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
color: var(--glide-core-color-white);
|
62
|
-
}
|
63
|
-
|
64
|
-
&:not(.disabled):active {
|
65
|
-
background-color: var(--glide-core-surface-selected);
|
66
|
-
border-color: var(--glide-core-border-focus);
|
67
|
-
color: var(--glide-core-color-white);
|
68
|
-
}
|
69
|
-
|
70
|
-
&:not(.disabled):focus-visible {
|
71
|
-
background-color: var(--glide-core-surface-selected);
|
72
|
-
border-color: var(--glide-core-border-focus);
|
73
|
-
color: var(--glide-core-color-white);
|
74
|
-
|
75
|
-
${focusOutline};
|
76
|
-
outline-offset: 2px;
|
77
|
-
|
78
|
-
/* create a stacking context so the outline doesn't become obscured behind other elements */
|
79
|
-
transform: translateX(0);
|
80
|
-
}
|
81
|
-
|
82
|
-
&:not(.disabled, :active):hover {
|
83
|
-
background-color: var(--glide-core-surface-hover);
|
84
|
-
border-color: transparent;
|
85
|
-
box-shadow: var(--glide-core-glow-sm);
|
86
|
-
color: var(--glide-core-text-primary);
|
82
|
+
&.icon-only {
|
83
|
+
min-inline-size: 0;
|
84
|
+
padding: var(--glide-core-spacing-xs);
|
87
85
|
}
|
88
86
|
|
89
87
|
&.disabled {
|
@@ -92,9 +90,34 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
|
|
92
90
|
color: var(--glide-core-text-tertiary-disabled);
|
93
91
|
cursor: not-allowed;
|
94
92
|
}
|
93
|
+
|
94
|
+
&:not(.disabled) {
|
95
|
+
&:active {
|
96
|
+
background-color: var(--glide-core-surface-selected);
|
97
|
+
border-color: var(--glide-core-border-focus);
|
98
|
+
color: var(--glide-core-color-white);
|
99
|
+
}
|
100
|
+
|
101
|
+
&.selected {
|
102
|
+
background-color: var(--glide-core-surface-selected);
|
103
|
+
border-color: var(--glide-core-surface-selected);
|
104
|
+
color: var(--glide-core-color-white);
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
&:not(.disabled, :active) {
|
109
|
+
&:hover {
|
110
|
+
background-color: var(--glide-core-surface-hover);
|
111
|
+
border-color: transparent;
|
112
|
+
box-shadow: var(--glide-core-glow-sm);
|
113
|
+
color: var(--glide-core-text-primary);
|
114
|
+
}
|
115
|
+
}
|
95
116
|
}
|
96
117
|
|
97
|
-
.
|
98
|
-
|
118
|
+
.label {
|
119
|
+
&.visually-hidden {
|
120
|
+
${visuallyHidden};
|
121
|
+
}
|
99
122
|
}
|
100
123
|
`];
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
import './button-group.button.js';
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
|
+
import './button-group.button.js';
|
1
3
|
import { ArgumentError } from 'ow';
|
2
4
|
import { expect, fixture, html } from '@open-wc/testing';
|
3
5
|
import GlideCoreButtonGroupButton from './button-group.button.js';
|
@@ -6,164 +8,99 @@ GlideCoreButtonGroupButton.shadowRootOptions.mode = 'open';
|
|
6
8
|
it('registers', async () => {
|
7
9
|
expect(window.customElements.get('glide-core-button-group-button')).to.equal(GlideCoreButtonGroupButton);
|
8
10
|
});
|
9
|
-
it('
|
10
|
-
const
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
expect(
|
21
|
-
});
|
22
|
-
it('renders "aria-checked" equal to "false" and "tabindex" equal to "-1" by default', async () => {
|
23
|
-
const element = await fixture(html `<glide-core-button-group-button value="value"
|
24
|
-
>Button</glide-core-button-group-button
|
25
|
-
>`);
|
26
|
-
const liElement = element.shadowRoot?.querySelector('li');
|
27
|
-
expect(liElement).to.not.be.null;
|
28
|
-
expect(liElement).to.have.attribute('aria-checked', 'false');
|
29
|
-
expect(liElement).to.have.attribute('tabindex', '-1');
|
30
|
-
});
|
31
|
-
it('renders "aria-checked" equal to "true" and "tabindex" equal to "0" when attribute "selected" exists', async () => {
|
32
|
-
const element = await fixture(html `<glide-core-button-group-button value="value" selected
|
33
|
-
>Button</glide-core-button-group-button
|
34
|
-
>`);
|
35
|
-
const liElement = element.shadowRoot?.querySelector('li');
|
36
|
-
expect(liElement).to.have.attribute('aria-checked', 'true');
|
37
|
-
expect(liElement).to.have.attribute('tabindex', '0');
|
38
|
-
});
|
39
|
-
it('renders two slots, where one has name "prefix", and the other is default with given text', async () => {
|
40
|
-
const element = await fixture(html `<glide-core-button-group-button value="value" selected
|
41
|
-
><span slot="prefix" data-prefix>Prefix</span
|
42
|
-
>Button</glide-core-button-group-button
|
43
|
-
>`);
|
44
|
-
const prefixSlot = element.shadowRoot?.querySelector('slot[name="prefix"]');
|
45
|
-
const defaultSlot = element.shadowRoot?.querySelector('slot:not([name="prefix"])');
|
46
|
-
// verify the slots exist
|
47
|
-
expect(prefixSlot).to.not.be.null;
|
48
|
-
expect(defaultSlot).to.not.be.null;
|
49
|
-
const prefixContent = document.querySelector('[data-prefix]');
|
50
|
-
const content = document.querySelector('glide-core-button-group-button');
|
51
|
-
// verify the content of the slots exist
|
52
|
-
expect(prefixContent).to.not.be.null;
|
53
|
-
expect(prefixContent?.textContent).to.equal('Prefix');
|
54
|
-
expect(content?.textContent).to.contain('Button');
|
55
|
-
});
|
56
|
-
it('is has a disabled presentation when the "disabled" attribute is true', async () => {
|
57
|
-
const element = await fixture(html `<glide-core-button-group-button value="value" disabled
|
58
|
-
>Button</glide-core-button-group-button
|
59
|
-
>`);
|
60
|
-
const liElement = element.shadowRoot?.querySelector('li');
|
61
|
-
expect(liElement).to.have.attribute('aria-disabled', 'true');
|
62
|
-
});
|
63
|
-
it('does not have a disabled presentation when "disabled" attribute is false', async () => {
|
64
|
-
const element = await fixture(html `<glide-core-button-group-button value="value"
|
65
|
-
>Button</glide-core-button-group-button
|
66
|
-
>`);
|
67
|
-
const liElement = element.shadowRoot?.querySelector('li');
|
68
|
-
expect(liElement).to.have.attribute('aria-disabled', 'false');
|
69
|
-
});
|
70
|
-
it('has a vertical presention when the "vertical" attribute is set', async () => {
|
71
|
-
await fixture(html ` <glide-core-button-group-button value="value" vertical
|
72
|
-
>Button</glide-core-button-group-button
|
73
|
-
>`);
|
74
|
-
const buttonElement = document.querySelector('glide-core-button-group-button');
|
75
|
-
const liElement = buttonElement?.shadowRoot?.querySelector('li');
|
76
|
-
expect(liElement).to.have.class('vertical');
|
77
|
-
});
|
78
|
-
it('does not have a vertical presention when the "vertical" attribute is not set', async () => {
|
79
|
-
await fixture(html ` <glide-core-button-group-button value="value"
|
80
|
-
>Button</glide-core-button-group-button
|
81
|
-
>`);
|
82
|
-
const buttonElement = document.querySelector('glide-core-button-group-button');
|
83
|
-
const liElement = buttonElement?.shadowRoot?.querySelector('li');
|
84
|
-
expect(liElement).to.not.have.class('vertical');
|
85
|
-
});
|
86
|
-
it('sets buttons as not tabbable by default', async () => {
|
87
|
-
const element = await fixture(html `<glide-core-button-group-button value="value"
|
88
|
-
>Button</glide-core-button-group-button
|
89
|
-
>`);
|
90
|
-
const liElement = element.shadowRoot?.querySelector('li');
|
91
|
-
await expect(liElement).to.have.attribute('tabindex', '-1');
|
11
|
+
it('has defaults', async () => {
|
12
|
+
const component = await fixture(html `
|
13
|
+
<glide-core-button-group-button
|
14
|
+
label="Button"
|
15
|
+
></glide-core-button-group-button>
|
16
|
+
`);
|
17
|
+
expect(component.disabled).to.be.false;
|
18
|
+
expect(component.selected).to.be.false;
|
19
|
+
expect(component.value).to.equal('');
|
20
|
+
expect(component).to.have.attribute('value', '');
|
21
|
+
expect(component).to.not.have.attribute('disabled');
|
22
|
+
expect(component).to.not.have.attribute('selected');
|
92
23
|
});
|
93
|
-
it('
|
94
|
-
const
|
95
|
-
|
96
|
-
>`);
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
value="value"
|
24
|
+
it('is accessible', async () => {
|
25
|
+
const component = await fixture(html `<glide-core-button-group-button
|
26
|
+
label="Button"
|
27
|
+
></glide-core-button-group-button>`);
|
28
|
+
await expect(component).to.be.accessible();
|
29
|
+
});
|
30
|
+
it('can have a label', async () => {
|
31
|
+
const component = await fixture(html `<glide-core-button-group-button
|
32
|
+
label="Button"
|
103
33
|
selected
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
const
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
34
|
+
></glide-core-button-group-button>`);
|
35
|
+
expect(component.shadowRoot?.textContent?.trim()).to.equal('Button');
|
36
|
+
});
|
37
|
+
it('can have a "prefix" slot', async () => {
|
38
|
+
const component = await fixture(html `<glide-core-button-group-button label="Button">
|
39
|
+
<span slot="prefix">Prefix</span>
|
40
|
+
</glide-core-button-group-button>`);
|
41
|
+
const assignedElements = component.shadowRoot
|
42
|
+
?.querySelector('slot[name="prefix"]')
|
43
|
+
?.assignedElements();
|
44
|
+
expect(assignedElements?.at(0)?.textContent).to.equal('Prefix');
|
45
|
+
});
|
46
|
+
it('sets `aria-checked` when selected', async () => {
|
47
|
+
const component = await fixture(html `<glide-core-button-group-button
|
48
|
+
label="Button"
|
49
|
+
selected
|
50
|
+
></glide-core-button-group-button>`);
|
51
|
+
const radio = component.shadowRoot?.querySelector('[role="radio"]');
|
52
|
+
expect(radio).to.have.attribute('aria-checked', 'true');
|
53
|
+
});
|
54
|
+
it('sets `aria-checked` when not selected', async () => {
|
55
|
+
const component = await fixture(html `<glide-core-button-group-button
|
56
|
+
label="Button"
|
57
|
+
></glide-core-button-group-button>`);
|
58
|
+
const radio = component.shadowRoot?.querySelector('[role="radio"]');
|
59
|
+
expect(radio).to.have.attribute('aria-checked', 'false');
|
60
|
+
});
|
61
|
+
it('sets `aria-disabled` when disabled', async () => {
|
62
|
+
const component = await fixture(html `<glide-core-button-group-button
|
63
|
+
label="Button"
|
64
|
+
disabled
|
65
|
+
></glide-core-button-group-button>`);
|
66
|
+
const radio = component.shadowRoot?.querySelector('[role="radio"]');
|
67
|
+
expect(radio).to.have.attribute('aria-disabled', 'true');
|
68
|
+
});
|
69
|
+
it('sets `aria-disabled` when not disabled', async () => {
|
70
|
+
const component = await fixture(html `<glide-core-button-group-button
|
71
|
+
label="Button"
|
72
|
+
></glide-core-button-group-button>`);
|
73
|
+
const radio = component.shadowRoot?.querySelector('[role="radio"]');
|
74
|
+
expect(radio).to.have.attribute('aria-disabled', 'false');
|
75
|
+
});
|
76
|
+
it('is tabbable when selected', async () => {
|
77
|
+
const component = await fixture(html `<glide-core-button-group-button
|
78
|
+
label="Button"
|
79
|
+
selected
|
80
|
+
></glide-core-button-group-button>`);
|
81
|
+
const radio = component.shadowRoot?.querySelector('[role="radio"]');
|
82
|
+
expect(radio).to.have.attribute('tabindex', '0');
|
83
|
+
});
|
84
|
+
it('is not tabbable when not selected', async () => {
|
85
|
+
const component = await fixture(html `<glide-core-button-group-button
|
86
|
+
label="Button"
|
87
|
+
></glide-core-button-group-button>`);
|
88
|
+
const radio = component.shadowRoot?.querySelector('[role="radio"]');
|
89
|
+
expect(radio).to.have.attribute('tabindex', '-1');
|
90
|
+
});
|
91
|
+
it('throws when icon-only and no "prefix" slot', async () => {
|
135
92
|
const spy = sinon.spy();
|
136
|
-
// Not sure how to resolve the below, despite the test passing, so disabling console errors for now:
|
137
|
-
//
|
138
|
-
// Browser logs:
|
139
|
-
// An error was thrown in a Promise outside a test. Did you forget to await a function or assertion?
|
140
|
-
sinon.stub(console, 'error'); // Disable console.error
|
141
93
|
try {
|
142
94
|
await fixture(html `<glide-core-button-group-button
|
143
95
|
value="value"
|
144
96
|
selected
|
145
|
-
|
146
|
-
|
147
|
-
>`);
|
148
|
-
}
|
149
|
-
catch (error) {
|
150
|
-
if (error instanceof ArgumentError) {
|
151
|
-
spy();
|
152
|
-
}
|
153
|
-
}
|
154
|
-
expect(spy.called).to.be.true;
|
155
|
-
});
|
156
|
-
it('does not throw an error when prefix slot is empty and no variant is set', async () => {
|
157
|
-
const spy = sinon.spy();
|
158
|
-
try {
|
159
|
-
await fixture(html `<glide-core-button-group-button value="value" selected
|
160
|
-
>Button</glide-core-button-group-button
|
161
|
-
>`);
|
97
|
+
privateVariant="icon-only"
|
98
|
+
></glide-core-button-group-button>`);
|
162
99
|
}
|
163
100
|
catch (error) {
|
164
101
|
if (error instanceof ArgumentError) {
|
165
102
|
spy();
|
166
103
|
}
|
167
104
|
}
|
168
|
-
expect(spy.
|
105
|
+
expect(spy.callCount).to.equal(1);
|
169
106
|
});
|