@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.
Files changed (240) hide show
  1. package/.husky/commit-msg +0 -3
  2. package/.husky/pre-commit +0 -3
  3. package/CHANGELOG.md +48 -0
  4. package/dist/Accordion.d.ts +10 -9
  5. package/dist/Accordion.d.ts.map +1 -1
  6. package/dist/Accordion.js +12 -11
  7. package/dist/Breadcrumb.d.ts +4 -4
  8. package/dist/Breadcrumb.d.ts.map +1 -1
  9. package/dist/Breadcrumb.js +28 -26
  10. package/dist/{Button-da11d064.d.ts → Button-9692e403.d.ts} +10 -11
  11. package/dist/Button-9692e403.d.ts.map +1 -0
  12. package/dist/{Button-da11d064.js → Button-9692e403.js} +65 -62
  13. package/dist/Button.d.ts +1 -1
  14. package/dist/Button.js +3 -3
  15. package/dist/ButtonGroup.d.ts +2 -2
  16. package/dist/ButtonGroup.d.ts.map +1 -1
  17. package/dist/ButtonGroup.js +3 -3
  18. package/dist/Checkbox.d.ts +4 -3
  19. package/dist/Checkbox.d.ts.map +1 -1
  20. package/dist/Checkbox.js +14 -19
  21. package/dist/CheckboxGroup.d.ts +2 -2
  22. package/dist/CheckboxGroup.d.ts.map +1 -1
  23. package/dist/CheckboxGroup.js +4 -6
  24. package/dist/Chip.d.ts +2 -2
  25. package/dist/Chip.d.ts.map +1 -1
  26. package/dist/Chip.js +6 -13
  27. package/dist/ChipGroup.d.ts +9 -7
  28. package/dist/ChipGroup.d.ts.map +1 -1
  29. package/dist/ChipGroup.js +8 -5
  30. package/dist/ChipLink.d.ts +2 -1
  31. package/dist/ChipLink.d.ts.map +1 -1
  32. package/dist/ChipLink.js +4 -7
  33. package/dist/ChipRemovable.d.ts +0 -2
  34. package/dist/ChipRemovable.d.ts.map +1 -1
  35. package/dist/ChipRemovable.js +8 -11
  36. package/dist/ChipSelectable.d.ts +9 -1
  37. package/dist/ChipSelectable.d.ts.map +1 -1
  38. package/dist/ChipSelectable.js +12 -16
  39. package/dist/Dropdown.d.ts +9 -5
  40. package/dist/Dropdown.d.ts.map +1 -1
  41. package/dist/Dropdown.js +73 -32
  42. package/dist/Icon.d.ts +20 -0
  43. package/dist/Icon.d.ts.map +1 -0
  44. package/dist/{icon-03e86700.js → Icon.js} +61 -32
  45. package/dist/Input.d.ts +7 -16
  46. package/dist/Input.d.ts.map +1 -1
  47. package/dist/Input.js +24 -28
  48. package/dist/LeuElement-6de6f209.d.ts +7 -0
  49. package/dist/LeuElement-6de6f209.d.ts.map +1 -0
  50. package/dist/LeuElement-6de6f209.js +43 -0
  51. package/dist/Menu.d.ts +24 -2
  52. package/dist/Menu.d.ts.map +1 -1
  53. package/dist/Menu.js +120 -3
  54. package/dist/MenuItem.d.ts +28 -11
  55. package/dist/MenuItem.d.ts.map +1 -1
  56. package/dist/MenuItem.js +110 -63
  57. package/dist/Pagination.d.ts +10 -3
  58. package/dist/Pagination.d.ts.map +1 -1
  59. package/dist/Pagination.js +24 -21
  60. package/dist/Popup.d.ts +21 -3
  61. package/dist/Popup.d.ts.map +1 -1
  62. package/dist/Popup.js +44 -19
  63. package/dist/Radio.d.ts +4 -2
  64. package/dist/Radio.d.ts.map +1 -1
  65. package/dist/Radio.js +9 -16
  66. package/dist/RadioGroup.d.ts +2 -2
  67. package/dist/RadioGroup.d.ts.map +1 -1
  68. package/dist/RadioGroup.js +4 -6
  69. package/dist/ScrollTop.d.ts +2 -2
  70. package/dist/ScrollTop.d.ts.map +1 -1
  71. package/dist/ScrollTop.js +10 -8
  72. package/dist/Select.d.ts +75 -37
  73. package/dist/Select.d.ts.map +1 -1
  74. package/dist/Select.js +279 -183
  75. package/dist/Table.d.ts +2 -6
  76. package/dist/Table.d.ts.map +1 -1
  77. package/dist/Table.js +17 -18
  78. package/dist/VisuallyHidden.d.ts +2 -2
  79. package/dist/VisuallyHidden.d.ts.map +1 -1
  80. package/dist/VisuallyHidden.js +5 -7
  81. package/dist/{index.js.d.ts → index.d.ts} +3 -3
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/{index.js.js → index.js} +5 -14
  84. package/dist/leu-accordion.d.ts.map +1 -1
  85. package/dist/leu-accordion.js +2 -3
  86. package/dist/leu-breadcrumb.d.ts.map +1 -1
  87. package/dist/leu-breadcrumb.js +4 -10
  88. package/dist/leu-button-group.d.ts.map +1 -1
  89. package/dist/leu-button-group.js +2 -3
  90. package/dist/leu-button.d.ts +1 -1
  91. package/dist/leu-button.d.ts.map +1 -1
  92. package/dist/leu-button.js +4 -5
  93. package/dist/leu-checkbox-group.d.ts.map +1 -1
  94. package/dist/leu-checkbox-group.js +2 -3
  95. package/dist/leu-checkbox.d.ts.map +1 -1
  96. package/dist/leu-checkbox.js +3 -4
  97. package/dist/leu-chip-group.d.ts.map +1 -1
  98. package/dist/leu-chip-group.js +2 -3
  99. package/dist/leu-chip-link.d.ts.map +1 -1
  100. package/dist/leu-chip-link.js +2 -3
  101. package/dist/leu-chip-removable.d.ts.map +1 -1
  102. package/dist/leu-chip-removable.js +3 -4
  103. package/dist/leu-chip-selectable.d.ts.map +1 -1
  104. package/dist/leu-chip-selectable.js +2 -3
  105. package/dist/leu-dropdown.d.ts.map +1 -1
  106. package/dist/leu-dropdown.js +5 -10
  107. package/dist/leu-icon.d.ts +3 -0
  108. package/dist/leu-icon.d.ts.map +1 -0
  109. package/dist/leu-icon.js +7 -0
  110. package/dist/leu-input.d.ts.map +1 -1
  111. package/dist/leu-input.js +3 -4
  112. package/dist/leu-menu-item.d.ts.map +1 -1
  113. package/dist/leu-menu-item.js +3 -5
  114. package/dist/leu-menu.d.ts.map +1 -1
  115. package/dist/leu-menu.js +5 -3
  116. package/dist/leu-pagination.d.ts.map +1 -1
  117. package/dist/leu-pagination.js +4 -7
  118. package/dist/leu-popup.d.ts.map +1 -1
  119. package/dist/leu-popup.js +2 -3
  120. package/dist/leu-radio-group.d.ts.map +1 -1
  121. package/dist/leu-radio-group.js +2 -3
  122. package/dist/leu-radio.d.ts.map +1 -1
  123. package/dist/leu-radio.js +2 -3
  124. package/dist/leu-scroll-top.d.ts.map +1 -1
  125. package/dist/leu-scroll-top.js +4 -6
  126. package/dist/leu-select.d.ts.map +1 -1
  127. package/dist/leu-select.js +5 -13
  128. package/dist/leu-table.d.ts.map +1 -1
  129. package/dist/leu-table.js +4 -8
  130. package/dist/leu-visually-hidden.d.ts.map +1 -1
  131. package/dist/leu-visually-hidden.js +2 -3
  132. package/dist/theme.css +2 -0
  133. package/dist/vscode.html-custom-data.json +616 -0
  134. package/dist/vue/index.d.ts +682 -0
  135. package/dist/web-types.json +1211 -0
  136. package/package.json +10 -13
  137. package/rollup.config.js +1 -1
  138. package/scripts/generate-component/templates/[Name].js +6 -3
  139. package/scripts/generate-component/templates/test/[name].test.js +1 -1
  140. package/src/components/accordion/Accordion.js +13 -10
  141. package/src/components/accordion/leu-accordion.js +1 -2
  142. package/src/components/breadcrumb/Breadcrumb.js +31 -18
  143. package/src/components/breadcrumb/leu-breadcrumb.js +1 -2
  144. package/src/components/button/Button.js +45 -71
  145. package/src/components/button/button.css +19 -4
  146. package/src/components/button/leu-button.js +1 -2
  147. package/src/components/button/stories/button.stories.js +60 -19
  148. package/src/components/button/test/button.test.js +26 -63
  149. package/src/components/button-group/ButtonGroup.js +4 -2
  150. package/src/components/button-group/leu-button-group.js +1 -2
  151. package/src/components/checkbox/Checkbox.js +17 -11
  152. package/src/components/checkbox/CheckboxGroup.js +6 -3
  153. package/src/components/checkbox/leu-checkbox-group.js +1 -2
  154. package/src/components/checkbox/leu-checkbox.js +1 -2
  155. package/src/components/checkbox/stories/checkbox-group.stories.js +10 -26
  156. package/src/components/checkbox/stories/checkbox.stories.js +2 -7
  157. package/src/components/checkbox/test/checkbox-group.test.js +6 -21
  158. package/src/components/checkbox/test/checkbox.test.js +1 -12
  159. package/src/components/chip/Chip.js +5 -4
  160. package/src/components/chip/ChipGroup.js +10 -4
  161. package/src/components/chip/ChipLink.js +3 -7
  162. package/src/components/chip/ChipRemovable.js +8 -11
  163. package/src/components/chip/ChipSelectable.js +11 -17
  164. package/src/components/chip/chip.css +3 -4
  165. package/src/components/chip/leu-chip-group.js +1 -2
  166. package/src/components/chip/leu-chip-link.js +1 -2
  167. package/src/components/chip/leu-chip-removable.js +1 -2
  168. package/src/components/chip/leu-chip-selectable.js +1 -2
  169. package/src/components/chip/stories/chip-link.stories.js +3 -5
  170. package/src/components/chip/stories/chip-removable.stories.js +3 -4
  171. package/src/components/chip/stories/chip-selectable.stories.js +2 -2
  172. package/src/components/chip/test/chip-group.test.js +15 -30
  173. package/src/components/chip/test/chip-link.test.js +2 -6
  174. package/src/components/chip/test/chip-removable.test.js +4 -10
  175. package/src/components/chip/test/chip-selectable.test.js +3 -5
  176. package/src/components/dropdown/Dropdown.js +80 -26
  177. package/src/components/dropdown/dropdown.css +4 -0
  178. package/src/components/dropdown/leu-dropdown.js +1 -2
  179. package/src/components/dropdown/stories/dropdown.stories.js +30 -7
  180. package/src/components/dropdown/test/dropdown.test.js +5 -5
  181. package/src/components/icon/Icon.js +55 -0
  182. package/src/components/icon/icon.css +6 -0
  183. package/src/components/icon/leu-icon.js +5 -0
  184. package/src/components/icon/{icon.js → paths.js} +4 -37
  185. package/src/components/icon/stories/icon.stories.js +47 -0
  186. package/src/components/icon/test/icon.test.js +23 -40
  187. package/src/components/input/Input.js +21 -23
  188. package/src/components/input/input.css +4 -2
  189. package/src/components/input/leu-input.js +1 -2
  190. package/src/components/input/stories/input.stories.js +2 -2
  191. package/src/components/input/test/input.test.js +2 -0
  192. package/src/components/menu/Menu.js +143 -2
  193. package/src/components/menu/MenuItem.js +104 -52
  194. package/src/components/menu/leu-menu-item.js +1 -2
  195. package/src/components/menu/leu-menu.js +1 -2
  196. package/src/components/menu/menu-item.css +11 -4
  197. package/src/components/menu/stories/menu-item.stories.js +15 -4
  198. package/src/components/menu/stories/menu.stories.js +34 -7
  199. package/src/components/menu/test/menu-item.test.js +88 -82
  200. package/src/components/menu/test/menu.test.js +101 -8
  201. package/src/components/pagination/Pagination.js +27 -18
  202. package/src/components/pagination/leu-pagination.js +1 -2
  203. package/src/components/popup/Popup.js +39 -16
  204. package/src/components/popup/leu-popup.js +1 -2
  205. package/src/components/popup/popup.css +1 -0
  206. package/src/components/radio/Radio.js +12 -7
  207. package/src/components/radio/RadioGroup.js +6 -3
  208. package/src/components/radio/leu-radio-group.js +1 -2
  209. package/src/components/radio/leu-radio.js +1 -2
  210. package/src/components/radio/stories/radio-group.stories.js +5 -19
  211. package/src/components/radio/stories/radio.stories.js +2 -7
  212. package/src/components/radio/test/radio-group.test.js +6 -9
  213. package/src/components/radio/test/radio.test.js +3 -13
  214. package/src/components/scroll-top/ScrollTop.js +15 -5
  215. package/src/components/scroll-top/leu-scroll-top.js +1 -2
  216. package/src/components/select/Select.js +279 -175
  217. package/src/components/select/leu-select.js +1 -2
  218. package/src/components/select/select.css +20 -12
  219. package/src/components/select/stories/select.stories.js +16 -2
  220. package/src/components/select/test/select.test.js +191 -37
  221. package/src/components/table/Table.js +15 -9
  222. package/src/components/table/leu-table.js +1 -2
  223. package/src/components/table/table.css +3 -1
  224. package/src/components/visually-hidden/VisuallyHidden.js +6 -2
  225. package/src/components/visually-hidden/leu-visually-hidden.js +1 -2
  226. package/src/lib/LeuElement.js +23 -0
  227. package/src/lib/a11y.js +26 -0
  228. package/src/styles/custom-properties.css +2 -0
  229. package/web-test-runner.config.mjs +2 -0
  230. package/dist/Button-da11d064.d.ts.map +0 -1
  231. package/dist/_rollupPluginBabelHelpers-20f659f4.d.ts +0 -3
  232. package/dist/_rollupPluginBabelHelpers-20f659f4.d.ts.map +0 -1
  233. package/dist/_rollupPluginBabelHelpers-20f659f4.js +0 -30
  234. package/dist/defineElement-40372b4b.d.ts +0 -9
  235. package/dist/defineElement-40372b4b.d.ts.map +0 -1
  236. package/dist/defineElement-40372b4b.js +0 -15
  237. package/dist/icon-03e86700.d.ts +0 -11
  238. package/dist/icon-03e86700.d.ts.map +0 -1
  239. package/dist/index.js.d.ts.map +0 -1
  240. package/src/lib/defineElement.js +0 -13
