@statistikzh/leu 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/commit-msg +0 -3
- package/.husky/pre-commit +0 -3
- package/CHANGELOG.md +48 -0
- package/dist/Accordion.d.ts +10 -9
- package/dist/Accordion.d.ts.map +1 -1
- package/dist/Accordion.js +12 -11
- package/dist/Breadcrumb.d.ts +4 -4
- package/dist/Breadcrumb.d.ts.map +1 -1
- package/dist/Breadcrumb.js +28 -26
- package/dist/{Button-da11d064.d.ts → Button-9692e403.d.ts} +10 -11
- package/dist/Button-9692e403.d.ts.map +1 -0
- package/dist/{Button-da11d064.js → Button-9692e403.js} +65 -62
- package/dist/Button.d.ts +1 -1
- package/dist/Button.js +3 -3
- package/dist/ButtonGroup.d.ts +2 -2
- package/dist/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup.js +3 -3
- package/dist/Checkbox.d.ts +4 -3
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +14 -19
- package/dist/CheckboxGroup.d.ts +2 -2
- package/dist/CheckboxGroup.d.ts.map +1 -1
- package/dist/CheckboxGroup.js +4 -6
- package/dist/Chip.d.ts +2 -2
- package/dist/Chip.d.ts.map +1 -1
- package/dist/Chip.js +6 -13
- package/dist/ChipGroup.d.ts +9 -7
- package/dist/ChipGroup.d.ts.map +1 -1
- package/dist/ChipGroup.js +8 -5
- package/dist/ChipLink.d.ts +2 -1
- package/dist/ChipLink.d.ts.map +1 -1
- package/dist/ChipLink.js +4 -7
- package/dist/ChipRemovable.d.ts +0 -2
- package/dist/ChipRemovable.d.ts.map +1 -1
- package/dist/ChipRemovable.js +8 -11
- package/dist/ChipSelectable.d.ts +9 -1
- package/dist/ChipSelectable.d.ts.map +1 -1
- package/dist/ChipSelectable.js +12 -16
- package/dist/Dropdown.d.ts +9 -5
- package/dist/Dropdown.d.ts.map +1 -1
- package/dist/Dropdown.js +73 -32
- package/dist/Icon.d.ts +20 -0
- package/dist/Icon.d.ts.map +1 -0
- package/dist/{icon-03e86700.js → Icon.js} +61 -32
- package/dist/Input.d.ts +7 -16
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +24 -28
- package/dist/LeuElement-6de6f209.d.ts +7 -0
- package/dist/LeuElement-6de6f209.d.ts.map +1 -0
- package/dist/LeuElement-6de6f209.js +43 -0
- package/dist/Menu.d.ts +24 -2
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Menu.js +120 -3
- package/dist/MenuItem.d.ts +28 -11
- package/dist/MenuItem.d.ts.map +1 -1
- package/dist/MenuItem.js +110 -63
- package/dist/Pagination.d.ts +10 -3
- package/dist/Pagination.d.ts.map +1 -1
- package/dist/Pagination.js +24 -21
- package/dist/Popup.d.ts +21 -3
- package/dist/Popup.d.ts.map +1 -1
- package/dist/Popup.js +44 -19
- package/dist/Radio.d.ts +4 -2
- package/dist/Radio.d.ts.map +1 -1
- package/dist/Radio.js +9 -16
- package/dist/RadioGroup.d.ts +2 -2
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +4 -6
- package/dist/ScrollTop.d.ts +2 -2
- package/dist/ScrollTop.d.ts.map +1 -1
- package/dist/ScrollTop.js +10 -8
- package/dist/Select.d.ts +75 -37
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +279 -183
- package/dist/Table.d.ts +2 -6
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +17 -18
- package/dist/VisuallyHidden.d.ts +2 -2
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +5 -7
- package/dist/{index.js.d.ts → index.d.ts} +3 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/{index.js.js → index.js} +5 -14
- package/dist/leu-accordion.d.ts.map +1 -1
- package/dist/leu-accordion.js +2 -3
- package/dist/leu-breadcrumb.d.ts.map +1 -1
- package/dist/leu-breadcrumb.js +4 -10
- package/dist/leu-button-group.d.ts.map +1 -1
- package/dist/leu-button-group.js +2 -3
- package/dist/leu-button.d.ts +1 -1
- package/dist/leu-button.d.ts.map +1 -1
- package/dist/leu-button.js +4 -5
- package/dist/leu-checkbox-group.d.ts.map +1 -1
- package/dist/leu-checkbox-group.js +2 -3
- package/dist/leu-checkbox.d.ts.map +1 -1
- package/dist/leu-checkbox.js +3 -4
- package/dist/leu-chip-group.d.ts.map +1 -1
- package/dist/leu-chip-group.js +2 -3
- package/dist/leu-chip-link.d.ts.map +1 -1
- package/dist/leu-chip-link.js +2 -3
- package/dist/leu-chip-removable.d.ts.map +1 -1
- package/dist/leu-chip-removable.js +3 -4
- package/dist/leu-chip-selectable.d.ts.map +1 -1
- package/dist/leu-chip-selectable.js +2 -3
- package/dist/leu-dropdown.d.ts.map +1 -1
- package/dist/leu-dropdown.js +5 -10
- package/dist/leu-icon.d.ts +3 -0
- package/dist/leu-icon.d.ts.map +1 -0
- package/dist/leu-icon.js +7 -0
- package/dist/leu-input.d.ts.map +1 -1
- package/dist/leu-input.js +3 -4
- package/dist/leu-menu-item.d.ts.map +1 -1
- package/dist/leu-menu-item.js +3 -5
- package/dist/leu-menu.d.ts.map +1 -1
- package/dist/leu-menu.js +5 -3
- package/dist/leu-pagination.d.ts.map +1 -1
- package/dist/leu-pagination.js +4 -7
- package/dist/leu-popup.d.ts.map +1 -1
- package/dist/leu-popup.js +2 -3
- package/dist/leu-radio-group.d.ts.map +1 -1
- package/dist/leu-radio-group.js +2 -3
- package/dist/leu-radio.d.ts.map +1 -1
- package/dist/leu-radio.js +2 -3
- package/dist/leu-scroll-top.d.ts.map +1 -1
- package/dist/leu-scroll-top.js +4 -6
- package/dist/leu-select.d.ts.map +1 -1
- package/dist/leu-select.js +5 -13
- package/dist/leu-table.d.ts.map +1 -1
- package/dist/leu-table.js +4 -8
- package/dist/leu-visually-hidden.d.ts.map +1 -1
- package/dist/leu-visually-hidden.js +2 -3
- package/dist/theme.css +2 -0
- package/dist/vscode.html-custom-data.json +616 -0
- package/dist/vue/index.d.ts +682 -0
- package/dist/web-types.json +1211 -0
- package/package.json +10 -13
- package/rollup.config.js +1 -1
- package/scripts/generate-component/templates/[Name].js +6 -3
- package/scripts/generate-component/templates/test/[name].test.js +1 -1
- package/src/components/accordion/Accordion.js +13 -10
- package/src/components/accordion/leu-accordion.js +1 -2
- package/src/components/breadcrumb/Breadcrumb.js +31 -18
- package/src/components/breadcrumb/leu-breadcrumb.js +1 -2
- package/src/components/button/Button.js +45 -71
- package/src/components/button/button.css +19 -4
- package/src/components/button/leu-button.js +1 -2
- package/src/components/button/stories/button.stories.js +60 -19
- package/src/components/button/test/button.test.js +26 -63
- package/src/components/button-group/ButtonGroup.js +4 -2
- package/src/components/button-group/leu-button-group.js +1 -2
- package/src/components/checkbox/Checkbox.js +17 -11
- package/src/components/checkbox/CheckboxGroup.js +6 -3
- package/src/components/checkbox/leu-checkbox-group.js +1 -2
- package/src/components/checkbox/leu-checkbox.js +1 -2
- package/src/components/checkbox/stories/checkbox-group.stories.js +10 -26
- package/src/components/checkbox/stories/checkbox.stories.js +2 -7
- package/src/components/checkbox/test/checkbox-group.test.js +6 -21
- package/src/components/checkbox/test/checkbox.test.js +1 -12
- package/src/components/chip/Chip.js +5 -4
- package/src/components/chip/ChipGroup.js +10 -4
- package/src/components/chip/ChipLink.js +3 -7
- package/src/components/chip/ChipRemovable.js +8 -11
- package/src/components/chip/ChipSelectable.js +11 -17
- package/src/components/chip/chip.css +3 -4
- package/src/components/chip/leu-chip-group.js +1 -2
- package/src/components/chip/leu-chip-link.js +1 -2
- package/src/components/chip/leu-chip-removable.js +1 -2
- package/src/components/chip/leu-chip-selectable.js +1 -2
- package/src/components/chip/stories/chip-link.stories.js +3 -5
- package/src/components/chip/stories/chip-removable.stories.js +3 -4
- package/src/components/chip/stories/chip-selectable.stories.js +2 -2
- package/src/components/chip/test/chip-group.test.js +15 -30
- package/src/components/chip/test/chip-link.test.js +2 -6
- package/src/components/chip/test/chip-removable.test.js +4 -10
- package/src/components/chip/test/chip-selectable.test.js +3 -5
- package/src/components/dropdown/Dropdown.js +80 -26
- package/src/components/dropdown/dropdown.css +4 -0
- package/src/components/dropdown/leu-dropdown.js +1 -2
- package/src/components/dropdown/stories/dropdown.stories.js +30 -7
- package/src/components/dropdown/test/dropdown.test.js +5 -5
- package/src/components/icon/Icon.js +55 -0
- package/src/components/icon/icon.css +6 -0
- package/src/components/icon/leu-icon.js +5 -0
- package/src/components/icon/{icon.js → paths.js} +4 -37
- package/src/components/icon/stories/icon.stories.js +47 -0
- package/src/components/icon/test/icon.test.js +23 -40
- package/src/components/input/Input.js +21 -23
- package/src/components/input/input.css +4 -2
- package/src/components/input/leu-input.js +1 -2
- package/src/components/input/stories/input.stories.js +2 -2
- package/src/components/input/test/input.test.js +2 -0
- package/src/components/menu/Menu.js +143 -2
- package/src/components/menu/MenuItem.js +104 -52
- package/src/components/menu/leu-menu-item.js +1 -2
- package/src/components/menu/leu-menu.js +1 -2
- package/src/components/menu/menu-item.css +11 -4
- package/src/components/menu/stories/menu-item.stories.js +15 -4
- package/src/components/menu/stories/menu.stories.js +34 -7
- package/src/components/menu/test/menu-item.test.js +88 -82
- package/src/components/menu/test/menu.test.js +101 -8
- package/src/components/pagination/Pagination.js +27 -18
- package/src/components/pagination/leu-pagination.js +1 -2
- package/src/components/popup/Popup.js +39 -16
- package/src/components/popup/leu-popup.js +1 -2
- package/src/components/popup/popup.css +1 -0
- package/src/components/radio/Radio.js +12 -7
- package/src/components/radio/RadioGroup.js +6 -3
- package/src/components/radio/leu-radio-group.js +1 -2
- package/src/components/radio/leu-radio.js +1 -2
- package/src/components/radio/stories/radio-group.stories.js +5 -19
- package/src/components/radio/stories/radio.stories.js +2 -7
- package/src/components/radio/test/radio-group.test.js +6 -9
- package/src/components/radio/test/radio.test.js +3 -13
- package/src/components/scroll-top/ScrollTop.js +15 -5
- package/src/components/scroll-top/leu-scroll-top.js +1 -2
- package/src/components/select/Select.js +279 -175
- package/src/components/select/leu-select.js +1 -2
- package/src/components/select/select.css +20 -12
- package/src/components/select/stories/select.stories.js +16 -2
- package/src/components/select/test/select.test.js +191 -37
- package/src/components/table/Table.js +15 -9
- package/src/components/table/leu-table.js +1 -2
- package/src/components/table/table.css +3 -1
- package/src/components/visually-hidden/VisuallyHidden.js +6 -2
- package/src/components/visually-hidden/leu-visually-hidden.js +1 -2
- package/src/lib/LeuElement.js +23 -0
- package/src/lib/a11y.js +26 -0
- package/src/styles/custom-properties.css +2 -0
- package/web-test-runner.config.mjs +2 -0
- package/dist/Button-da11d064.d.ts.map +0 -1
- package/dist/_rollupPluginBabelHelpers-20f659f4.d.ts +0 -3
- package/dist/_rollupPluginBabelHelpers-20f659f4.d.ts.map +0 -1
- package/dist/_rollupPluginBabelHelpers-20f659f4.js +0 -30
- package/dist/defineElement-40372b4b.d.ts +0 -9
- package/dist/defineElement-40372b4b.d.ts.map +0 -1
- package/dist/defineElement-40372b4b.js +0 -15
- package/dist/icon-03e86700.d.ts +0 -11
- package/dist/icon-03e86700.d.ts.map +0 -1
- package/dist/index.js.d.ts.map +0 -1
- package/src/lib/defineElement.js +0 -13
|
@@ -1,44 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { html, unsafeStatic } from "lit/static-html.js"
|
|
1
|
+
import { html } from "lit"
|
|
3
2
|
import { ifDefined } from "lit/directives/if-defined.js"
|
|
4
3
|
|
|
4
|
+
import { LeuElement } from "../../lib/LeuElement.js"
|
|
5
|
+
import { LeuIcon } from "../icon/Icon.js"
|
|
6
|
+
|
|
7
|
+
// @ts-ignore
|
|
5
8
|
import styles from "./menu-item.css"
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {'menuitem' | 'menuitemcheckbox' | 'menuitemradio' | 'option' | 'none'} MenuItemRole
|
|
12
|
+
*/
|
|
8
13
|
|
|
9
14
|
/**
|
|
10
15
|
* @tagname leu-menu-item
|
|
11
16
|
* @slot - The label of the menu item
|
|
17
|
+
* @property {boolean} active - Defines if the item is selected or checked
|
|
18
|
+
* @property {boolean} disabled - Disables the underlying button or link
|
|
19
|
+
* @property {string} value - The value of the item. It must not contain commas. See `getValue()`
|
|
20
|
+
* @property {string} href - The href of the underlying link
|
|
21
|
+
* @property {boolean} tabbable - If the item should be focusable. Will be reflected as `tabindex` to the underlying button or link
|
|
22
|
+
* @property {MenuItemRole} componentRole - The role of the item. This will be reflected as `role` to the underlying button or link. Default is `'menuitem'.`
|
|
12
23
|
*/
|
|
13
|
-
export class LeuMenuItem extends
|
|
24
|
+
export class LeuMenuItem extends LeuElement {
|
|
25
|
+
static dependencies = {
|
|
26
|
+
"leu-icon": LeuIcon,
|
|
27
|
+
}
|
|
28
|
+
|
|
14
29
|
static styles = styles
|
|
15
30
|
|
|
16
31
|
/**
|
|
17
32
|
* @internal
|
|
18
33
|
*/
|
|
19
34
|
static shadowRootOptions = {
|
|
20
|
-
...
|
|
35
|
+
...LeuElement.shadowRootOptions,
|
|
21
36
|
delegatesFocus: true,
|
|
22
37
|
}
|
|
23
38
|
|
|
24
39
|
static properties = {
|
|
25
|
-
/**
|
|
26
|
-
* Can be either an icon name or a text
|
|
27
|
-
* If no icon with this value is found, it will be displayed as text.
|
|
28
|
-
* If the value is "EMPTY", an empty placeholder with the size of an icon will be displayed.
|
|
29
|
-
*/
|
|
30
|
-
before: { type: String, reflect: true },
|
|
31
|
-
/**
|
|
32
|
-
* Can be either an icon name or a text
|
|
33
|
-
* If no icon with this value is found, it will be displayed as text
|
|
34
|
-
* If the value is "EMPTY", an empty placeholder with the size of an icon will be displayed.
|
|
35
|
-
*/
|
|
36
|
-
after: { type: String, reflect: true },
|
|
37
40
|
active: { type: Boolean, reflect: true },
|
|
38
|
-
highlighted: { type: Boolean, reflect: true },
|
|
39
41
|
disabled: { type: Boolean, reflect: true },
|
|
40
|
-
|
|
42
|
+
tabbable: { type: Boolean, reflect: true },
|
|
41
43
|
href: { type: String, reflect: true },
|
|
44
|
+
value: { type: String, reflect: true },
|
|
45
|
+
componentRole: { type: String, reflect: true },
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
constructor() {
|
|
@@ -46,57 +50,105 @@ export class LeuMenuItem extends LitElement {
|
|
|
46
50
|
|
|
47
51
|
this.active = false
|
|
48
52
|
this.disabled = false
|
|
53
|
+
this.value = undefined
|
|
54
|
+
this.href = undefined
|
|
55
|
+
this.tabbable = undefined
|
|
49
56
|
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
* This is just a visual effect and does not change the active state.
|
|
53
|
-
*/
|
|
54
|
-
this.highlighted = false
|
|
57
|
+
/** @type {MenuItemRole} */
|
|
58
|
+
this.componentRole = "menuitem"
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
connectedCallback() {
|
|
62
|
+
super.connectedCallback()
|
|
63
|
+
this.addEventListener("click", this._handleClick, true)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
disconnectedCallback() {
|
|
67
|
+
super.disconnectedCallback()
|
|
68
|
+
this.removeEventListener("click", this._handleClick, true)
|
|
69
|
+
}
|
|
61
70
|
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
_handleClick(event) {
|
|
72
|
+
if (this.disabled) {
|
|
73
|
+
event.stopPropagation()
|
|
74
|
+
event.preventDefault()
|
|
64
75
|
}
|
|
76
|
+
}
|
|
65
77
|
|
|
66
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Returns the value of the item. If `value` is not set, it will return the inner text
|
|
80
|
+
* @returns {string}
|
|
81
|
+
*/
|
|
82
|
+
getValue() {
|
|
83
|
+
return this.value || this.innerText
|
|
67
84
|
}
|
|
68
85
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
86
|
+
_getAria() {
|
|
87
|
+
const commonAttributes = {
|
|
88
|
+
disabled: this.disabled,
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (this.href) {
|
|
92
|
+
return commonAttributes
|
|
73
93
|
}
|
|
74
94
|
|
|
75
|
-
return
|
|
95
|
+
return {
|
|
96
|
+
...commonAttributes,
|
|
97
|
+
checked:
|
|
98
|
+
this.componentRole === "menuitemcheckbox" ||
|
|
99
|
+
this.componentRole === "menuitemradio"
|
|
100
|
+
? this.active
|
|
101
|
+
: undefined,
|
|
102
|
+
selected: this.componentRole === "option" ? this.active : undefined,
|
|
103
|
+
role: this.componentRole === "none" ? undefined : this.componentRole,
|
|
104
|
+
}
|
|
76
105
|
}
|
|
77
106
|
|
|
78
|
-
|
|
79
|
-
if (this.
|
|
80
|
-
|
|
81
|
-
return html`<span class="after">${content}</span>`
|
|
107
|
+
_getTabIndex() {
|
|
108
|
+
if (typeof this.tabbable === "boolean") {
|
|
109
|
+
return this.tabbable ? 0 : -1
|
|
82
110
|
}
|
|
83
111
|
|
|
84
|
-
return
|
|
112
|
+
return undefined
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
_renderLink(content) {
|
|
116
|
+
const aria = this._getAria()
|
|
117
|
+
|
|
118
|
+
return html`<a
|
|
119
|
+
class="button"
|
|
120
|
+
href=${this.href}
|
|
121
|
+
aria-disabled=${ifDefined(aria.disabled)}
|
|
122
|
+
aria-checked=${ifDefined(aria.checked)}
|
|
123
|
+
aria-selected=${ifDefined(aria.selected)}
|
|
124
|
+
role=${ifDefined(aria.role)}
|
|
125
|
+
tabindex=${ifDefined(this._getTabIndex())}
|
|
126
|
+
>${content}</a
|
|
127
|
+
>`
|
|
85
128
|
}
|
|
86
129
|
|
|
87
|
-
|
|
88
|
-
|
|
130
|
+
_renderButton(content) {
|
|
131
|
+
const aria = this._getAria()
|
|
132
|
+
|
|
133
|
+
return html`<button
|
|
134
|
+
class="button"
|
|
135
|
+
aria-disabled=${ifDefined(aria.disabled)}
|
|
136
|
+
aria-checked=${ifDefined(aria.checked)}
|
|
137
|
+
aria-selected=${ifDefined(aria.selected)}
|
|
138
|
+
role=${ifDefined(aria.role)}
|
|
139
|
+
tabindex=${ifDefined(this._getTabIndex())}
|
|
140
|
+
>
|
|
141
|
+
${content}
|
|
142
|
+
</button>`
|
|
89
143
|
}
|
|
90
144
|
|
|
91
145
|
render() {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</${unsafeStatic(this.getTagName())}>`
|
|
100
|
-
/* eslint-enable lit/binding-positions, lit/no-invalid-html */
|
|
146
|
+
const content = html`
|
|
147
|
+
<slot class="before" name="before"></slot>
|
|
148
|
+
<span class="label"><slot></slot></span>
|
|
149
|
+
<slot class="after" name="after"></slot>
|
|
150
|
+
`
|
|
151
|
+
|
|
152
|
+
return this.href ? this._renderLink(content) : this._renderButton(content)
|
|
101
153
|
}
|
|
102
154
|
}
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
:host {
|
|
7
7
|
--background: var(--leu-color-black-0);
|
|
8
8
|
--background-hover: var(--leu-color-black-10);
|
|
9
|
-
--background-active: var(--leu-color-
|
|
9
|
+
--background-active: var(--leu-color-accent-blue);
|
|
10
10
|
--background-disabled: var(--leu-color-black-black-0);
|
|
11
11
|
--color: var(--leu-color-black-transp-60);
|
|
12
|
+
--color-active: var(--leu-color-black-0);
|
|
12
13
|
--color-disabled: var(--leu-color-black-transp-20);
|
|
13
14
|
--font-regular: var(--leu-font-family-regular);
|
|
14
15
|
--font-black: var(--leu-font-family-black);
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
|
|
30
31
|
padding: 0.75rem;
|
|
31
32
|
|
|
33
|
+
font-family: inherit;
|
|
32
34
|
font-size: 1rem;
|
|
33
35
|
line-height: 1.5;
|
|
34
36
|
text-align: left;
|
|
@@ -43,21 +45,26 @@
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
.button:hover,
|
|
46
|
-
|
|
48
|
+
.button:focus-visible {
|
|
47
49
|
--background: var(--background-hover);
|
|
48
50
|
}
|
|
49
51
|
|
|
52
|
+
/*
|
|
53
|
+
* These colors do not match with the design system (yet).
|
|
54
|
+
* But at least they are compliant with the WCAG AA contrast ratio.
|
|
55
|
+
*/
|
|
50
56
|
:host([active]) .button {
|
|
51
57
|
--background: var(--background-active);
|
|
58
|
+
--color: var(--color-active);
|
|
52
59
|
}
|
|
53
60
|
|
|
54
61
|
:host([disabled]) .button {
|
|
55
62
|
--background: var(--background-disabled);
|
|
56
63
|
--color: var(--color-disabled);
|
|
57
|
-
cursor:
|
|
64
|
+
cursor: not-allowed;
|
|
58
65
|
}
|
|
59
66
|
|
|
60
|
-
:is(.before, .after)
|
|
67
|
+
:is(.before, .after) leu-icon {
|
|
61
68
|
display: block;
|
|
62
69
|
}
|
|
63
70
|
|
|
@@ -2,6 +2,12 @@ import { html } from "lit"
|
|
|
2
2
|
import { ifDefined } from "lit/directives/if-defined.js"
|
|
3
3
|
|
|
4
4
|
import "../leu-menu-item.js"
|
|
5
|
+
import "../../icon/leu-icon.js"
|
|
6
|
+
import { paths as iconPaths } from "../../icon/paths.js"
|
|
7
|
+
|
|
8
|
+
function isIcon(name) {
|
|
9
|
+
return name === "EMPTY" || Object.keys(iconPaths).includes(name)
|
|
10
|
+
}
|
|
5
11
|
|
|
6
12
|
export default {
|
|
7
13
|
title: "Menu/Item",
|
|
@@ -20,13 +26,18 @@ export default {
|
|
|
20
26
|
function Template(args) {
|
|
21
27
|
return html`
|
|
22
28
|
<leu-menu-item
|
|
23
|
-
label=${args.label}
|
|
24
|
-
before=${ifDefined(args.before)}
|
|
25
|
-
after=${ifDefined(args.after)}
|
|
26
29
|
href=${ifDefined(args.href)}
|
|
27
30
|
?active=${args.active}
|
|
28
31
|
?disabled=${args.disabled}
|
|
29
|
-
|
|
32
|
+
>
|
|
33
|
+
${isIcon(args.before)
|
|
34
|
+
? html`<leu-icon slot="before" name=${args.before}></leu-icon>`
|
|
35
|
+
: html`<span slot="before">${args.before}</span>`}
|
|
36
|
+
${args.label}
|
|
37
|
+
${isIcon(args.after)
|
|
38
|
+
? html`<leu-icon slot="after" name=${args.after}></leu-icon>`
|
|
39
|
+
: html`<span slot="after">${args.after}</span>`}
|
|
40
|
+
</leu-menu-item>
|
|
30
41
|
`
|
|
31
42
|
}
|
|
32
43
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { html } from "lit"
|
|
2
2
|
import "../leu-menu.js"
|
|
3
3
|
import "../leu-menu-item.js"
|
|
4
|
+
import "../../icon/leu-icon.js"
|
|
5
|
+
import { ifDefined } from "lit/directives/if-defined.js"
|
|
4
6
|
|
|
5
7
|
export default {
|
|
6
8
|
title: "Menu",
|
|
@@ -11,16 +13,41 @@ export default {
|
|
|
11
13
|
url: "https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=17340-82208&mode=design&t=lzVrtq8lxYVJU5TB-11",
|
|
12
14
|
},
|
|
13
15
|
},
|
|
16
|
+
argTypes: {
|
|
17
|
+
selects: {
|
|
18
|
+
control: "select",
|
|
19
|
+
options: ["single", "multiple"],
|
|
20
|
+
},
|
|
21
|
+
role: {
|
|
22
|
+
control: "select",
|
|
23
|
+
options: ["menu", "listbox"],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
14
26
|
}
|
|
15
27
|
|
|
16
|
-
function Template() {
|
|
17
|
-
return html` <leu-menu
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
function Template(args) {
|
|
29
|
+
return html` <leu-menu
|
|
30
|
+
role=${ifDefined(args.role)}
|
|
31
|
+
selects=${ifDefined(args.selects)}
|
|
32
|
+
>
|
|
33
|
+
<leu-menu-item
|
|
34
|
+
><leu-icon slot="before"></leu-icon>Menu Item 1</leu-menu-item
|
|
35
|
+
>
|
|
36
|
+
<leu-menu-item active
|
|
37
|
+
><leu-icon slot="before" name="check"></leu-icon>Menu Item
|
|
38
|
+
2</leu-menu-item
|
|
39
|
+
>
|
|
40
|
+
<leu-menu-item
|
|
41
|
+
><leu-icon slot="before"></leu-icon>Menu Item 3</leu-menu-item
|
|
42
|
+
>
|
|
21
43
|
<hr />
|
|
22
|
-
<leu-menu-item
|
|
23
|
-
|
|
44
|
+
<leu-menu-item
|
|
45
|
+
><leu-icon slot="before" name="pin"></leu-icon>Menu Item 3<span
|
|
46
|
+
slot="after"
|
|
47
|
+
>CH</span
|
|
48
|
+
></leu-menu-item
|
|
49
|
+
>
|
|
50
|
+
<leu-menu-item>Menu Item 4</leu-menu-item>
|
|
24
51
|
</leu-menu>`
|
|
25
52
|
}
|
|
26
53
|
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
import { html } from "lit"
|
|
2
|
-
import { fixture, expect, oneEvent } from "@open-wc/testing"
|
|
2
|
+
import { fixture, expect, oneEvent, elementUpdated } from "@open-wc/testing"
|
|
3
3
|
import { ifDefined } from "lit/directives/if-defined.js"
|
|
4
4
|
import { spy } from "sinon"
|
|
5
5
|
|
|
6
|
+
import "../leu-menu.js"
|
|
6
7
|
import "../leu-menu-item.js"
|
|
7
8
|
|
|
8
9
|
async function defaultFixture(args = {}) {
|
|
9
10
|
return fixture(html`
|
|
10
11
|
<leu-menu-item
|
|
11
|
-
label=${args.label}
|
|
12
|
-
before=${ifDefined(args.before)}
|
|
13
|
-
after=${ifDefined(args.after)}
|
|
14
12
|
href=${ifDefined(args.href)}
|
|
13
|
+
componentRole=${ifDefined(args.componentRole)}
|
|
14
|
+
value=${ifDefined(args.value)}
|
|
15
15
|
?active=${args.active}
|
|
16
16
|
?disabled=${args.disabled}
|
|
17
|
-
|
|
17
|
+
?tabbable=${args.tabbable}
|
|
18
|
+
>
|
|
19
|
+
${args.label}
|
|
20
|
+
</leu-menu-item>
|
|
21
|
+
`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function wrappedFixture(args = {}) {
|
|
25
|
+
return fixture(html`
|
|
26
|
+
<leu-menu role=${ifDefined(args.menuRole)}>
|
|
27
|
+
${await defaultFixture(args)}
|
|
28
|
+
</leu-menu>
|
|
18
29
|
`)
|
|
19
30
|
}
|
|
20
31
|
|
|
@@ -26,26 +37,25 @@ describe("LeuMenuItem", () => {
|
|
|
26
37
|
})
|
|
27
38
|
|
|
28
39
|
it("passes the a11y audit", async () => {
|
|
29
|
-
const el = await
|
|
40
|
+
const el = await wrappedFixture({ label: "Download" })
|
|
30
41
|
|
|
31
|
-
await expect(el).
|
|
42
|
+
await expect(el).dom.to.be.accessible()
|
|
32
43
|
})
|
|
33
44
|
|
|
34
45
|
it("passes the a11y audit with a link", async () => {
|
|
35
|
-
const el = await
|
|
46
|
+
const el = await wrappedFixture({
|
|
36
47
|
label: "Download",
|
|
37
48
|
href: "https://zh.ch",
|
|
49
|
+
menuRole: "none",
|
|
38
50
|
})
|
|
39
51
|
|
|
40
|
-
await expect(el).
|
|
52
|
+
await expect(el).dom.to.be.accessible()
|
|
41
53
|
})
|
|
42
54
|
|
|
43
55
|
it("renders a label", async () => {
|
|
44
56
|
const el = await defaultFixture({ label: "Download" })
|
|
45
57
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
expect(button).to.have.trimmed.text("Download")
|
|
58
|
+
expect(el).to.have.trimmed.text("Download")
|
|
49
59
|
})
|
|
50
60
|
|
|
51
61
|
it("renders a button", async () => {
|
|
@@ -66,90 +76,61 @@ describe("LeuMenuItem", () => {
|
|
|
66
76
|
|
|
67
77
|
expect(link).to.exist
|
|
68
78
|
expect(link).to.have.attribute("href", "https://zh.ch")
|
|
69
|
-
expect(
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it("renders a before icon", async () => {
|
|
73
|
-
const el = await defaultFixture({ label: "Download", before: "download" })
|
|
74
|
-
|
|
75
|
-
const before = el.shadowRoot.querySelector(".before")
|
|
76
|
-
expect(before).to.exist
|
|
77
|
-
|
|
78
|
-
expect(el).shadowDom.to.equal(
|
|
79
|
-
"<button class='button'><span class='before'></span><span class='label'>Download</span></button>"
|
|
80
|
-
)
|
|
79
|
+
expect(el).to.have.trimmed.text("Kanton Zürich")
|
|
81
80
|
})
|
|
82
81
|
|
|
83
|
-
it("
|
|
84
|
-
const el = await defaultFixture({ label: "Download",
|
|
85
|
-
|
|
86
|
-
const before = el.shadowRoot.querySelector(".before")
|
|
87
|
-
expect(before).to.exist
|
|
88
|
-
expect(before).to.have.trimmed.text("DE")
|
|
89
|
-
|
|
90
|
-
expect(el).shadowDom.to.equal(
|
|
91
|
-
"<button class='button'><span class='before'>DE</span><span class='label'>Download</span></button>"
|
|
92
|
-
)
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
it("renders a before placeholder", async () => {
|
|
96
|
-
const el = await defaultFixture({ label: "Download", before: "EMPTY" })
|
|
97
|
-
|
|
98
|
-
const before = el.shadowRoot.querySelector(".before")
|
|
99
|
-
expect(before).to.exist
|
|
100
|
-
expect(before).to.not.have.trimmed.text()
|
|
101
|
-
|
|
102
|
-
const iconPlaceholder = before.querySelector(".icon-placeholder")
|
|
103
|
-
expect(iconPlaceholder).to.exist
|
|
104
|
-
|
|
105
|
-
expect(el).shadowDom.to.equal(
|
|
106
|
-
"<button class='button'><span class='before'><div class='icon-placeholder'></div></span><span class='label'>Download</span></button>"
|
|
107
|
-
)
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
it("renders a after icon", async () => {
|
|
111
|
-
const el = await defaultFixture({ label: "Download", after: "download" })
|
|
112
|
-
|
|
113
|
-
const after = el.shadowRoot.querySelector(".after")
|
|
114
|
-
expect(after).to.exist
|
|
82
|
+
it("sets the aria-disabled attribute to the button", async () => {
|
|
83
|
+
const el = await defaultFixture({ label: "Download", disabled: true })
|
|
115
84
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
85
|
+
const button = el.shadowRoot.querySelector("button")
|
|
86
|
+
expect(button).to.have.attribute("aria-disabled", "true")
|
|
119
87
|
})
|
|
120
88
|
|
|
121
|
-
it("
|
|
122
|
-
const el = await defaultFixture({
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
expect(after).to.exist
|
|
126
|
-
expect(after).to.have.trimmed.text("DE")
|
|
89
|
+
it("sets the defined role on the button", async () => {
|
|
90
|
+
const el = await defaultFixture({
|
|
91
|
+
label: "Download",
|
|
92
|
+
})
|
|
127
93
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
)
|
|
131
|
-
})
|
|
94
|
+
const button = el.shadowRoot.querySelector("button")
|
|
95
|
+
expect(button).to.have.attribute("role", "menuitem")
|
|
132
96
|
|
|
133
|
-
|
|
134
|
-
|
|
97
|
+
el.componentRole = "menuitemcheckbox"
|
|
98
|
+
await elementUpdated(el)
|
|
99
|
+
expect(button).to.have.attribute("role", "menuitemcheckbox")
|
|
135
100
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
expect(
|
|
101
|
+
el.componentRole = "menuitemradio"
|
|
102
|
+
await elementUpdated(el)
|
|
103
|
+
expect(button).to.have.attribute("role", "menuitemradio")
|
|
139
104
|
|
|
140
|
-
|
|
141
|
-
|
|
105
|
+
el.componentRole = "option"
|
|
106
|
+
await elementUpdated(el)
|
|
107
|
+
expect(button).to.have.attribute("role", "option")
|
|
142
108
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
)
|
|
109
|
+
el.componentRole = "none"
|
|
110
|
+
await elementUpdated(el)
|
|
111
|
+
expect(button).to.not.have.attribute("role")
|
|
146
112
|
})
|
|
147
113
|
|
|
148
|
-
it("
|
|
149
|
-
const el = await defaultFixture({
|
|
114
|
+
it("adds either the aria-checked or aria-selected attribute to the button when the item is active", async () => {
|
|
115
|
+
const el = await defaultFixture({
|
|
116
|
+
label: "Download",
|
|
117
|
+
componentRole: "option",
|
|
118
|
+
active: true,
|
|
119
|
+
})
|
|
150
120
|
|
|
151
121
|
const button = el.shadowRoot.querySelector("button")
|
|
152
|
-
expect(button).to.have.attribute("
|
|
122
|
+
expect(button).to.have.attribute("aria-selected", "true")
|
|
123
|
+
expect(button).not.to.have.attribute("aria-checked")
|
|
124
|
+
|
|
125
|
+
el.componentRole = "menuitemcheckbox"
|
|
126
|
+
await elementUpdated(el)
|
|
127
|
+
expect(button).to.have.attribute("aria-checked", "true")
|
|
128
|
+
expect(button).not.to.have.attribute("aria-selected")
|
|
129
|
+
|
|
130
|
+
el.componentRole = "menuitemradio"
|
|
131
|
+
await elementUpdated(el)
|
|
132
|
+
expect(button).to.have.attribute("aria-checked", "true")
|
|
133
|
+
expect(button).not.to.have.attribute("aria-selected")
|
|
153
134
|
})
|
|
154
135
|
|
|
155
136
|
it("lets the click event bubble up", async () => {
|
|
@@ -177,4 +158,29 @@ describe("LeuMenuItem", () => {
|
|
|
177
158
|
|
|
178
159
|
expect(clickSpy).to.have.not.been.called
|
|
179
160
|
})
|
|
161
|
+
|
|
162
|
+
it("reflects the tabbable property as tabindex to the button", async () => {
|
|
163
|
+
const el = await defaultFixture({ label: "Download", tabbable: true })
|
|
164
|
+
|
|
165
|
+
const button = el.shadowRoot.querySelector("button")
|
|
166
|
+
expect(button).to.have.attribute("tabindex", "0")
|
|
167
|
+
|
|
168
|
+
el.tabbable = false
|
|
169
|
+
await elementUpdated(el)
|
|
170
|
+
expect(button).to.have.attribute("tabindex", "-1")
|
|
171
|
+
|
|
172
|
+
el.tabbable = undefined
|
|
173
|
+
await elementUpdated(el)
|
|
174
|
+
expect(button).to.not.have.attribute("tabindex")
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it("returns the value or label when getValue is called", async () => {
|
|
178
|
+
const el = await defaultFixture({ label: "Download " })
|
|
179
|
+
|
|
180
|
+
expect(el.getValue()).to.equal("Download")
|
|
181
|
+
|
|
182
|
+
el.value = "download-01"
|
|
183
|
+
|
|
184
|
+
expect(el.getValue()).to.equal("download-01")
|
|
185
|
+
})
|
|
180
186
|
})
|