@statistikzh/leu 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/.storybook/preview.js +1 -2
  2. package/CHANGELOG.md +32 -0
  3. package/custom-elements-manifest.config.js +46 -0
  4. package/dist/Accordion.d.ts +31 -0
  5. package/dist/Accordion.d.ts.map +1 -0
  6. package/dist/Accordion.js +257 -0
  7. package/dist/Breadcrumb.d.ts +69 -0
  8. package/dist/Breadcrumb.d.ts.map +1 -0
  9. package/dist/Breadcrumb.js +392 -0
  10. package/dist/Button-5326c982.d.ts +84 -0
  11. package/dist/Button-5326c982.d.ts.map +1 -0
  12. package/dist/Button-5326c982.js +555 -0
  13. package/dist/Button.d.ts +2 -0
  14. package/dist/Button.d.ts.map +1 -0
  15. package/dist/Button.js +6 -420
  16. package/dist/ButtonGroup.d.ts +24 -0
  17. package/dist/ButtonGroup.d.ts.map +1 -0
  18. package/dist/ButtonGroup.js +70 -39
  19. package/dist/Checkbox.d.ts +13 -0
  20. package/dist/Checkbox.d.ts.map +1 -0
  21. package/dist/Checkbox.js +2 -2
  22. package/dist/CheckboxGroup.d.ts +13 -0
  23. package/dist/CheckboxGroup.d.ts.map +1 -0
  24. package/dist/CheckboxGroup.js +3 -3
  25. package/dist/Chip.d.ts +5 -0
  26. package/dist/Chip.d.ts.map +1 -0
  27. package/dist/{Chip-dac7337d.js → Chip.js} +16 -5
  28. package/dist/ChipGroup.d.ts +28 -0
  29. package/dist/ChipGroup.d.ts.map +1 -0
  30. package/dist/ChipGroup.js +62 -5
  31. package/dist/ChipLink.d.ts +15 -0
  32. package/dist/ChipLink.d.ts.map +1 -0
  33. package/dist/ChipLink.js +1 -1
  34. package/dist/ChipRemovable.d.ts +13 -0
  35. package/dist/ChipRemovable.d.ts.map +1 -0
  36. package/dist/ChipRemovable.js +2 -2
  37. package/dist/ChipSelectable.d.ts +22 -0
  38. package/dist/ChipSelectable.d.ts.map +1 -0
  39. package/dist/ChipSelectable.js +5 -5
  40. package/dist/Dropdown.d.ts +15 -0
  41. package/dist/Dropdown.d.ts.map +1 -0
  42. package/dist/Dropdown.js +30 -7
  43. package/dist/Input.d.ts +154 -0
  44. package/dist/Input.d.ts.map +1 -0
  45. package/dist/Input.js +13 -7
  46. package/dist/Menu.d.ts +8 -0
  47. package/dist/Menu.d.ts.map +1 -0
  48. package/dist/MenuItem.d.ts +21 -0
  49. package/dist/MenuItem.d.ts.map +1 -0
  50. package/dist/MenuItem.js +3 -3
  51. package/dist/Pagination.d.ts +27 -0
  52. package/dist/Pagination.d.ts.map +1 -0
  53. package/dist/Pagination.js +93 -61
  54. package/dist/Popup.d.ts +18 -0
  55. package/dist/Popup.d.ts.map +1 -0
  56. package/dist/{leu-popup-4bf6f1f4.js → Popup.js} +4 -5
  57. package/dist/Radio.d.ts +12 -0
  58. package/dist/Radio.d.ts.map +1 -0
  59. package/dist/Radio.js +2 -2
  60. package/dist/RadioGroup.d.ts +20 -0
  61. package/dist/RadioGroup.d.ts.map +1 -0
  62. package/dist/RadioGroup.js +3 -3
  63. package/dist/ScrollTop.d.ts +19 -0
  64. package/dist/ScrollTop.d.ts.map +1 -0
  65. package/dist/ScrollTop.js +122 -0
  66. package/dist/Select.d.ts +98 -0
  67. package/dist/Select.d.ts.map +1 -0
  68. package/dist/Select.js +27 -82
  69. package/dist/Table.d.ts +48 -0
  70. package/dist/Table.d.ts.map +1 -0
  71. package/dist/Table.js +7 -4
  72. package/dist/VisuallyHidden.d.ts +8 -0
  73. package/dist/VisuallyHidden.d.ts.map +1 -0
  74. package/dist/VisuallyHidden.js +28 -0
  75. package/dist/_rollupPluginBabelHelpers-20f659f4.d.ts +3 -0
  76. package/dist/_rollupPluginBabelHelpers-20f659f4.d.ts.map +1 -0
  77. package/dist/defineElement-40372b4b.d.ts +9 -0
  78. package/dist/defineElement-40372b4b.d.ts.map +1 -0
  79. package/dist/{defineElement-47d4f665.js → defineElement-40372b4b.js} +1 -1
  80. package/dist/icon-03e86700.d.ts +11 -0
  81. package/dist/icon-03e86700.d.ts.map +1 -0
  82. package/dist/index.d.ts +21 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +14 -8
  85. package/dist/leu-accordion.d.ts +3 -0
  86. package/dist/leu-accordion.d.ts.map +1 -0
  87. package/dist/leu-accordion.js +9 -0
  88. package/dist/leu-breadcrumb.d.ts +3 -0
  89. package/dist/leu-breadcrumb.d.ts.map +1 -0
  90. package/dist/leu-breadcrumb.js +23 -0
  91. package/dist/leu-button-group.d.ts +3 -0
  92. package/dist/leu-button-group.d.ts.map +1 -0
  93. package/dist/leu-button-group.js +1 -5
  94. package/dist/leu-button.d.ts +3 -0
  95. package/dist/leu-button.d.ts.map +1 -0
  96. package/dist/leu-button.js +3 -2
  97. package/dist/leu-checkbox-group.d.ts +3 -0
  98. package/dist/leu-checkbox-group.d.ts.map +1 -0
  99. package/dist/leu-checkbox-group.js +1 -1
  100. package/dist/leu-checkbox.d.ts +3 -0
  101. package/dist/leu-checkbox.d.ts.map +1 -0
  102. package/dist/leu-checkbox.js +1 -1
  103. package/dist/leu-chip-group.d.ts +3 -0
  104. package/dist/leu-chip-group.d.ts.map +1 -0
  105. package/dist/leu-chip-group.js +2 -1
  106. package/dist/leu-chip-link.d.ts +3 -0
  107. package/dist/leu-chip-link.d.ts.map +1 -0
  108. package/dist/leu-chip-link.js +2 -2
  109. package/dist/leu-chip-removable.d.ts +3 -0
  110. package/dist/leu-chip-removable.d.ts.map +1 -0
  111. package/dist/leu-chip-removable.js +2 -2
  112. package/dist/leu-chip-selectable.d.ts +3 -0
  113. package/dist/leu-chip-selectable.d.ts.map +1 -0
  114. package/dist/leu-chip-selectable.js +2 -2
  115. package/dist/leu-dropdown.d.ts +3 -0
  116. package/dist/leu-dropdown.d.ts.map +1 -0
  117. package/dist/leu-dropdown.js +5 -4
  118. package/dist/leu-input.d.ts +3 -0
  119. package/dist/leu-input.d.ts.map +1 -0
  120. package/dist/leu-input.js +1 -1
  121. package/dist/leu-menu-item.d.ts +3 -0
  122. package/dist/leu-menu-item.d.ts.map +1 -0
  123. package/dist/leu-menu-item.js +1 -1
  124. package/dist/leu-menu.d.ts +3 -0
  125. package/dist/leu-menu.d.ts.map +1 -0
  126. package/dist/leu-menu.js +1 -1
  127. package/dist/leu-pagination.d.ts +3 -0
  128. package/dist/leu-pagination.d.ts.map +1 -0
  129. package/dist/leu-pagination.js +5 -2
  130. package/dist/leu-popup.d.ts +3 -0
  131. package/dist/leu-popup.d.ts.map +1 -0
  132. package/dist/leu-popup.js +9 -0
  133. package/dist/leu-radio-group.d.ts +3 -0
  134. package/dist/leu-radio-group.d.ts.map +1 -0
  135. package/dist/leu-radio-group.js +1 -1
  136. package/dist/leu-radio.d.ts +3 -0
  137. package/dist/leu-radio.d.ts.map +1 -0
  138. package/dist/leu-radio.js +1 -1
  139. package/dist/leu-scroll-top.d.ts +3 -0
  140. package/dist/leu-scroll-top.d.ts.map +1 -0
  141. package/dist/leu-scroll-top.js +14 -0
  142. package/dist/leu-select.d.ts +3 -0
  143. package/dist/leu-select.d.ts.map +1 -0
  144. package/dist/leu-select.js +4 -3
  145. package/dist/leu-table.d.ts +3 -0
  146. package/dist/leu-table.d.ts.map +1 -0
  147. package/dist/leu-table.js +5 -2
  148. package/dist/leu-visually-hidden.d.ts +3 -0
  149. package/dist/leu-visually-hidden.d.ts.map +1 -0
  150. package/dist/leu-visually-hidden.js +8 -0
  151. package/dist/theme.css +386 -2
  152. package/dist/utils-65469421.d.ts +16 -0
  153. package/dist/utils-65469421.d.ts.map +1 -0
  154. package/dist/utils-65469421.js +35 -0
  155. package/dist/vscode.html-custom-data.json +579 -0
  156. package/dist/vue/index.d.ts +678 -0
  157. package/dist/web-types.json +1076 -0
  158. package/index.js +3 -0
  159. package/package.json +30 -12
  160. package/postcss.config.cjs +2 -0
  161. package/rollup.config.js +21 -40
  162. package/scripts/generate-component/templates/[name].css +2 -2
  163. package/scripts/postcss-leu-font-styles.cjs +160 -0
  164. package/src/components/accordion/accordion.css +2 -2
  165. package/src/components/accordion/stories/accordion.stories.js +2 -1
  166. package/src/components/accordion/test/accordion.test.js +4 -2
  167. package/src/components/breadcrumb/Breadcrumb.js +2 -1
  168. package/src/components/breadcrumb/breadcrumb.css +2 -13
  169. package/src/components/button/Button.js +69 -8
  170. package/src/components/button/button.css +23 -2
  171. package/src/components/button/stories/button.stories.js +43 -90
  172. package/src/components/button/test/button.test.js +90 -19
  173. package/src/components/button-group/ButtonGroup.js +76 -34
  174. package/src/components/button-group/stories/button-group.stories.js +13 -6
  175. package/src/components/button-group/test/button-group.test.js +38 -31
  176. package/src/components/checkbox/checkbox-group.css +2 -2
  177. package/src/components/checkbox/checkbox.css +1 -1
  178. package/src/components/chip/ChipGroup.js +42 -2
  179. package/src/components/chip/ChipRemovable.js +1 -1
  180. package/src/components/chip/ChipSelectable.js +4 -4
  181. package/src/components/chip/chip-group.css +12 -2
  182. package/src/components/chip/chip.css +14 -3
  183. package/src/components/chip/stories/chip-group.stories.js +100 -46
  184. package/src/components/chip/test/chip-removable.test.js +3 -3
  185. package/src/components/dropdown/Dropdown.js +24 -3
  186. package/src/components/dropdown/dropdown.css +4 -0
  187. package/src/components/input/Input.js +7 -4
  188. package/src/components/input/input.css +2 -2
  189. package/src/components/input/stories/input.stories.js +13 -0
  190. package/src/components/input/test/input.test.js +1 -0
  191. package/src/components/menu/menu-item.css +3 -3
  192. package/src/components/pagination/Pagination.js +91 -60
  193. package/src/components/pagination/pagination.css +6 -1
  194. package/src/components/pagination/stories/pagination.stories.js +15 -2
  195. package/src/components/pagination/test/pagination.test.js +15 -15
  196. package/src/components/popup/popup.css +2 -2
  197. package/src/components/popup/stories/popup.stories.js +1 -1
  198. package/src/components/radio/radio-group.css +2 -2
  199. package/src/components/radio/radio.css +1 -1
  200. package/src/components/scroll-top/ScrollTop.js +87 -0
  201. package/src/components/scroll-top/leu-scroll-top.js +6 -0
  202. package/src/components/scroll-top/scroll-top.css +34 -0
  203. package/src/components/scroll-top/stories/scroll-top.stories.js +217 -0
  204. package/src/components/scroll-top/test/scroll-top.test.js +22 -0
  205. package/src/components/select/Select.js +24 -6
  206. package/src/components/select/select.css +2 -2
  207. package/src/components/table/table.css +2 -2
  208. package/src/components/visually-hidden/VisuallyHidden.js +13 -0
  209. package/src/components/visually-hidden/leu-visually-hidden.js +6 -0
  210. package/src/components/visually-hidden/stories/visually-hidden.stories.js +22 -0
  211. package/src/components/visually-hidden/test/visually-hidden.test.js +36 -0
  212. package/src/components/visually-hidden/visually-hidden.css +10 -0
  213. package/src/lib/defineElement.js +1 -1
  214. package/src/lib/hasSlotController.js +5 -3
  215. package/src/lib/utils.js +21 -3
  216. package/src/styles/custom-properties.css +6 -2
  217. package/src/styles/font-definitions.json +202 -0
  218. package/stylelint.config.mjs +2 -0
  219. package/tsconfig.build.json +21 -0
  220. package/tsconfig.json +16 -0
