@statistikzh/leu 0.3.0 → 0.4.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 (153) hide show
  1. package/.github/workflows/deploy-github-pages.yaml +33 -0
  2. package/.storybook/main.js +27 -1
  3. package/.storybook/manager-head.html +1 -0
  4. package/.storybook/manager.js +9 -0
  5. package/.storybook/preview-head.html +1 -1
  6. package/.storybook/preview.js +59 -5
  7. package/.storybook/static/logo.svg +19 -0
  8. package/.storybook/theme.js +7 -0
  9. package/CHANGELOG.md +30 -0
  10. package/README.md +1 -1
  11. package/dist/Button.js +15 -18
  12. package/dist/ButtonGroup.js +5 -7
  13. package/dist/Checkbox.js +101 -84
  14. package/dist/CheckboxGroup.js +41 -37
  15. package/dist/{Chip-5f70d04f.js → Chip-dac7337d.js} +5 -1
  16. package/dist/ChipGroup.js +2 -5
  17. package/dist/ChipLink.js +4 -7
  18. package/dist/ChipRemovable.js +4 -7
  19. package/dist/ChipSelectable.js +4 -7
  20. package/dist/Dropdown.js +55 -26
  21. package/dist/Input.js +29 -28
  22. package/dist/Menu.js +2 -5
  23. package/dist/MenuItem.js +30 -15
  24. package/dist/Pagination.js +54 -54
  25. package/dist/Radio.js +7 -6
  26. package/dist/RadioGroup.js +41 -39
  27. package/dist/Select.js +55 -43
  28. package/dist/Table.js +137 -120
  29. package/dist/{defineElement-ba770aed.js → _rollupPluginBabelHelpers-20f659f4.js} +1 -15
  30. package/dist/defineElement-47d4f665.js +15 -0
  31. package/dist/index.js +29 -19
  32. package/dist/leu-button-group.js +7 -3
  33. package/dist/leu-button.js +6 -3
  34. package/dist/leu-checkbox-group.js +6 -3
  35. package/dist/leu-checkbox.js +6 -3
  36. package/dist/leu-chip-group.js +6 -3
  37. package/dist/leu-chip-link.js +7 -4
  38. package/dist/leu-chip-removable.js +7 -4
  39. package/dist/leu-chip-selectable.js +7 -4
  40. package/dist/leu-dropdown.js +13 -3
  41. package/dist/leu-input.js +7 -3
  42. package/dist/leu-menu-item.js +8 -3
  43. package/dist/leu-menu.js +6 -3
  44. package/dist/leu-pagination.js +8 -3
  45. package/dist/leu-popup-4bf6f1f4.js +216 -0
  46. package/dist/leu-radio-group.js +6 -3
  47. package/dist/leu-radio.js +6 -3
  48. package/dist/leu-select.js +14 -3
  49. package/dist/leu-table.js +9 -3
  50. package/package.json +24 -12
  51. package/scripts/generate-component/templates/[Name].js +0 -5
  52. package/scripts/generate-component/templates/[name].css +1 -1
  53. package/scripts/generate-component/templates/[namespace]-[name].js +5 -2
  54. package/src/components/accordion/Accordion.js +0 -6
  55. package/src/components/accordion/leu-accordion.js +5 -2
  56. package/src/components/accordion/stories/accordion.stories.js +7 -4
  57. package/src/components/accordion/test/accordion.test.js +92 -2
  58. package/src/components/breadcrumb/Breadcrumb.js +310 -0
  59. package/src/components/breadcrumb/breadcrumb.css +114 -0
  60. package/src/components/breadcrumb/leu-breadcrumb.js +6 -0
  61. package/src/components/breadcrumb/stories/breadcrumb.stories.js +73 -0
  62. package/src/components/breadcrumb/test/breadcrumb.test.js +141 -0
  63. package/src/components/button/Button.js +10 -15
  64. package/src/components/button/button.css +3 -3
  65. package/src/components/button/leu-button.js +5 -2
  66. package/src/components/button/stories/button.stories.js +58 -37
  67. package/src/components/button/test/button.test.js +112 -2
  68. package/src/components/button-group/ButtonGroup.js +1 -7
  69. package/src/components/button-group/leu-button-group.js +5 -2
  70. package/src/components/button-group/stories/button-group.stories.js +6 -0
  71. package/src/components/button-group/test/button-group.test.js +79 -3
  72. package/src/components/checkbox/Checkbox.js +6 -85
  73. package/src/components/checkbox/CheckboxGroup.js +8 -38
  74. package/src/components/checkbox/checkbox-group.css +29 -0
  75. package/src/components/checkbox/checkbox.css +76 -0
  76. package/src/components/checkbox/leu-checkbox-group.js +5 -2
  77. package/src/components/checkbox/leu-checkbox.js +5 -2
  78. package/src/components/checkbox/stories/checkbox-group.stories.js +44 -21
  79. package/src/components/checkbox/stories/checkbox.stories.js +7 -1
  80. package/src/components/checkbox/test/checkbox-group.test.js +124 -0
  81. package/src/components/checkbox/test/checkbox.test.js +72 -59
  82. package/src/components/chip/Chip.js +1 -0
  83. package/src/components/chip/ChipGroup.js +0 -5
  84. package/src/components/chip/ChipLink.js +1 -6
  85. package/src/components/chip/ChipRemovable.js +1 -6
  86. package/src/components/chip/ChipSelectable.js +1 -6
  87. package/src/components/chip/exports.js +4 -10
  88. package/src/components/chip/leu-chip-group.js +5 -2
  89. package/src/components/chip/leu-chip-link.js +5 -2
  90. package/src/components/chip/leu-chip-removable.js +5 -2
  91. package/src/components/chip/leu-chip-selectable.js +5 -2
  92. package/src/components/chip/stories/chip-group.stories.js +18 -6
  93. package/src/components/chip/stories/chip-link.stories.js +16 -4
  94. package/src/components/chip/stories/chip-removable.stories.js +15 -4
  95. package/src/components/chip/stories/chip-selectable.stories.js +13 -3
  96. package/src/components/chip/test/chip-group.test.js +124 -0
  97. package/src/components/chip/test/chip-link.test.js +58 -0
  98. package/src/components/chip/test/chip-removable.test.js +79 -0
  99. package/src/components/chip/test/chip-selectable.test.js +95 -0
  100. package/src/components/chip/test/chip.test.js +1 -1
  101. package/src/components/dropdown/Dropdown.js +52 -24
  102. package/src/components/dropdown/dropdown.css +1 -2
  103. package/src/components/dropdown/leu-dropdown.js +5 -2
  104. package/src/components/dropdown/stories/dropdown.stories.js +11 -5
  105. package/src/components/dropdown/test/dropdown.test.js +6 -6
  106. package/src/components/icon/icon.js +1 -1
  107. package/src/components/icon/test/icon.test.js +66 -0
  108. package/src/components/input/Input.js +18 -24
  109. package/src/components/input/input.css +9 -6
  110. package/src/components/input/leu-input.js +5 -2
  111. package/src/components/input/stories/input.stories.js +8 -2
  112. package/src/components/input/test/input.test.js +431 -4
  113. package/src/components/menu/Menu.js +0 -5
  114. package/src/components/menu/MenuItem.js +20 -13
  115. package/src/components/menu/leu-menu-item.js +5 -2
  116. package/src/components/menu/leu-menu.js +5 -2
  117. package/src/components/menu/menu-item.css +5 -2
  118. package/src/components/menu/stories/menu-item.stories.js +13 -4
  119. package/src/components/menu/stories/menu.stories.js +11 -5
  120. package/src/components/menu/test/menu-item.test.js +180 -0
  121. package/src/components/menu/test/menu.test.js +10 -2
  122. package/src/components/pagination/Pagination.js +53 -65
  123. package/src/components/pagination/leu-pagination.js +5 -2
  124. package/src/components/pagination/stories/pagination.stories.js +17 -9
  125. package/src/components/pagination/test/pagination.test.js +191 -5
  126. package/src/components/popup/Popup.js +200 -0
  127. package/src/components/popup/leu-popup.js +6 -0
  128. package/src/components/popup/popup.css +27 -0
  129. package/src/components/popup/stories/popup.stories.js +58 -0
  130. package/src/components/popup/test/popup.test.js +29 -0
  131. package/src/components/radio/Radio.js +2 -6
  132. package/src/components/radio/RadioGroup.js +6 -38
  133. package/src/components/radio/leu-radio-group.js +5 -2
  134. package/src/components/radio/leu-radio.js +5 -2
  135. package/src/components/radio/radio-group.css +29 -0
  136. package/src/components/radio/stories/radio-group.stories.js +38 -19
  137. package/src/components/radio/stories/radio.stories.js +7 -1
  138. package/src/components/radio/test/radio-group.test.js +86 -0
  139. package/src/components/radio/test/radio.test.js +108 -17
  140. package/src/components/select/Select.js +34 -31
  141. package/src/components/select/leu-select.js +5 -2
  142. package/src/components/select/select.css +13 -13
  143. package/src/components/select/stories/select.stories.js +15 -168
  144. package/src/components/select/test/fixtures.js +162 -0
  145. package/src/components/select/test/select.test.js +236 -12
  146. package/src/components/table/Table.js +43 -118
  147. package/src/components/table/leu-table.js +5 -2
  148. package/src/components/table/stories/table.stories.js +20 -10
  149. package/src/components/table/table.css +99 -0
  150. package/src/components/table/test/table.test.js +1 -1
  151. package/src/lib/utils.js +17 -0
  152. package/{web-dev-server-storybook.config.mjs → web-dev-server.config.mjs} +1 -2
  153. package/web-test-runner.config.mjs +15 -2