@@ -1,7 +1,7 @@
1
1
  import { html } from "lit"
2
2
 
3
3
  import { LeuChipBase } from "./Chip.js"
4
- import { Icon } from "../icon/icon.js"
4
+ import { LeuIcon } from "../icon/Icon.js"
5
5
 
6
6
  /**
7
7
  * @slot - The content of the chip
@@ -9,20 +9,17 @@ import { Icon } from "../icon/icon.js"
9
9
  * @fires remove - Dispatched when the user clicks on the chip
10
10
  */
11
11
  export class LeuChipRemovable extends LeuChipBase {
12
- static properties = {
13
- ...LeuChipBase.properties,
12
+ static dependencies = {
13
+ "leu-icon": LeuIcon,
14
14
  }
15
15
 
16
- constructor() {
17
- super()
18
-
19
- /** @internal */
20
- this._removeIcon = Icon("close", 16)
16
+ static properties = {
17
+ ...LeuChipBase.properties,
21
18
  }
22
19
 
23
20
  handleClick() {
24
21
  const customEvent = new CustomEvent("leu:remove", {
25
- bubble: true,
22
+ bubbles: true,
26
23
  composed: true,
27
24
  })
28
25
  this.dispatchEvent(customEvent)
@@ -30,8 +27,8 @@ export class LeuChipRemovable extends LeuChipBase {
30
27
 
31
28
  render() {
32
29
  return html`<button @click=${(e) => this.handleClick(e)} class="button">
33
- <span class="label">${this.label}</span>
34
- <div class="icon">${this._removeIcon}</div>
30
+ <span class="label"><slot></slot></span>
31
+ <leu-icon name="close" class="icon"></leu-icon>
35
32
  </button>`
36
33
  }
37
34
  }
@@ -14,28 +14,15 @@ export const VARIANTS = {
14
14
 
15
15
  /**
16
16
  * A chip component that can be selected.
17
- * @slot - The content of the chip
18
17
  * @tagname leu-chip-selectable
18
+ * @slot - The content of the chip
19
+ * @prop {keyof typeof SIZES} size - The size of the chip. Not supported for radio variant.
20
+ * @prop {keyof typeof VARIANTS} variant - `toggle` or `radio`. Determines if only one or multiple chips can be selected.
19
21
  */
20
22
  export class LeuChipSelectable extends LeuChipBase {
21
23
  static properties = {
22
24
  ...LeuChipBase.properties,
23
-
24
- /**
25
- * The size of the chip. Not supported for radio variant.
26
- * @type {keyof typeof SIZES}
27
- * @default "regular"
28
- */
29
25
  size: { type: String, reflect: true },
30
-
31
- /**
32
- * The variant of the chip. Has an effect not only on the visual appearance but also on the behavior.
33
- * - `toggle`: The chip behaves like a toggle button.
34
- * - `radio`: The chip behaves like a radio button.
35
- *
36
- * @type {keyof typeof VARIANTS}
37
- * @default "toggle"
38
- */
39
26
  variant: { type: String, reflect: true },
40
27
 
41
28
  selected: { type: Boolean, reflect: true },
@@ -45,6 +32,13 @@ export class LeuChipSelectable extends LeuChipBase {
45
32
  constructor() {
46
33
  super()
47
34
  this.size = SIZES.regular
35
+
36
+ /**
37
+ * The variant of the chip. Has an effect not only on the visual appearance but also on the behavior.
38
+ * - `toggle`: The chip behaves like a toggle button.
39
+ * - `radio`: The chip behaves like a radio button.
40
+ * @default "toggle"
41
+ */
48
42
  this.variant = VARIANTS.toggle
49
43
  this.selected = false
50
44
 
@@ -80,7 +74,7 @@ export class LeuChipSelectable extends LeuChipBase {
80
74
  class="button"
81
75
  aria-pressed=${this.selected ? "true" : "false"}
82
76
  >
83
- <span class="label">${this.label}</span>
77
+ <span class="label"><slot></slot></span>
84
78
  </button>`
85
79
  }
86
80
  }
@@ -28,6 +28,8 @@
28
28
  --chip-radio-border: var(--chip-radio-border-default);
29
29
  --chip-radio-background: var(--chip-radio-background-default);
30
30
 
31
+ --leu-icon-size: 1rem;
32
+
31
33
  font-family: var(--chip-font-regular);
32
34
 
33
35
  /* Allow shrinking to achieve text truncation (ellipsis) */
@@ -58,6 +60,7 @@
58
60
  padding: 0.5rem 1rem;
59
61
 
60
62
  color: var(--chip-color);
63
+ font-family: inherit;
61
64
  font-size: 0.875rem;
62
65
  line-height: 1rem;
63
66
 
@@ -135,7 +138,3 @@
135
138
  text-overflow: ellipsis;
136
139
  white-space: nowrap;
137
140
  }
138
-
139
- .icon svg {
140
- display: block;
141
- }
@@ -1,6 +1,5 @@
1
- import { defineElement } from "../../lib/defineElement.js"
2
1
  import { LeuChipGroup } from "./ChipGroup.js"
3
2
 
4
3
  export { LeuChipGroup }
5
4
 
6
- defineElement("chip-group", LeuChipGroup)
5
+ LeuChipGroup.define("leu-chip-group")
@@ -1,6 +1,5 @@
1
- import { defineElement } from "../../lib/defineElement.js"
2
1
  import { LeuChipLink } from "./ChipLink.js"
3
2
 
4
3
  export { LeuChipLink }
5
4
 
6
- defineElement("chip-link", LeuChipLink)
5
+ LeuChipLink.define("leu-chip-link")
@@ -1,6 +1,5 @@
1
- import { defineElement } from "../../lib/defineElement.js"
2
1
  import { LeuChipRemovable } from "./ChipRemovable.js"
3
2
 
4
3
  export { LeuChipRemovable }
5
4
 
6
- defineElement("chip-removable", LeuChipRemovable)
5
+ LeuChipRemovable.define("leu-chip-removable")
@@ -1,6 +1,5 @@
1
- import { defineElement } from "../../lib/defineElement.js"
2
1
  import { LeuChipSelectable } from "./ChipSelectable.js"
3
2
 
4
3
  export { LeuChipSelectable }
5
4
 
6
- defineElement("chip-selectable", LeuChipSelectable)
5
+ LeuChipSelectable.define("leu-chip-selectable")
@@ -33,11 +33,9 @@ function Template(args) {
33
33
  : "var(--leu-color-black-5)"}; padding: 1rem;"
34
34
  data-root
35
35
  >
36
- <leu-chip-link
37
- size=${ifDefined(args.size)}
38
- ?inverted=${args.inverted}
39
- label=${args.label}
40
- ></leu-chip-link>
36
+ <leu-chip-link size=${ifDefined(args.size)} ?inverted=${args.inverted}
37
+ >${args.label}</leu-chip-link
38
+ >
41
39
  </div>
42
40
  `
43
41
  }
@@ -27,10 +27,9 @@ function Template(args) {
27
27
  : "var(--leu-color-black-5)"}; padding: 1rem;"
28
28
  data-root
29
29
  >
30
- <leu-chip-removable
31
- ?inverted=${args.inverted}
32
- label=${args.label}
33
- ></leu-chip-removable>
30
+ <leu-chip-removable ?inverted=${args.inverted}
31
+ >${args.label}</leu-chip-removable
32
+ >
34
33
  </div>
35
34
  `
36
35
  }
@@ -38,10 +38,10 @@ function Template(args) {
38
38
  <leu-chip-selectable
39
39
  size=${ifDefined(args.size)}
40
40
  variant=${ifDefined(args.variant)}
41
- label=${args.label}
42
41
  ?selected=${args.selected}
43
42
  ?inverted=${args.inverted}
44
- ></leu-chip-selectable>
43
+ >${args.label}</leu-chip-selectable
44
+ >
45
45
  </div>
46
46
  `
47
47
  }
@@ -9,12 +9,9 @@ async function removableFixture() {
9
9
  return fixture(
10
10
  html`
11
11
  <leu-chip-group>
12
- <leu-chip-removable label="Publikationen"></leu-chip-removable>
13
- <leu-chip-removable label="Daten" value="2"></leu-chip-removable>
14
- <leu-chip-removable
15
- label="Schnittstellen"
16
- value="3"
17
- ></leu-chip-removable>
12
+ <leu-chip-removable>Publikationen</leu-chip-removable>
13
+ <leu-chip-removable value="2">Daten</leu-chip-removable>
14
+ <leu-chip-removable value="3">Schnittstellen</leu-chip-removable>
18
15
  </leu-chip-group>
19
16
  `
20
17
  )
@@ -24,21 +21,15 @@ async function singleSelectionFixture() {
24
21
  return fixture(
25
22
  html`
26
23
  <leu-chip-group selection-mode="single">
27
- <leu-chip-selectable
28
- label="Publikationen"
29
- value="1"
30
- variant="radio"
31
- ></leu-chip-selectable>
32
- <leu-chip-selectable
33
- label="Daten"
34
- value="2"
35
- variant="radio"
36
- ></leu-chip-selectable>
37
- <leu-chip-selectable
38
- label="Schnittstellen"
39
- value="3"
40
- variant="radio"
41
- ></leu-chip-selectable>
24
+ <leu-chip-selectable value="1" variant="radio"
25
+ >Publikationen</leu-chip-selectable
26
+ >
27
+ <leu-chip-selectable value="2" variant="radio"
28
+ >Daten</leu-chip-selectable
29
+ >
30
+ <leu-chip-selectable value="3" variant="radio"
31
+ >Schnittstellen</leu-chip-selectable
32
+ >
42
33
  </leu-chip-group>
43
34
  `
44
35
  )
@@ -48,15 +39,9 @@ async function multipleSelectionFixture() {
48
39
  return fixture(
49
40
  html`
50
41
  <leu-chip-group selection-mode="multiple">
51
- <leu-chip-selectable
52
- label="Publikationen"
53
- value="1"
54
- ></leu-chip-selectable>
55
- <leu-chip-selectable label="Daten" value="2"></leu-chip-selectable>
56
- <leu-chip-selectable
57
- label="Schnittstellen"
58
- value="3"
59
- ></leu-chip-selectable>
42
+ <leu-chip-selectable value="1">Publikationen</leu-chip-selectable>
43
+ <leu-chip-selectable value="2">Daten</leu-chip-selectable>
44
+ <leu-chip-selectable value="3">Schnittstellen</leu-chip-selectable>
60
45
  </leu-chip-group>
61
46
  `
62
47
  )
@@ -5,9 +5,7 @@ import "../leu-chip-link.js"
5
5
 
6
6
  async function defaultFixture() {
7
7
  return fixture(
8
- html`
9
- <leu-chip-link label="Daten" href="https://zh.ch/daten"></leu-chip-link>
10
- `
8
+ html` <leu-chip-link href="https://zh.ch/daten">Daten</leu-chip-link> `
11
9
  )
12
10
  }
13
11
 
@@ -27,9 +25,7 @@ describe("LeuChipLink", () => {
27
25
  it("renders the label", async () => {
28
26
  const el = await defaultFixture()
29
27
 
30
- const link = el.shadowRoot.querySelector("a")
31
-
32
- expect(link).to.have.trimmed.text("Daten")
28
+ expect(el).to.have.trimmed.text("Daten")
33
29
  })
34
30
 
35
31
  it("renders a link element", async () => {
@@ -2,14 +2,10 @@ import { html } from "lit"
2
2
  import { fixture, expect, oneEvent } from "@open-wc/testing"
3
3
  import { sendKeys } from "@web/test-runner-commands"
4
4
 
5
- import { iconPaths } from "../../icon/icon.js"
6
-
7
5
  import "../leu-chip-removable.js"
8
6
 
9
7
  async function defaultFixture() {
10
- return fixture(
11
- html` <leu-chip-removable label="Daten"></leu-chip-removable> `
12
- )
8
+ return fixture(html` <leu-chip-removable>Daten</leu-chip-removable> `)
13
9
  }
14
10
 
15
11
  describe("LeuChipRemovable", () => {
@@ -28,9 +24,7 @@ describe("LeuChipRemovable", () => {
28
24
  it("renders the label", async () => {
29
25
  const el = await defaultFixture()
30
26
 
31
- const button = el.shadowRoot.querySelector("button")
32
-
33
- expect(button).to.have.trimmed.text("Daten")
27
+ expect(el).to.have.trimmed.text("Daten")
34
28
  })
35
29
 
36
30
  it("renders a button element", async () => {
@@ -42,9 +36,9 @@ describe("LeuChipRemovable", () => {
42
36
  it("renders a remove icon", async () => {
43
37
  const el = await defaultFixture()
44
38
 
45
- const iconPath = el.shadowRoot.querySelector("svg path")
39
+ const iconPath = el.shadowRoot.querySelector("leu-icon")
46
40
 
47
- expect(iconPath.getAttribute("d")).to.equal(iconPaths.close)
41
+ expect(iconPath.name).to.equal("close")
48
42
  })
49
43
 
50
44
  it("delegates the focus to the button element", async () => {
@@ -9,11 +9,11 @@ async function defaultFixture(args = {}) {
9
9
  return fixture(
10
10
  html`
11
11
  <leu-chip-selectable
12
- label="Publikationen"
13
12
  value="Publikationen"
14
13
  variant=${ifDefined(args.variant)}
15
14
  ?selected=${args.selected}
16
- ></leu-chip-selectable>
15
+ >Publikationen</leu-chip-selectable
16
+ >
17
17
  `
18
18
  )
19
19
  }
@@ -34,9 +34,7 @@ describe("LeuChipSelectable", () => {
34
34
  it("renders the label", async () => {
35
35
  const el = await defaultFixture()
36
36
 
37
- const button = el.shadowRoot.querySelector("button")
38
-
39
- expect(button).to.have.trimmed.text("Publikationen")
37
+ expect(el).to.have.trimmed.text("Publikationen")
40
38
  })
41
39
 
42
40
  it("renders a button element", async () => {
@@ -1,15 +1,28 @@
1
- import { html, LitElement } from "lit"
2
- import styles from "./dropdown.css"
1
+ import { html, nothing } from "lit"
2
+ import { createRef, ref } from "lit/directives/ref.js"
3
+
4
+ import { LeuElement } from "../../lib/LeuElement.js"
5
+ import { HasSlotController } from "../../lib/hasSlotController.js"
6
+
7
+ import { LeuButton } from "../button/Button.js"
8
+ import { LeuMenu } from "../menu/Menu.js"
9
+ import { LeuMenuItem } from "../menu/MenuItem.js"
10
+ import { LeuPopup } from "../popup/Popup.js"
3
11
 
4
- import "../button/leu-button.js"
5
- import "../menu/leu-menu.js"
6
- import "../menu/leu-menu-item.js"
7
- import "../popup/leu-popup.js"
12
+ // @ts-ignore
13
+ import styles from "./dropdown.css"
8
14
 
9
15
  /**
10
16
  * @tagname leu-dropdown
11
17
  */
12
- export class LeuDropdown extends LitElement {
18
+ export class LeuDropdown extends LeuElement {
19
+ static dependencies = {
20
+ "leu-button": LeuButton,
21
+ "leu-menu": LeuMenu,
22
+ "leu-menu-item": LeuMenuItem,
23
+ "leu-popup": LeuPopup,
24
+ }
25
+
13
26
  static styles = styles
14
27
 
15
28
  static properties = {
@@ -17,25 +30,38 @@ export class LeuDropdown extends LitElement {
17
30
  expanded: { type: Boolean, reflect: true },
18
31
  }
19
32
 
33
+ hasSlotController = new HasSlotController(this, ["icon"])
34
+
20
35
  constructor() {
21
36
  super()
22
37
 
23
38
  this.label = ""
24
39
  this.expanded = false
25
- this.menuItems = []
40
+
41
+ /** @type {import("lit/directives/ref").Ref<HTMLButtonElement>} */
42
+ this._toggleRef = createRef()
26
43
  }
27
44
 
28
45
  connectedCallback() {
29
46
  super.connectedCallback()
30
47
  this.addEventListener("keyup", this._keyUpHandler)
31
48
  document.addEventListener("click", this._documentClickHandler)
49
+
50
+ const menu = this._getMenu()
51
+
52
+ menu.addEventListener("keydown", this._keyDownMenuHandler)
53
+ menu.addEventListener("click", this._menuItemClickHandler)
32
54
  }
33
55
 
34
56
  disconnectedCallback() {
35
57
  super.disconnectedCallback()
36
- this._removeMenuItemListeners()
37
58
  this.removeEventListener("keyup", this._keyUpHandler)
38
59
  document.removeEventListener("click", this._documentClickHandler)
60
+
61
+ const menu = this._getMenu()
62
+
63
+ menu.removeEventListener("keydown", this._keyDownMenuHandler)
64
+ menu.removeEventListener("click", this._menuItemClickHandler)
39
65
  }
40
66
 
41
67
  _documentClickHandler = (event) => {
@@ -50,30 +76,56 @@ export class LeuDropdown extends LitElement {
50
76
  }
51
77
  }
52
78
 
53
- _handleSlotChange() {
54
- this._removeMenuItemListeners()
55
- this.menuItems = [...this.querySelectorAll("leu-menu > leu-menu-item")]
79
+ async _keyDownToggleHandler(event) {
80
+ if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
81
+ event.preventDefault()
82
+ const menu = this._getMenu()
56
83
 
57
- this.menuItems.forEach((item) =>
58
- item.addEventListener("click", this._handleMenuItemClick)
59
- )
84
+ this.expanded = true
85
+
86
+ await this.updateComplete
87
+
88
+ if (event.key === "ArrowDown" || event.key === "Home") {
89
+ menu.focusItem(0)
90
+ } else if (event.key === "ArrowUp" || event.key === "End") {
91
+ menu.focusItem(-1)
92
+ }
93
+ }
60
94
  }
61
95
 
62
- _removeMenuItemListeners() {
63
- this.menuItems.forEach((item) => {
64
- item.removeEventListener("click", this._handleMenuItemClick)
65
- })
96
+ _menuItemClickHandler = (e) => {
97
+ if (e.target.tagName.toLowerCase() === "leu-menu-item") {
98
+ this.expanded = false
99
+ this._toggleRef.value.focus()
100
+ }
66
101
  }
67
102
 
68
- _handleMenuItemClick = () => {
69
- this.expanded = false
103
+ /**
104
+ * Close the dropdown when the user presses the Escape or the Tab key.
105
+ * Navigating the menu with the arrow keys is handled by the menu itself.
106
+ * @param {KeyboardEvent} e
107
+ */
108
+ _keyDownMenuHandler = (e) => {
109
+ if (e.key === "Escape" || e.key === "Tab") {
110
+ e.preventDefault()
111
+ this.expanded = false
112
+ this._toggleRef.value.focus()
113
+ }
70
114
  }
71
115
 
72
116
  _handleToggleClick() {
73
117
  this.expanded = !this.expanded
74
118
  }
75
119
 
120
+ /**
121
+ * @returns {import("../menu/Menu").LeuMenu}
122
+ */
123
+ _getMenu() {
124
+ return this.querySelector("leu-menu")
125
+ }
126
+
76
127
  render() {
128
+ const hasIcon = this.hasSlotController.test("icon")
77
129
  return html`
78
130
  <leu-popup
79
131
  ?active=${this.expanded}
@@ -84,18 +136,20 @@ export class LeuDropdown extends LitElement {
84
136
  autoSizePadding="8"
85
137
  >
86
138
  <leu-button
139
+ ref=${ref(this._toggleRef)}
140
+ class="button"
87
141
  slot="anchor"
88
- icon="download"
89
142
  variant="ghost"
90
143
  expanded=${this.expanded ? "true" : "false"}
91
- aria-expanded=${this.expanded ? "true" : "false"}
92
- aria-controls="content"
93
144
  ?active=${this.expanded}
94
145
  @click=${this._handleToggleClick}
95
- >${this.label}</leu-button
146
+ @keydown=${this._keyDownToggleHandler}
147
+ >
148
+ ${hasIcon ? html`<slot name="icon" slot="before"></slot>` : nothing}
149
+ ${this.label}</leu-button
96
150
  >
97
151
  <div id="content" class="content" ?hidden=${!this.expanded}>
98
- <slot @slotchange=${this._handleSlotChange}></slot>
152
+ <slot></slot>
99
153
  </div>
100
154
  </leu-popup>
101
155
  `
@@ -14,3 +14,7 @@
14
14
 
15
15
  margin-top: 0.5rem;
16
16
  }
17
+
18
+ .button {
19
+ max-width: 100%;
20
+ }
@@ -1,6 +1,5 @@
1
- import { defineElement } from "../../lib/defineElement.js"
2
1
  import { LeuDropdown } from "./Dropdown.js"
3
2
 
4
3
  export { LeuDropdown }
5
4
 
6
- defineElement("dropdown", LeuDropdown)
5
+ LeuDropdown.define("leu-dropdown")
@@ -1,6 +1,12 @@
1
- import { html } from "lit"
1
+ import { html, nothing } from "lit"
2
2
  import "../leu-dropdown.js"
3
+ import "../../icon/leu-icon.js"
3
4
 
5
+ import { paths as iconPaths } from "../../icon/paths.js"
6
+
7
+ /**
8
+ * @type {import("@storybook/web-components").Meta}
9
+ */
4
10
  export default {
5
11
  title: "Dropdown",
6
12
  component: "leu-dropdown",
@@ -10,17 +16,28 @@ export default {
10
16
  url: "https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=136815-217650&mode=design&t=lzVrtq8lxYVJU5TB-11",
11
17
  },
12
18
  },
19
+ argTypes: {
20
+ icon: {
21
+ control: "select",
22
+ options: Object.keys(iconPaths),
23
+ },
24
+ },
13
25
  }
14
26
 
15
- function Template({ label, expanded }) {
27
+ function Template({ label, expanded, icon }) {
16
28
  return html` <leu-dropdown label=${label} ?expanded=${expanded}>
29
+ ${icon ? html`<leu-icon name=${icon} slot="icon"></leu-icon>` : nothing}
17
30
  <leu-menu>
18
- <leu-menu-item label="Als CSV Tabelle"></leu-menu-item>
19
- <leu-menu-item label="Als XLS Tabelle"></leu-menu-item>
31
+ <leu-menu-item
32
+ href="https://www.web.statistik.zh.ch/ogd/daten/ressourcen/KTZH_00001120_00002165.csv"
33
+ >OGD Ressource</leu-menu-item
34
+ >
35
+ <leu-menu-item>Als CSV Tabelle</leu-menu-item>
36
+ <leu-menu-item>Als XLS Tabelle</leu-menu-item>
20
37
  <hr />
21
- <leu-menu-item label="Als PNG exportieren"></leu-menu-item>
22
- <leu-menu-item label="Als SVG exportieren"></leu-menu-item>
23
- <leu-menu-item label="Als PDF exportieren" disabled></leu-menu-item>
38
+ <leu-menu-item>Als PNG exportieren</leu-menu-item>
39
+ <leu-menu-item>Als SVG exportieren</leu-menu-item>
40
+ <leu-menu-item disabled>Als PDF exportieren</leu-menu-item>
24
41
  </leu-menu>
25
42
  </leu-dropdown>`
26
43
  }
@@ -28,4 +45,10 @@ function Template({ label, expanded }) {
28
45
  export const Regular = Template.bind({})
29
46
  Regular.args = {
30
47
  label: "Download",
48
+ icon: "download",
49
+ }
50
+
51
+ export const WithoutIcon = Template.bind({})
52
+ WithoutIcon.args = {
53
+ label: "Download",
31
54
  }
@@ -6,12 +6,12 @@ import "../leu-dropdown.js"
6
6
  async function defaultFixture() {
7
7
  return fixture(html` <leu-dropdown label="Download">
8
8
  <leu-menu>
9
- <leu-menu-item label="Als CSV Tabelle"></leu-menu-item>
10
- <leu-menu-item label="Als XLS Tabelle"></leu-menu-item>
9
+ <leu-menu-item>Als CSV Tabelle</leu-menu-item>
10
+ <leu-menu-item>Als XLS Tabelle</leu-menu-item>
11
11
  <hr />
12
- <leu-menu-item label="Als PNG exportieren"></leu-menu-item>
13
- <leu-menu-item label="Als SVG exportieren"></leu-menu-item>
14
- <leu-menu-item label="Als PDF exportieren"></leu-menu-item>
12
+ <leu-menu-item>Als PNG exportieren</leu-menu-item>
13
+ <leu-menu-item>Als SVG exportieren</leu-menu-item>
14
+ <leu-menu-item>Als PDF exportieren</leu-menu-item>
15
15
  </leu-menu>
16
16
  </leu-dropdown>`)
17
17
  }