@@ -1,12 +1,23 @@
1
1
  import { html } from "lit"
2
- import { fixture, expect, oneEvent, elementUpdated } from "@open-wc/testing"
2
+ import {
3
+ fixture,
4
+ expect,
5
+ oneEvent,
6
+ elementUpdated,
7
+ aTimeout,
8
+ } from "@open-wc/testing"
3
9
 
4
10
  import "../leu-button-group.js"
5
-
6
- const items = ["Eins", "Zwei", "Drei"]
11
+ import "../../button/leu-button.js"
7
12
 
8
13
  async function defaultFixture() {
9
- return fixture(html` <leu-button-group .items=${items}></leu-button-group> `)
14
+ return fixture(html`
15
+ <leu-button-group>
16
+ <leu-button variant="secondary" value="Eins">Eins</leu-button>
17
+ <leu-button variant="secondary" value="Zweierlei">Zwei</leu-button>
18
+ <leu-button variant="secondary">Drei</leu-button>
19
+ </leu-button-group>
20
+ `)
10
21
  }
11
22
 
12
23
  describe("LeuButtonGroup", () => {
@@ -19,7 +30,7 @@ describe("LeuButtonGroup", () => {
19
30
  it("passes the a11y audit", async () => {
20
31
  const el = await defaultFixture()
21
32
 
22
- await expect(el).shadowDom.to.be.accessible()
33
+ await expect(el).to.be.accessible()
23
34
  })
24
35
 
25
36
  it("has no value by default", async () => {
@@ -31,32 +42,36 @@ describe("LeuButtonGroup", () => {
31
42
  it("has the correct value after clicking a button", async () => {
32
43
  const el = await defaultFixture()
33
44
 
34
- const buttons = el.shadowRoot.querySelectorAll("leu-button")
45
+ const buttons = Array.from(el.querySelectorAll("leu-button"))
35
46
 
36
- buttons[1].click()
37
- await expect(el.value).to.equal("Zwei")
47
+ setTimeout(() => buttons[1].click())
48
+ await oneEvent(el, "input")
49
+ await expect(el.value).to.equal("Zweierlei")
38
50
 
39
- buttons[0].click()
51
+ setTimeout(() => buttons[0].click())
52
+ await oneEvent(el, "input")
40
53
  await expect(el.value).to.equal("Eins")
41
54
 
42
- buttons[2].click()
55
+ setTimeout(() => buttons[2].click())
56
+ await oneEvent(el, "input")
43
57
  await expect(el.value).to.equal("Drei")
44
58
 
45
59
  // Should not change after clicking the same button again
46
- buttons[2].click()
60
+ setTimeout(() => buttons[2].click())
61
+ await aTimeout(100) // There is no event to wait for so
47
62
  await expect(el.value).to.equal("Drei")
48
63
  })
49
64
 
50
- it("renders the active button as a primary button", async () => {
65
+ it("sets the active attribute on the active button", async () => {
51
66
  const el = await defaultFixture()
52
- el.value = "Zwei"
67
+ el.value = "Zweierlei"
53
68
  await elementUpdated(el)
54
69
 
55
- const buttons = el.shadowRoot.querySelectorAll("leu-button")
70
+ const buttons = el.querySelectorAll("leu-button")
56
71
 
57
- await expect(buttons[0].variant).to.equal("secondary")
58
- await expect(buttons[1].variant).to.equal("primary")
59
- await expect(buttons[2].variant).to.equal("secondary")
72
+ await expect(buttons[0].active).to.be.false
73
+ await expect(buttons[1].active).to.be.true
74
+ await expect(buttons[2].active).to.be.false
60
75
 
61
76
  buttons[0].click()
62
77
 
@@ -65,21 +80,13 @@ describe("LeuButtonGroup", () => {
65
80
  await expect(buttons[2].variant).to.equal("secondary")
66
81
  })
67
82
 
68
- it("sets the correct aria-checked attribute", async () => {
83
+ it("sets the menuitemradio role on the buttons", async () => {
69
84
  const el = await defaultFixture()
70
- el.value = "Drei"
71
- await elementUpdated(el)
72
-
73
- const buttons = el.shadowRoot.querySelectorAll("leu-button")
85
+ const buttons = el.querySelectorAll("leu-button")
74
86
 
75
- await expect(buttons[0].getAttribute("aria-checked")).to.equal("false")
76
- await expect(buttons[1].getAttribute("aria-checked")).to.equal("false")
77
- await expect(buttons[2].getAttribute("aria-checked")).to.equal("true")
78
-
79
- buttons[0].click()
80
- await expect(buttons[0].getAttribute("aria-checked")).to.equal("false")
81
- await expect(buttons[1].getAttribute("aria-checked")).to.equal("false")
82
- await expect(buttons[2].getAttribute("aria-checked")).to.equal("false")
87
+ await expect(buttons[0].componentRole).to.equal("menuitemradio")
88
+ await expect(buttons[1].componentRole).to.equal("menuitemradio")
89
+ await expect(buttons[2].componentRole).to.equal("menuitemradio")
83
90
  })
84
91
 
85
92
  it("dispatches an input event when the value changes", async () => {
@@ -87,7 +94,7 @@ describe("LeuButtonGroup", () => {
87
94
  el.value = "Drei"
88
95
  await elementUpdated(el)
89
96
 
90
- const buttons = el.shadowRoot.querySelectorAll("leu-button")
97
+ const buttons = el.querySelectorAll("leu-button")
91
98
 
92
99
  setTimeout(() => buttons[0].click())
93
100
 
@@ -1,6 +1,6 @@
1
1
  :host {
2
- --group-font-regular: var(--leu-font-regular);
3
- --group-font-black: var(--leu-font-black);
2
+ --group-font-regular: var(--leu-font-family-regular);
3
+ --group-font-black: var(--leu-font-family-black);
4
4
 
5
5
  font-family: var(--group-font-regular);
6
6
  }
@@ -8,7 +8,7 @@
8
8
 
9
9
  --checkbox-tick-color: var(--leu-color-black-0);
10
10
 
11
- --checkbox-font-regular: var(--leu-font-regular);
11
+ --checkbox-font-regular: var(--leu-font-family-regular);
12
12
 
13
13
  position: relative;
14
14
 
@@ -1,4 +1,5 @@
1
- import { LitElement, html } from "lit"
1
+ import { LitElement } from "lit"
2
+ import { html, unsafeStatic } from "lit/static-html.js"
2
3
  import styles from "./chip-group.css"
3
4
 
4
5
  /* Figma https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=131766-248643&mode=design&t=Kjo5VDiqivihn8dh-11 */
@@ -11,18 +12,26 @@ export const SELECTION_MODES = {
11
12
 
12
13
  /**
13
14
  * @slot - Place leu-chip-* elements inside this slot
15
+ * @cssproperty --leu-chip-group-gap - The gap between the chips
14
16
  * @tagname leu-chip-group
15
17
  */
16
18
  export class LeuChipGroup extends LitElement {
17
19
  static styles = styles
18
20
 
19
21
  static properties = {
22
+ inverted: { type: Boolean, reflect: true },
20
23
  selectionMode: { type: String, attribute: "selection-mode", reflect: true },
24
+ headingLevel: { type: Number, attribute: "heading-level", reflect: true },
25
+ label: { type: String, reflect: true },
21
26
  }
22
27
 
23
28
  constructor() {
24
29
  super()
25
30
 
31
+ this.inverted = false
32
+ this.headingLevel = 2
33
+ this.label = ""
34
+
26
35
  /** @internal */
27
36
  this.items = []
28
37
  }
@@ -43,6 +52,22 @@ export class LeuChipGroup extends LitElement {
43
52
  return this.items.filter((i) => i.selected).map((i) => i.value)
44
53
  }
45
54
 
55
+ /**
56
+ * Determines the heading tag of the accordion toggle.
57
+ * The headingLevel shouldn't be used directly to render the heading tag
58
+ * in order to avoid XSS issues.
59
+ * @returns {String} The heading tag of the accordion toggle.
60
+ * @internal
61
+ */
62
+ _getHeadingTag() {
63
+ let level = 2
64
+ if (this.headingLevel > 0 && this.headingLevel < 7) {
65
+ level = this.headingLevel
66
+ }
67
+
68
+ return `h${level}`
69
+ }
70
+
46
71
  /** @internal */
47
72
  handleInput = (e) => {
48
73
  if (this.selectionMode === SELECTION_MODES.single) {
@@ -61,6 +86,21 @@ export class LeuChipGroup extends LitElement {
61
86
  }
62
87
 
63
88
  render() {
64
- return html`<slot @slotchange=${this.handleSlotChange}></slot>`
89
+ const hTag = this._getHeadingTag()
90
+
91
+ /* The eslint rules don't recognize html import from lit/static-html.js */
92
+ /* eslint-disable lit/binding-positions, lit/no-invalid-html */
93
+ return html`
94
+ ${this.label
95
+ ? html`<${unsafeStatic(hTag)} class="label">
96
+ <span class="label">${this.label}</span>
97
+ </${unsafeStatic(hTag)}>`
98
+ : ""}
99
+ <slot
100
+ class="group"
101
+ part="group"
102
+ @slotchange=${this.handleSlotChange}
103
+ ></slot>
104
+ `
65
105
  }
66
106
  }
@@ -21,7 +21,7 @@ export class LeuChipRemovable extends LeuChipBase {
21
21
  }
22
22
 
23
23
  handleClick() {
24
- const customEvent = new CustomEvent("remove", {
24
+ const customEvent = new CustomEvent("leu:remove", {
25
25
  bubble: true,
26
26
  composed: true,
27
27
  })
@@ -8,7 +8,7 @@ export const SIZES = {
8
8
  }
9
9
 
10
10
  export const VARIANTS = {
11
- default: "default",
11
+ toggle: "toggle",
12
12
  radio: "radio",
13
13
  }
14
14
 
@@ -30,11 +30,11 @@ export class LeuChipSelectable extends LeuChipBase {
30
30
 
31
31
  /**
32
32
  * The variant of the chip. Has an effect not only on the visual appearance but also on the behavior.
33
- * - `default`: The chip behaves like a toggle button.
33
+ * - `toggle`: The chip behaves like a toggle button.
34
34
  * - `radio`: The chip behaves like a radio button.
35
35
  *
36
36
  * @type {keyof typeof VARIANTS}
37
- * @default "default"
37
+ * @default "toggle"
38
38
  */
39
39
  variant: { type: String, reflect: true },
40
40
 
@@ -78,7 +78,7 @@ export class LeuChipSelectable extends LeuChipBase {
78
78
  return html`<button
79
79
  @click=${(e) => this.handleClick(e)}
80
80
  class="button"
81
- aria-selected=${this.selected ? "true" : "false"}
81
+ aria-pressed=${this.selected ? "true" : "false"}
82
82
  >
83
83
  <span class="label">${this.label}</span>
84
84
  </button>`
@@ -1,5 +1,15 @@
1
- :host {
1
+ .label {
2
+ margin: 0 0 0.5rem;
3
+ font: var(--leu-t-curve-35-black-font);
4
+ color: var(--leu-color-black-100);
5
+ }
6
+
7
+ :host([inverted]) .label {
8
+ color: var(--leu-color-black-0);
9
+ }
10
+
11
+ .group {
2
12
  display: flex;
3
13
  flex-wrap: wrap;
4
- gap: 0.5rem;
14
+ gap: var(--leu-chip-group-gap, 0.5rem);
5
15
  }
@@ -20,8 +20,8 @@
20
20
  --chip-radio-background-default: var(--leu-color-black-0);
21
21
  --chip-radio-background-selected: var(--leu-color-func-cyan);
22
22
 
23
- --chip-font-regular: var(--leu-font-regular);
24
- --chip-font-black: var(--leu-font-black);
23
+ --chip-font-regular: var(--leu-font-family-regular);
24
+ --chip-font-black: var(--leu-font-family-black);
25
25
 
26
26
  --chip-background-color: var(--chip-background-color-default);
27
27
  --chip-color: var(--chip-color-default);
@@ -29,6 +29,9 @@
29
29
  --chip-radio-background: var(--chip-radio-background-default);
30
30
 
31
31
  font-family: var(--chip-font-regular);
32
+
33
+ /* Allow shrinking to achieve text truncation (ellipsis) */
34
+ min-width: 0;
32
35
  }
33
36
 
34
37
  :host([inverted]) {
@@ -61,8 +64,11 @@
61
64
  cursor: pointer;
62
65
 
63
66
  display: inline-flex;
64
- align-items: center;
65
67
  gap: 0.5rem;
68
+
69
+ /* Allow shrinking to achieve text truncation (ellipsis) */
70
+ min-width: 0;
71
+ max-width: 100%;
66
72
  }
67
73
 
68
74
  .button:hover,
@@ -109,6 +115,7 @@
109
115
 
110
116
  :host([variant="radio"]) .button::before {
111
117
  content: "";
118
+ flex: 0 0 1rem;
112
119
  width: 1rem;
113
120
  height: 1rem;
114
121
  background-color: var(--chip-radio-background);
@@ -123,6 +130,10 @@
123
130
  .label {
124
131
  position: relative;
125
132
  top: -0.0625rem;
133
+
134
+ overflow: hidden;
135
+ text-overflow: ellipsis;
136
+ white-space: nowrap;
126
137
  }
127
138
 
128
139
  .icon svg {
@@ -1,7 +1,10 @@
1
1
  import { html } from "lit"
2
+ import { ifDefined } from "lit/directives/if-defined.js"
3
+ import { styleMap } from "lit/directives/style-map.js"
2
4
 
3
5
  import "../leu-chip-selectable.js"
4
6
  import "../leu-chip-removable.js"
7
+ import "../leu-chip-link.js"
5
8
  import "../leu-chip-group.js"
6
9
 
7
10
  import { SELECTION_MODES } from "../ChipGroup.js"
@@ -15,7 +18,13 @@ export default {
15
18
  control: "select",
16
19
  options: Object.values(SELECTION_MODES),
17
20
  },
18
- inverted: { control: "boolean" },
21
+ headingLevel: {
22
+ control: "select",
23
+ options: [1, 2, 3, 4, 5, 6],
24
+ },
25
+ "--leu-chip-group-gap": {
26
+ control: "text",
27
+ },
19
28
  },
20
29
  args: {
21
30
  selectionMode: "",
@@ -32,73 +41,115 @@ export default {
32
41
  },
33
42
  }
34
43
 
35
- const chips = ["Chip 1", "Chip 2", "Chip 3"]
44
+ const chips = [
45
+ "Chip mit einem sehr langen Text der dann hoffentlich mal abgeschnitten wird",
46
+ "Chip 2",
47
+ "Chip 3",
48
+ ]
36
49
 
37
- function invertedBackground(args, content) {
38
- return html`
39
- <div
40
- style="background: ${args.inverted
41
- ? "hsla(209, 83%, 59%, 1)"
42
- : "var(--leu-color-black-5)"}; padding: 1rem;"
43
- data-root
50
+ const links = [
51
+ "Steuererklärung",
52
+ "Abstimmungen",
53
+ "Zentrale Aufnahmeprüfung",
54
+ "Pass & Identitätskarte",
55
+ "Arbeiten beim Kanton",
56
+ ]
57
+
58
+ function invertedBackground({ args, content }) {
59
+ return {
60
+ content: html`
61
+ <div
62
+ style="background: ${args.inverted
63
+ ? "hsla(209, 83%, 59%, 1)"
64
+ : "var(--leu-color-black-5)"}; padding: 1rem;"
65
+ data-root
66
+ >
67
+ ${content}
68
+ </div>
69
+ `,
70
+ args,
71
+ }
72
+ }
73
+
74
+ function chipGroup({ args, content }) {
75
+ const styles = {
76
+ "--leu-chip-group-gap": args["--leu-chip-group-gap"],
77
+ }
78
+
79
+ const nextContent = html`
80
+ <leu-chip-group
81
+ style=${styleMap(styles)}
82
+ selection-mode=${ifDefined(args.selectionMode)}
83
+ heading-level=${ifDefined(args.headingLevel)}
84
+ label=${ifDefined(args.label)}
85
+ ?inverted=${args.inverted}
44
86
  >
45
87
  ${content}
46
- </div>
88
+ </leu-chip-group>
47
89
  `
90
+
91
+ return { args, content: nextContent }
48
92
  }
49
93
 
50
94
  function DefaultTemplate(args) {
51
95
  const content = html`
52
- <leu-chip-group selection-mode=${args.selectionMode}>
53
- ${chips.map(
54
- (chip) => html`
55
- <leu-chip-removable ?inverted=${args.inverted} label=${chip}>
56
- </leu-chip-removable>
57
- `
58
- )}
59
- </leu-chip-group>
96
+ ${chips.map(
97
+ (chip) => html`
98
+ <leu-chip-removable ?inverted=${args.inverted} label=${chip}>
99
+ </leu-chip-removable>
100
+ `
101
+ )}
60
102
  `
61
103
 
62
- return invertedBackground(args, content)
104
+ return invertedBackground(chipGroup({ args, content })).content
63
105
  }
64
106
 
65
107
  function SingleTemplate(args) {
66
108
  const content = html`
67
- <leu-chip-group selection-mode=${args.selectionMode}>
68
- ${chips.map(
69
- (chip) => html`
70
- <leu-chip-selectable
71
- ?inverted=${args.inverted}
72
- variant=${SELECTABLE_VARIANTS.radio}
73
- value="chip-${chip}"
74
- label=${chip}
75
- >
76
- </leu-chip-selectable>
77
- `
78
- )}
79
- </leu-chip-group>
109
+ ${chips.map(
110
+ (chip) => html`
111
+ <leu-chip-selectable
112
+ ?inverted=${args.inverted}
113
+ variant=${SELECTABLE_VARIANTS.radio}
114
+ value="chip-${chip}"
115
+ label=${chip}
116
+ >
117
+ </leu-chip-selectable>
118
+ `
119
+ )}
80
120
  `
81
121
 
82
- return invertedBackground(args, content)
122
+ return invertedBackground(chipGroup({ args, content })).content
83
123
  }
84
124
 
85
125
  function MultipleTemplate(args) {
86
126
  const content = html`
87
- <leu-chip-group selection-mode=${args.selectionMode}>
88
- ${chips.map(
89
- (chip) => html`
90
- <leu-chip-selectable
91
- ?inverted=${args.inverted}
92
- value="chip-${chip}"
93
- label=${chip}
94
- >
95
- </leu-chip-selectable>
96
- `
97
- )}
98
- </leu-chip-group>
127
+ ${chips.map(
128
+ (chip) => html`
129
+ <leu-chip-selectable
130
+ ?inverted=${args.inverted}
131
+ value="chip-${chip}"
132
+ label=${chip}
133
+ >
134
+ </leu-chip-selectable>
135
+ `
136
+ )}
99
137
  `
100
138
 
101
- return invertedBackground(args, content)
139
+ return invertedBackground(chipGroup({ args, content })).content
140
+ }
141
+
142
+ function LabeledTemplate(args) {
143
+ const content = html`
144
+ ${links.map(
145
+ (chip) => html`
146
+ <leu-chip-link ?inverted=${args.inverted} label=${chip}>
147
+ </leu-chip-link>
148
+ `
149
+ )}
150
+ `
151
+
152
+ return invertedBackground(chipGroup({ args, content })).content
102
153
  }
103
154
 
104
155
  export const Default = DefaultTemplate.bind({})
@@ -109,3 +160,6 @@ Single.args = { selectionMode: SELECTION_MODES.single }
109
160
 
110
161
  export const Multiple = MultipleTemplate.bind({})
111
162
  Multiple.args = { selectionMode: SELECTION_MODES.multiple }
163
+
164
+ export const Labeled = LabeledTemplate.bind({})
165
+ Labeled.args = { label: "Top Themen" }
@@ -4,7 +4,7 @@ import { sendKeys } from "@web/test-runner-commands"
4
4
 
5
5
  import { iconPaths } from "../../icon/icon.js"
6
6
 
7
- import "../leu-chip-group.js"
7
+ import "../leu-chip-removable.js"
8
8
 
9
9
  async function defaultFixture() {
10
10
  return fixture(
@@ -62,7 +62,7 @@ describe("LeuChipRemovable", () => {
62
62
  const button = el.shadowRoot.querySelector("button")
63
63
 
64
64
  setTimeout(() => button.click())
65
- const event = await oneEvent(el, "remove")
65
+ const event = await oneEvent(el, "leu:remove")
66
66
 
67
67
  expect(event).to.exist
68
68
  })
@@ -72,7 +72,7 @@ describe("LeuChipRemovable", () => {
72
72
 
73
73
  el.focus()
74
74
  setTimeout(() => sendKeys({ press: "Enter" }))
75
- const event = await oneEvent(el, "remove")
75
+ const event = await oneEvent(el, "leu:remove")
76
76
 
77
77
  expect(event).to.exist
78
78
  })
@@ -25,9 +25,29 @@ export class LeuDropdown extends LitElement {
25
25
  this.menuItems = []
26
26
  }
27
27
 
28
+ connectedCallback() {
29
+ super.connectedCallback()
30
+ this.addEventListener("keyup", this._keyUpHandler)
31
+ document.addEventListener("click", this._documentClickHandler)
32
+ }
33
+
28
34
  disconnectedCallback() {
29
35
  super.disconnectedCallback()
30
36
  this._removeMenuItemListeners()
37
+ this.removeEventListener("keyup", this._keyUpHandler)
38
+ document.removeEventListener("click", this._documentClickHandler)
39
+ }
40
+
41
+ _documentClickHandler = (event) => {
42
+ if (!this.contains(event.target)) {
43
+ this.expanded = false
44
+ }
45
+ }
46
+
47
+ _keyUpHandler(event) {
48
+ if (event.key === "Escape") {
49
+ this.expanded = false
50
+ }
31
51
  }
32
52
 
33
53
  _handleSlotChange() {
@@ -64,16 +84,17 @@ export class LeuDropdown extends LitElement {
64
84
  autoSizePadding="8"
65
85
  >
66
86
  <leu-button
87
+ class="button"
67
88
  slot="anchor"
68
89
  icon="download"
69
90
  variant="ghost"
70
- label=${this.label}
71
- expanded=${this.expanded ? "open" : "closed"}
91
+ expanded=${this.expanded ? "true" : "false"}
72
92
  aria-expanded=${this.expanded ? "true" : "false"}
73
93
  aria-controls="content"
74
94
  ?active=${this.expanded}
75
95
  @click=${this._handleToggleClick}
76
- ></leu-button>
96
+ >${this.label}</leu-button
97
+ >
77
98
  <div id="content" class="content" ?hidden=${!this.expanded}>
78
99
  <slot @slotchange=${this._handleSlotChange}></slot>
79
100
  </div>
@@ -14,3 +14,7 @@
14
14
 
15
15
  margin-top: 0.5rem;
16
16
  }
17
+
18
+ .button {
19
+ max-width: 100%;
20
+ }
@@ -56,6 +56,7 @@ const VALIDATION_MESSAGES = {
56
56
  * @prop {string} maxlength - The maximum length of the input element.
57
57
  * @prop {object} validationMessages - Custom validation messages. The key is the name of the validity state and the value is the message.
58
58
  * @prop {boolean} novalidate - Disables the browser's validation.
59
+ * @prop {string} step - The step value of the input element.
59
60
  *
60
61
  * @fires {CustomEvent} input - Dispatched when the value of the input element changes.
61
62
  * @fires {CustomEvent} change - Dispatched when the value of the input element changes and the input element loses focus.
@@ -91,12 +92,13 @@ export class LeuInput extends LitElement {
91
92
  /* Validation attributes */
92
93
  pattern: { type: String, reflect: true },
93
94
  type: { type: String, reflect: true },
94
- min: { type: Number, reflect: true },
95
- max: { type: Number, reflect: true },
96
- maxlength: { type: Number, reflect: true },
97
- minlength: { type: Number, reflect: true },
95
+ min: { type: String, reflect: true },
96
+ max: { type: String, reflect: true },
97
+ maxlength: { type: String, reflect: true },
98
+ minlength: { type: String, reflect: true },
98
99
  validationMessages: { type: Object },
99
100
  novalidate: { type: Boolean, reflect: true },
101
+ step: { type: String, reflect: true },
100
102
 
101
103
  /** @type {ValidityState} */
102
104
  _validity: { state: true },
@@ -407,6 +409,7 @@ export class LeuInput extends LitElement {
407
409
  max=${ifDefined(this.max)}
408
410
  maxlength=${ifDefined(this.maxlength)}
409
411
  minlength=${ifDefined(this.minlength)}
412
+ step=${ifDefined(this.step)}
410
413
  ref=${ref(this._inputRef)}
411
414
  aria-invalid=${isInvalid}
412
415
  />
@@ -26,8 +26,8 @@
26
26
 
27
27
  --input-clear-color: var(--leu-color-black-60);
28
28
 
29
- --input-font-regular: var(--leu-font-regular);
30
- --input-font-black: var(--leu-font-black);
29
+ --input-font-regular: var(--leu-font-family-regular);
30
+ --input-font-black: var(--leu-font-family-black);
31
31
 
32
32
  display: block;
33
33
  font-family: var(--input-font-regular);