@@ -0,0 +1,200 @@
1
+ import { html, LitElement } from "lit"
2
+ import {
3
+ autoUpdate,
4
+ computePosition,
5
+ flip,
6
+ shift,
7
+ size,
8
+ } from "@floating-ui/dom"
9
+ import styles from "./popup.css"
10
+
11
+ /**
12
+ * @tagname leu-popup
13
+ */
14
+ export class LeuPopup extends LitElement {
15
+ static styles = styles
16
+
17
+ static shadowRootOptions = {
18
+ ...LitElement.shadowRootOptions,
19
+ delegatesFocus: true,
20
+ }
21
+
22
+ static properties = {
23
+ anchor: {},
24
+ active: { type: Boolean },
25
+ /**
26
+ * @type {"top"|"top-start"|"top-end"|"bottom"|"bottom-start"|"bottom-end"|"left"|"left-start"|"left-end"|"right"|"right-start"|"right-end"}
27
+ */
28
+ placement: { type: String },
29
+ flip: { type: Boolean },
30
+ shift: { type: Boolean },
31
+ shiftPadding: { type: Number },
32
+ /** @type {"width" | "height" | "both"} */
33
+ matchSize: { type: String },
34
+ /** @type {"width" | "height" | "both"} */
35
+ autoSize: { type: String },
36
+ autoSizePadding: { type: Number },
37
+ }
38
+
39
+ constructor() {
40
+ super()
41
+
42
+ this.anchorEl = null
43
+ this.cleanup = undefined
44
+ this.flip = false
45
+ this.shift = false
46
+ }
47
+
48
+ disconnectedCallback() {
49
+ super.disconnectedCallback()
50
+ this.stop()
51
+ }
52
+
53
+ updated(changedProperties) {
54
+ if (changedProperties.has("active")) {
55
+ if (this.active) {
56
+ this.start()
57
+ } else {
58
+ this.stop()
59
+ }
60
+ }
61
+
62
+ if (changedProperties.has("anchor")) {
63
+ this.handleAnchorChange()
64
+ }
65
+
66
+ if (this.active) {
67
+ this.reposition()
68
+ }
69
+ }
70
+
71
+ get popupEl() {
72
+ return this.renderRoot?.querySelector(".popup") ?? null
73
+ }
74
+
75
+ start() {
76
+ if (!this.anchorEl || !this.active) return
77
+
78
+ this.cleanup = autoUpdate(this.anchorEl, this.popupEl, () => {
79
+ this.reposition()
80
+ })
81
+ }
82
+
83
+ stop() {
84
+ this.cleanup?.()
85
+
86
+ this.style.removeProperty("--auto-size-available-width")
87
+ this.style.removeProperty("--auto-size-available-height")
88
+ }
89
+
90
+ reposition() {
91
+ if (!this.anchorEl || !this.popupEl || !this.active) return
92
+
93
+ const middleware = []
94
+
95
+ if (this.matchSize) {
96
+ middleware.push(
97
+ size({
98
+ apply: ({ rects }) => {
99
+ const matchWidth =
100
+ this.matchSize === "width" || this.matchSize === "both"
101
+ const matchHeight =
102
+ this.matchSize === "height" || this.matchSize === "both"
103
+ this.popupEl.style.width = matchWidth
104
+ ? `${rects.reference.width}px`
105
+ : ""
106
+ this.popupEl.style.height = matchHeight
107
+ ? `${rects.reference.height}px`
108
+ : ""
109
+ },
110
+ })
111
+ )
112
+ } else {
113
+ // Cleanup styles if we're not matching width/height
114
+ this.popupEl.style.width = ""
115
+ this.popupEl.style.height = ""
116
+ }
117
+
118
+ if (this.flip) {
119
+ middleware.push(flip())
120
+ }
121
+
122
+ if (this.shift) {
123
+ middleware.push(shift({ padding: this.shiftPadding }))
124
+ }
125
+
126
+ if (this.autoSize) {
127
+ middleware.push(
128
+ size({
129
+ padding: this.autoSizePadding,
130
+ apply: ({ availableWidth, availableHeight }) => {
131
+ const setMaxWidth =
132
+ this.autoSize === "width" || this.autoSize === "both"
133
+ const setMaxHeight =
134
+ this.autoSize === "height" || this.autoSize === "both"
135
+
136
+ if (setMaxHeight) {
137
+ this.style.setProperty(
138
+ "--auto-size-available-height",
139
+ `${availableHeight}px`
140
+ )
141
+ } else {
142
+ this.style.removeProperty("--auto-size-available-height")
143
+ }
144
+
145
+ if (setMaxWidth) {
146
+ this.style.setProperty(
147
+ "--auto-size-available-width",
148
+ `${availableWidth}px`
149
+ )
150
+ } else {
151
+ this.style.removeProperty("--auto-size-available-width")
152
+ }
153
+ },
154
+ })
155
+ )
156
+ } else {
157
+ // Cleanup styles if we're not auto-sizing
158
+ this.style.removeProperty("--auto-size-available-width")
159
+ this.style.removeProperty("--auto-size-available-height")
160
+ }
161
+
162
+ computePosition(this.anchorEl, this.popupEl, {
163
+ placement: this.placement,
164
+ middleware,
165
+ }).then(({ x, y }) => {
166
+ Object.assign(this.popupEl.style, {
167
+ left: `${x}px`,
168
+ top: `${y}px`,
169
+ })
170
+ })
171
+ }
172
+
173
+ handleAnchorChange() {
174
+ if (this.anchor && typeof this.anchor === "string") {
175
+ const root = this.getRootNode()
176
+ this.anchorEl = root.getElementById(this.anchor)
177
+ } else if (this.anchor instanceof HTMLElement) {
178
+ this.anchorEl = this.anchor
179
+ } else {
180
+ this.anchorEl = this.querySelector("[slot=anchor]")
181
+ }
182
+
183
+ if (this.anchorEl instanceof HTMLSlotElement) {
184
+ ;[this.anchorEl] = this.anchorEl.assignedElements({ flatten: true })
185
+ }
186
+
187
+ if (this.anchorEl) {
188
+ this.start()
189
+ }
190
+ }
191
+
192
+ render() {
193
+ return html`
194
+ <slot name="anchor" @slotchange=${this.handleAnchorChange}></slot>
195
+ <div class="popup">
196
+ <slot> </slot>
197
+ </div>
198
+ `
199
+ }
200
+ }
@@ -0,0 +1,6 @@
1
+ import { defineElement } from "../../lib/defineElement.js"
2
+ import { LeuPopup } from "./Popup.js"
3
+
4
+ export { LeuPopup }
5
+
6
+ defineElement("popup", LeuPopup)
@@ -0,0 +1,27 @@
1
+ :host,
2
+ :host * {
3
+ box-sizing: border-box;
4
+ }
5
+
6
+ :host {
7
+ --popup-font-regular: var(--leu-font-regular);
8
+ --popup-font-black: var(--leu-font-black);
9
+
10
+ font-family: var(--popup-font-regular);
11
+ }
12
+
13
+ .popup {
14
+ display: none;
15
+
16
+ max-width: var(--auto-size-available-width, none);
17
+ max-height: var(--auto-size-available-height, none);
18
+
19
+ position: absolute;
20
+ top: 0;
21
+ left: 0;
22
+ }
23
+
24
+ /* TODO: Should visibility be a matter of the popup component? */
25
+ :host([active]) .popup {
26
+ display: block;
27
+ }
@@ -0,0 +1,58 @@
1
+ import { html } from "lit"
2
+ import { styleMap } from "lit/directives/style-map.js"
3
+ import { ifDefined } from "lit/directives/if-defined.js"
4
+ import "../leu-popup.js"
5
+ import "../../button/leu-button.js"
6
+
7
+ export default {
8
+ title: "Popup",
9
+ component: "leu-popup",
10
+ argTypes: {
11
+ placement: {
12
+ control: {
13
+ type: "select",
14
+ },
15
+ options: [
16
+ "top",
17
+ "top-start",
18
+ "top-end",
19
+ "bottom",
20
+ "bottom-start",
21
+ "bottom-end",
22
+ "left",
23
+ "left-start",
24
+ "left-end",
25
+ "right",
26
+ "right-start",
27
+ "right-end",
28
+ ],
29
+ },
30
+ },
31
+ }
32
+
33
+ const popupStyles = {
34
+ background: "white",
35
+ border: "1px solid var(--leu-color-black-40)",
36
+ padding: "0.5rem",
37
+ boxShadow: "var(--leu-box-shadow-regular)",
38
+ }
39
+
40
+ function Template(args = {}) {
41
+ return html`<leu-popup
42
+ ?active=${args.active}
43
+ ?flip=${args.flip}
44
+ ?shift=${args.shift}
45
+ placement=${ifDefined(args.placement)}
46
+ >
47
+ <leu-button slot="anchor" label="Open popup"></leu-button>
48
+ <div style=${styleMap(popupStyles)}>Popup content</div>
49
+ </leu-popup>`
50
+ }
51
+
52
+ export const Regular = Template.bind({})
53
+ Regular.args = {
54
+ active: true,
55
+ placement: "bottom-start",
56
+ flip: true,
57
+ shift: true,
58
+ }
@@ -0,0 +1,29 @@
1
+ import { html } from "lit"
2
+ import { fixture, expect } from "@open-wc/testing"
3
+
4
+ import "../leu-popup.js"
5
+
6
+ async function defaultFixture() {
7
+ return fixture(
8
+ html`
9
+ <leu-popup
10
+ ><div slot="anchor"></div>
11
+ <p>Popup content</p></leu-popup
12
+ >
13
+ `
14
+ )
15
+ }
16
+
17
+ describe("LeuPopup", () => {
18
+ it("is a defined element", async () => {
19
+ const el = await customElements.get("leu-popup")
20
+
21
+ await expect(el).not.to.be.undefined
22
+ })
23
+
24
+ it("passes the a11y audit", async () => {
25
+ const el = await defaultFixture()
26
+
27
+ await expect(el).shadowDom.to.be.accessible()
28
+ })
29
+ })
@@ -1,5 +1,4 @@
1
1
  import { html, LitElement } from "lit"
2
- import { defineElement } from "../../lib/defineElement.js"
3
2
  import styles from "./radio.css"
4
3
 
5
4
  /**
@@ -19,6 +18,7 @@ export class LeuRadio extends LitElement {
19
18
  identifier: { type: String, reflect: true },
20
19
  value: { type: String, reflect: true },
21
20
  name: { type: String, reflect: true },
21
+ label: { type: String, reflect: true },
22
22
  }
23
23
 
24
24
  constructor() {
@@ -51,11 +51,7 @@ export class LeuRadio extends LitElement {
51
51
  ?disabled=${this.disabled}
52
52
  .value=${this.value}
53
53
  />
54
- <label for=${this.identifier} class="label"><slot></slot></label>
54
+ <label for=${this.identifier} class="label">${this.label}</label>
55
55
  `
56
56
  }
57
57
  }
58
-
59
- export function defineRadioElements() {
60
- defineElement("radio", LeuRadio)
61
- }
@@ -1,45 +1,17 @@
1
- import { html, css, LitElement } from "lit"
1
+ import { html, LitElement } from "lit"
2
2
  import { classMap } from "lit/directives/class-map.js"
3
- import { defineElement } from "../../lib/defineElement.js"
3
+
4
+ import styles from "./radio-group.css"
4
5
 
5
6
  /**
6
7
  * @tagname leu-radio-group
7
8
  */
8
9
  export class LeuRadioGroup extends LitElement {
9
- static styles = css`
10
- :host {
11
- --group-font-regular: var(--leu-font-regular);
12
- --group-font-black: var(--leu-font-black);
13
-
14
- font-family: var(--group-font-regular);
15
- }
16
-
17
- .fieldset {
18
- display: flex;
19
- align-items: flex-start;
20
- flex-wrap: wrap;
21
- gap: 0.5rem 1rem;
22
-
23
- border: none;
24
- padding: 0;
25
- }
26
-
27
- .fieldset--vertical {
28
- flex-direction: column;
29
- gap: 1rem;
30
- }
31
-
32
- .legend {
33
- font-family: var(--group-font-black);
34
- font-size: 1.125rem;
35
- line-height: 1.5;
36
-
37
- margin-bottom: 0.5rem;
38
- }
39
- `
10
+ static styles = styles
40
11
 
41
12
  static properties = {
42
13
  orientation: { type: String, reflect: true },
14
+ label: { type: String, reflect: true },
43
15
  }
44
16
 
45
17
  constructor() {
@@ -181,13 +153,9 @@ export class LeuRadioGroup extends LitElement {
181
153
 
182
154
  return html`
183
155
  <fieldset class=${classMap(fieldsetClasses)}>
184
- <legend class="legend"><slot name="legend"></slot></legend>
156
+ <legend class="legend">${this.label}</legend>
185
157
  <slot @slotchange=${this.handleSlotChange}></slot>
186
158
  </fieldset>
187
159
  `
188
160
  }
189
161
  }
190
-
191
- export function defineRadioGroupElements() {
192
- defineElement("radio-group", LeuRadioGroup)
193
- }
@@ -1,3 +1,6 @@
1
- import { defineRadioGroupElements } from "./RadioGroup.js"
1
+ import { defineElement } from "../../lib/defineElement.js"
2
+ import { LeuRadioGroup } from "./RadioGroup.js"
2
3
 
3
- defineRadioGroupElements()
4
+ export { LeuRadioGroup }
5
+
6
+ defineElement("radio-group", LeuRadioGroup)
@@ -1,3 +1,6 @@
1
- import { defineRadioElements } from "./Radio.js"
1
+ import { defineElement } from "../../lib/defineElement.js"
2
+ import { LeuRadio } from "./Radio.js"
2
3
 
3
- defineRadioElements()
4
+ export { LeuRadio }
5
+
6
+ defineElement("radio", LeuRadio)
@@ -0,0 +1,29 @@
1
+ :host {
2
+ --group-font-regular: var(--leu-font-regular);
3
+ --group-font-black: var(--leu-font-black);
4
+
5
+ font-family: var(--group-font-regular);
6
+ }
7
+
8
+ .fieldset {
9
+ display: flex;
10
+ align-items: flex-start;
11
+ flex-wrap: wrap;
12
+ gap: 0.5rem 1rem;
13
+
14
+ border: none;
15
+ padding: 0;
16
+ }
17
+
18
+ .fieldset--vertical {
19
+ flex-direction: column;
20
+ gap: 1rem;
21
+ }
22
+
23
+ .legend {
24
+ font-family: var(--group-font-black);
25
+ font-size: 1.125rem;
26
+ line-height: 1.5;
27
+
28
+ margin-bottom: 0.5rem;
29
+ }
@@ -1,40 +1,59 @@
1
1
  import { html } from "lit"
2
2
  import "../leu-radio.js"
3
3
  import "../leu-radio-group.js"
4
+ import { ifDefined } from "lit/directives/if-defined.js"
4
5
 
5
6
  export default {
6
7
  title: "Radio/Group",
7
8
  component: "leu-radio-group",
8
9
  argTypes: {
9
- legend: { control: "text" },
10
+ label: { control: "text" },
10
11
  orientation: {
11
12
  options: ["VERTICAL", "HORIZONTAL"],
12
13
  control: { type: "radio" },
13
14
  },
14
15
  },
16
+ parameters: {
17
+ design: {
18
+ type: "figma",
19
+ url: "https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=17340-81935&mode=design&t=lzVrtq8lxYVJU5TB-11",
20
+ },
21
+ },
15
22
  }
16
23
 
17
- function Template({ legend, orientation }) {
24
+ function Template({ label, orientation }) {
18
25
  return html`
19
- <leu-radio-group orientation=${orientation}>
20
- <span slot="legend">${legend}</span>
21
- <leu-radio identifier="1" value="1" name="radio-button" disabled
22
- >Kurz</leu-radio
23
- >
24
- <leu-radio identifier="2" value="2" name="radio-button"
25
- >Etwas Länger</leu-radio
26
- >
27
- <leu-radio identifier="3" value="3" name="radio-button"
28
- >Ein langes Label um sicher ein umbruch zu erzwingen</leu-radio
29
- >
26
+ <leu-radio-group
27
+ orientation=${ifDefined(orientation)}
28
+ label=${ifDefined(label)}
29
+ >
30
+ <leu-radio
31
+ identifier="1"
32
+ value="1"
33
+ name="radio-button"
34
+ label="Kurz"
35
+ disabled
36
+ ></leu-radio>
37
+ <leu-radio
38
+ identifier="2"
39
+ value="2"
40
+ name="radio-button"
41
+ label="Etwas Länger"
42
+ ></leu-radio>
43
+ <leu-radio
44
+ identifier="3"
45
+ value="3"
46
+ name="radio-button"
47
+ label="Ein langes Label um sicher ein umbruch zu erzwingen"
48
+ ></leu-radio>
30
49
  </leu-radio-group>
31
50
  `
32
51
  }
33
52
 
34
53
  export const Horizontal = Template.bind({})
35
- export const HorizontalLegend = Template.bind({})
36
- HorizontalLegend.args = {
37
- legend: "Anrede",
54
+ export const HorizontalLabel = Template.bind({})
55
+ HorizontalLabel.args = {
56
+ label: "Anrede",
38
57
  }
39
58
 
40
59
  export const Vertical = Template.bind({})
@@ -42,8 +61,8 @@ Vertical.args = {
42
61
  orientation: "VERTICAL",
43
62
  }
44
63
 
45
- export const VerticalLegend = Template.bind({})
46
- VerticalLegend.args = {
64
+ export const VerticalLabel = Template.bind({})
65
+ VerticalLabel.args = {
47
66
  orientation: "VERTICAL",
48
- legend: "Anrede",
67
+ label: "Anrede",
49
68
  }
@@ -9,6 +9,12 @@ export default {
9
9
  control: "text",
10
10
  },
11
11
  },
12
+ parameters: {
13
+ design: {
14
+ type: "figma",
15
+ url: "https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=17340-81935&mode=design&t=lzVrtq8lxYVJU5TB-11",
16
+ },
17
+ },
12
18
  }
13
19
 
14
20
  function Template({
@@ -23,8 +29,8 @@ function Template({
23
29
  ?checked=${checked}
24
30
  ?disabled=${disabled}
25
31
  identifier=${"radio-1"}
32
+ label=${label}
26
33
  >
27
- ${label}
28
34
  </leu-radio>
29
35
  `
30
36
  }
@@ -0,0 +1,86 @@
1
+ import { html } from "lit"
2
+ import { fixture, expect } from "@open-wc/testing"
3
+
4
+ import "../leu-radio.js"
5
+ import "../leu-radio-group.js"
6
+
7
+ async function defaultFixture(args = {}) {
8
+ return fixture(html`
9
+ <leu-radio-group>
10
+ <span slot="legend">Legende</span>
11
+ <leu-radio
12
+ identifier="1"
13
+ value="1"
14
+ name="radio-button"
15
+ disabled
16
+ label="Kurz"
17
+ ?checked=${args.checkedValue === "1"}
18
+ ></leu-radio>
19
+ <leu-radio
20
+ identifier="2"
21
+ value="2"
22
+ name="radio-button"
23
+ label="Etwas Länger"
24
+ ?checked=${args.checkedValue === "2"}
25
+ ></leu-radio>
26
+ <leu-radio
27
+ identifier="3"
28
+ value="3"
29
+ name="radio-button"
30
+ label="Ein langes Label um sicher ein umbruch zu erzwingen"
31
+ ?checked=${args.checkedValue === "3"}
32
+ ></leu-radio>
33
+ </leu-radio-group>
34
+ `)
35
+ }
36
+
37
+ describe("LeuRadio", () => {
38
+ it("is a defined element", async () => {
39
+ const elRadioGroup = customElements.get("leu-radio-group")
40
+
41
+ await expect(elRadioGroup).not.to.be.undefined
42
+ })
43
+
44
+ it("passes the a11y audit", async () => {
45
+ const el = await defaultFixture()
46
+
47
+ await expect(el).shadowDom.to.be.accessible()
48
+ })
49
+
50
+ it("has an empty default value", async () => {
51
+ const el = await defaultFixture()
52
+
53
+ expect(el.value).to.equal("")
54
+ })
55
+
56
+ it("updates the value when a radio button is checked", async () => {
57
+ const el = await defaultFixture()
58
+ const leuRadio = el.querySelector('leu-radio[value="2"]')
59
+ const radio = leuRadio.shadowRoot.querySelector("input")
60
+
61
+ radio.click()
62
+
63
+ expect(el.value).to.equal("2")
64
+ })
65
+
66
+ it("doesn't allow multiple radio buttons to be checked", async () => {
67
+ const el = await defaultFixture()
68
+ const leuRadio2 = el.querySelector('leu-radio[value="2"]')
69
+ const leuRadio3 = el.querySelector('leu-radio[value="3"]')
70
+ const radio2 = leuRadio2.shadowRoot.querySelector("input")
71
+ const radio3 = leuRadio3.shadowRoot.querySelector("input")
72
+
73
+ radio2.click()
74
+ radio3.click()
75
+
76
+ expect(el.value).to.equal("3")
77
+ expect(leuRadio2.checked).to.be.false
78
+ expect(leuRadio3.checked).to.be.true
79
+ })
80
+
81
+ it("has a default value that reflects the checked radio button", async () => {
82
+ const el = await defaultFixture({ checkedValue: "2" })
83
+
84
+ expect(el.value).to.deep.equal("2")
85
+ })
86
+ })