@statistikzh/leu 0.2.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 +43 -0
  10. package/README.md +1 -1
  11. package/dist/Button.js +39 -30
  12. package/dist/ButtonGroup.js +5 -7
  13. package/dist/Checkbox.js +107 -88
  14. package/dist/CheckboxGroup.js +43 -38
  15. package/dist/{Chip-389013ff.js → Chip-dac7337d.js} +7 -2
  16. package/dist/ChipGroup.js +4 -6
  17. package/dist/ChipLink.js +6 -8
  18. package/dist/ChipRemovable.js +4 -7
  19. package/dist/ChipSelectable.js +10 -10
  20. package/dist/Dropdown.js +57 -27
  21. package/dist/Input.js +59 -43
  22. package/dist/Menu.js +2 -5
  23. package/dist/MenuItem.js +34 -17
  24. package/dist/Pagination.js +57 -55
  25. package/dist/Radio.js +13 -10
  26. package/dist/RadioGroup.js +43 -40
  27. package/dist/Select.js +57 -44
  28. package/dist/Table.js +147 -125
  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 +29 -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 +3 -9
  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 +22 -27
  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 +9 -89
  73. package/src/components/checkbox/CheckboxGroup.js +9 -39
  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 +2 -1
  83. package/src/components/chip/ChipGroup.js +1 -6
  84. package/src/components/chip/ChipLink.js +2 -8
  85. package/src/components/chip/ChipRemovable.js +1 -6
  86. package/src/components/chip/ChipSelectable.js +4 -9
  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 +53 -25
  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 +33 -39
  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 +22 -15
  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 +5 -10
  132. package/src/components/radio/RadioGroup.js +7 -39
  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 +35 -32
  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 +48 -123
  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,73 @@
1
+ import { html } from "lit"
2
+ import "../leu-breadcrumb.js"
3
+
4
+ export default {
5
+ title: "Breadcrumb",
6
+ component: "leu-breadcrumb",
7
+ parameters: {
8
+ design: {
9
+ type: "figma",
10
+ url: "https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=18100-258351&mode=design&t=lzVrtq8lxYVJU5TB-11",
11
+ },
12
+ html: {
13
+ root: "[data-root]",
14
+ },
15
+ },
16
+ }
17
+
18
+ function Template({ items, inverted }) {
19
+ return html`
20
+ <div
21
+ style=${inverted ? "background: var(--leu-color-accent-blue);" : ""}
22
+ data-root
23
+ >
24
+ <leu-breadcrumb .items=${items} ?inverted=${inverted}></leu-breadcrumb>
25
+ </div>
26
+ <button
27
+ @click=${() => {
28
+ document.getElementsByTagName("leu-breadcrumb")[0].items = [
29
+ { label: "Kanton Zürich", href: "https://zh.ch" },
30
+ { label: "Bildung", href: "https://www.zh.ch/de/bildung.html" },
31
+ {
32
+ label: "Schulen",
33
+ href: "https://www.zh.ch/de/bildung/schulen.html",
34
+ },
35
+ {
36
+ label: "Volksschule",
37
+ href: "https://www.zh.ch/de/bildung/schulen/volksschule.html",
38
+ },
39
+ ]
40
+ }}
41
+ style="margin-top:50px;"
42
+ >
43
+ update items
44
+ </button>
45
+ `
46
+ }
47
+
48
+ export const Regular = Template.bind({})
49
+ Regular.argTypes = {
50
+ _allListElementWidths: { table: { disable: true } },
51
+ _visible: { table: { disable: true } },
52
+ _small: { table: { disable: true } },
53
+ _resizeListenerFunction: { table: { disable: true } },
54
+ }
55
+ Regular.args = {
56
+ items: [
57
+ { label: "Kanton Zürich", href: "https://zh.ch" },
58
+ { label: "Gesundheit", href: "https://zh.ch/de/gesundheit.html" },
59
+ {
60
+ label: "Lebensmittel & Gebrauchsgegenstände",
61
+ href: "https://zh.ch/de/gesundheit/lebensmittel-gebrauchsgegenstaende.html",
62
+ },
63
+ {
64
+ label: "Lebensmittel",
65
+ href: "https://zh.ch/de/gesundheit/lebensmittel-gebrauchsgegenstaende/lebensmittel.html",
66
+ },
67
+ {
68
+ label: "Trinkwasser",
69
+ href: "https://zh.ch/de/gesundheit/lebensmittel-gebrauchsgegenstaende/lebensmittel.html",
70
+ },
71
+ ],
72
+ inverted: true,
73
+ }
@@ -0,0 +1,141 @@
1
+ import { html } from "lit"
2
+ import { fixture, expect, aTimeout } from "@open-wc/testing"
3
+ import { setViewport } from "@web/test-runner-commands"
4
+
5
+ import "../leu-breadcrumb.js"
6
+
7
+ const items = [
8
+ { label: "Kanton Zürich", href: "https://zh.ch" },
9
+ { label: "Gesundheit", href: "https://zh.ch/de/gesundheit.html" },
10
+ {
11
+ label: "Lebensmittel & Gebrauchsgegenstände",
12
+ href: "https://zh.ch/de/gesundheit/lebensmittel-gebrauchsgegenstaende.html",
13
+ },
14
+ {
15
+ label: "Lebensmittel",
16
+ href: "https://zh.ch/de/gesundheit/lebensmittel-gebrauchsgegenstaende/lebensmittel.html",
17
+ },
18
+ {
19
+ label: "Trinkwasser",
20
+ href: "https://zh.ch/de/gesundheit/lebensmittel-gebrauchsgegenstaende/lebensmittel.html",
21
+ },
22
+ ]
23
+
24
+ async function defaultFixture(args = {}) {
25
+ return fixture(
26
+ html` <leu-breadcrumb .items="${args.items ?? items}"></leu-breadcrumb> `
27
+ )
28
+ }
29
+
30
+ describe("LeuBreadcrumb", () => {
31
+ it("is a defined element", async () => {
32
+ const el = customElements.get("leu-breadcrumb")
33
+
34
+ expect(el).not.to.be.undefined
35
+ })
36
+
37
+ it("passes the a11y audit", async () => {
38
+ const el = await defaultFixture()
39
+ await expect(el).to.be.accessible()
40
+ })
41
+
42
+ it("renders a list of items", async () => {
43
+ await setViewport({ width: 1024, height: 1024 })
44
+ const el = await defaultFixture()
45
+
46
+ const itemEls = el.shadowRoot.querySelectorAll("li")
47
+
48
+ expect(itemEls[0]).to.have.trimmed.text(items[0].label)
49
+ expect(itemEls[0].querySelector("a")).to.have.attribute(
50
+ "href",
51
+ items[0].href
52
+ )
53
+ expect(itemEls[1]).to.have.trimmed.text(items[1].label)
54
+ expect(itemEls[1].querySelector("a")).to.have.attribute(
55
+ "href",
56
+ items[1].href
57
+ )
58
+ expect(itemEls[2]).to.have.trimmed.text(items[2].label)
59
+ expect(itemEls[2].querySelector("a")).to.have.attribute(
60
+ "href",
61
+ items[2].href
62
+ )
63
+ expect(itemEls[3]).to.have.trimmed.text(items[3].label)
64
+ expect(itemEls[3].querySelector("a")).to.have.attribute(
65
+ "href",
66
+ items[3].href
67
+ )
68
+
69
+ expect(itemEls[4]).to.have.trimmed.text(items[4].label)
70
+ expect(itemEls[4].querySelector("a")).to.not.exist
71
+ })
72
+
73
+ it("hides the overflowing items when shrinking the viewport", async () => {
74
+ await setViewport({ width: 1024, height: 1024 })
75
+ const el = await defaultFixture()
76
+
77
+ let itemEls = el.shadowRoot.querySelectorAll("li")
78
+ expect(itemEls.length).to.equal(5)
79
+
80
+ await setViewport({ width: 768, height: 1024 })
81
+ await aTimeout(600)
82
+ await el.updateComplete
83
+ itemEls = el.shadowRoot.querySelectorAll("li")
84
+
85
+ expect(itemEls.length).to.equal(4)
86
+ })
87
+
88
+ it("shows all the items when viewport is enlarged", async () => {
89
+ await setViewport({ width: 768, height: 1024 })
90
+ const el = await defaultFixture()
91
+
92
+ let itemEls = el.shadowRoot.querySelectorAll("li")
93
+ expect(itemEls.length).to.equal(4)
94
+
95
+ await setViewport({ width: 1024, height: 1024 })
96
+ await aTimeout(600)
97
+ await el.updateComplete
98
+ itemEls = el.shadowRoot.querySelectorAll("li")
99
+
100
+ expect(itemEls.length).to.equal(5)
101
+ })
102
+
103
+ it("only shows the first item when the viewport is too small", async () => {
104
+ await setViewport({ width: 240, height: 1024 })
105
+ const el = await defaultFixture()
106
+
107
+ const itemEls = el.shadowRoot.querySelectorAll("li")
108
+ expect(itemEls.length).to.equal(1)
109
+
110
+ expect(itemEls[0]).to.have.trimmed.text(items[3].label)
111
+ expect(itemEls[0].querySelector("a")).to.have.attribute(
112
+ "href",
113
+ items[3].href
114
+ )
115
+ })
116
+
117
+ it("shows a dropdown toggle when items are hidden", async () => {
118
+ await setViewport({ width: 768, height: 1024 })
119
+ const el = await defaultFixture()
120
+
121
+ const dropdownToggle = el.shadowRoot.querySelector("li:nth-child(2) button")
122
+ expect(dropdownToggle).to.exist
123
+ expect(dropdownToggle).to.have.trimmed.text("…")
124
+ })
125
+
126
+ it("shows a dropdown when the toggle is clicked", async () => {
127
+ await setViewport({ width: 768, height: 1024 })
128
+ const el = await defaultFixture()
129
+
130
+ const dropdownToggle = el.shadowRoot.querySelector("li:nth-child(2) button")
131
+ dropdownToggle.click()
132
+
133
+ await el.updateComplete
134
+
135
+ const dropdown = el.shadowRoot.querySelectorAll("leu-menu")
136
+ expect(dropdown).to.exist
137
+
138
+ const dropdownItems = el.shadowRoot.querySelectorAll("leu-menu-item")
139
+ expect(dropdownItems.length).to.equal(2)
140
+ })
141
+ })
@@ -1,7 +1,6 @@
1
1
  import { html, nothing, LitElement } from "lit"
2
2
  import { classMap } from "lit/directives/class-map.js"
3
3
  import { Icon } from "../icon/icon.js"
4
- import { defineElement } from "../../lib/defineElement.js"
5
4
 
6
5
  import styles from "./button.css"
7
6
 
@@ -14,7 +13,7 @@ const BUTTON_VARIANTS = ["primary", "secondary", "ghost"]
14
13
  Object.freeze(BUTTON_VARIANTS)
15
14
  export { BUTTON_VARIANTS }
16
15
 
17
- const BUTTON_SIZES = ["normal", "small"]
16
+ const BUTTON_SIZES = ["regular", "small"]
18
17
  Object.freeze(BUTTON_SIZES)
19
18
  export { BUTTON_SIZES }
20
19
 
@@ -40,19 +39,19 @@ export class LeuButton extends LitElement {
40
39
  }
41
40
 
42
41
  static properties = {
43
- label: { type: String },
44
- icon: { type: String },
45
- iconAfter: { type: String },
46
- size: { type: String },
47
- variant: { type: String },
48
- type: { type: String },
49
-
50
- disabled: { type: Boolean },
51
- round: { type: Boolean },
52
- active: { type: Boolean },
53
- inverted: { type: Boolean },
54
- expanded: { type: String },
55
- fluid: { type: Boolean },
42
+ label: { type: String, reflect: true },
43
+ icon: { type: String, reflect: true },
44
+ iconPosition: { type: String, reflect: true },
45
+ size: { type: String, reflect: true },
46
+ variant: { type: String, reflect: true },
47
+ type: { type: String, reflect: true },
48
+
49
+ disabled: { type: Boolean, reflect: true },
50
+ round: { type: Boolean, reflect: true },
51
+ active: { type: Boolean, reflect: true },
52
+ inverted: { type: Boolean, reflect: true },
53
+ expanded: { type: String, reflect: true },
54
+ fluid: { type: Boolean, reflect: true },
56
55
  }
57
56
 
58
57
  constructor() {
@@ -61,10 +60,10 @@ export class LeuButton extends LitElement {
61
60
  this.label = null
62
61
  /** @type {string} */
63
62
  this.icon = null
64
- /** @type {string} - Only taken into account if Label and no Icon is set */
65
- this.iconAfter = null
63
+ /** @type {("before" | "after")} - Only taken into account if Label and no Icon is set */
64
+ this.iconPosition = "before"
66
65
  /** @type {string} */
67
- this.size = "normal"
66
+ this.size = "regular"
68
67
  /** @type {string} */
69
68
  this.variant = "primary"
70
69
  /** @type {string} */
@@ -94,7 +93,7 @@ export class LeuButton extends LitElement {
94
93
  }
95
94
 
96
95
  renderIconBefore() {
97
- if (this.icon) {
96
+ if (this.icon && this.iconPosition === "before") {
98
97
  return html`<div class="icon-wrapper icon-wrapper--before">
99
98
  ${Icon(this.icon, this.getIconSize())}
100
99
  </div>`
@@ -104,9 +103,9 @@ export class LeuButton extends LitElement {
104
103
  }
105
104
 
106
105
  renderIconAfter() {
107
- if (this.iconAfter && this.label && !this.icon) {
106
+ if (this.icon && this.label && this.iconPosition === "after") {
108
107
  return html`<div class="icon-wrapper icon-wrapper--after">
109
- ${Icon(this.iconAfter, this.getIconSize())}
108
+ ${Icon(this.icon, this.getIconSize())}
110
109
  </div>`
111
110
  }
112
111
 
@@ -125,8 +124,8 @@ export class LeuButton extends LitElement {
125
124
 
126
125
  render() {
127
126
  const cssClasses = {
128
- icon: !this.label && this.icon && !this.iconAfter,
129
- round: !this.label && this.icon && !this.iconAfter && this.round,
127
+ icon: !this.label && this.icon,
128
+ round: !this.label && this.icon && this.round,
130
129
  active: this.active,
131
130
  inverted: this.inverted,
132
131
  [this.variant]: true,
@@ -144,7 +143,3 @@ export class LeuButton extends LitElement {
144
143
  `
145
144
  }
146
145
  }
147
-
148
- export function defineButtonElements() {
149
- defineElement("button", LeuButton)
150
- }
@@ -38,14 +38,14 @@ button.inverted:focus-visible {
38
38
  justify-content: center;
39
39
  }
40
40
 
41
- /* size - normal */
42
- button.normal {
41
+ /* size - regular */
42
+ button.regular {
43
43
  padding: 12px 24px;
44
44
  font-size: 16px;
45
45
  line-height: 24px;
46
46
  }
47
47
 
48
- button.normal.icon {
48
+ button.regular.icon {
49
49
  padding: 12px;
50
50
  }
51
51
 
@@ -1,3 +1,6 @@
1
- import { defineButtonElements } from "./Button.js"
1
+ import { defineElement } from "../../lib/defineElement.js"
2
+ import { LeuButton } from "./Button.js"
2
3
 
3
- defineButtonElements()
4
+ export { LeuButton }
5
+
6
+ defineElement("button", LeuButton)
@@ -20,6 +20,15 @@ function copyContent(params) {
20
20
  export default {
21
21
  title: "Button",
22
22
  component: "leu-button",
23
+ parameters: {
24
+ design: {
25
+ type: "figma",
26
+ url: "https://www.figma.com/file/d6Pv21UVUbnBs3AdcZijHmbN/KTZH-Design-System?type=design&node-id=4-1444&mode=design&t=xu5Vii8jXKKCKDez-0",
27
+ },
28
+ html: {
29
+ root: "[data-root]",
30
+ },
31
+ },
23
32
  }
24
33
 
25
34
  function Template({
@@ -31,7 +40,7 @@ function Template({
31
40
  variant,
32
41
  disabled,
33
42
  icon,
34
- iconAfter,
43
+ iconPosition,
35
44
  type,
36
45
  expanded,
37
46
  }) {
@@ -40,7 +49,7 @@ function Template({
40
49
  size: size === "small" ? ' size="small"' : undefined,
41
50
  variant: variant !== "primary" ? ` variant="${variant}"` : undefined,
42
51
  icon: icon ? ` icon="${icon}"` : undefined,
43
- iconAfter: iconAfter ? ` icon="${iconAfter}"` : undefined,
52
+ iconPosition: iconPosition ? ` icon="${iconPosition}"` : undefined,
44
53
  round: round ? " round" : undefined,
45
54
  active: active ? " active" : undefined,
46
55
  disabled: disabled ? " disabled" : undefined,
@@ -48,21 +57,23 @@ function Template({
48
57
  expanded: expanded ? ` expanded="${expanded}"` : undefined,
49
58
  }
50
59
  const component = html`
51
- <leu-button
52
- label=${ifDefined(label)}
53
- size=${ifDefined(size)}
54
- variant=${ifDefined(variant)}
55
- icon=${ifDefined(icon)}
56
- iconAfter=${ifDefined(iconAfter)}
57
- type=${ifDefined(type)}
58
- expanded=${expanded}
59
- ?round=${round}
60
- ?active=${active}
61
- ?inverted=${inverted}
62
- ?disabled=${disabled}
63
- @click=${() => copyContent(params)}
64
- >
65
- </leu-button>
60
+ <div data-root>
61
+ <leu-button
62
+ label=${ifDefined(label)}
63
+ size=${ifDefined(size)}
64
+ variant=${ifDefined(variant)}
65
+ icon=${ifDefined(icon)}
66
+ iconPosition=${ifDefined(iconPosition)}
67
+ type=${ifDefined(type)}
68
+ expanded=${ifDefined(expanded)}
69
+ ?round=${round}
70
+ ?active=${active}
71
+ ?inverted=${inverted}
72
+ ?disabled=${disabled}
73
+ @click=${() => copyContent(params)}
74
+ >
75
+ </leu-button>
76
+ </div>
66
77
  <br />
67
78
  <p>Click the button to copy the code to the clipboard</p>
68
79
  `
@@ -75,7 +86,7 @@ function Template({
75
86
  </style>
76
87
  <div
77
88
  style="${inverted
78
- ? "background:var(--leu-color-accent-blue);"
89
+ ? "background:var(--leu-color-accent-blue); color: var(--leu-color-white-transp-90);"
79
90
  : ""}padding:40px;"
80
91
  >
81
92
  ${component}
@@ -87,7 +98,7 @@ export const Regular = Template.bind({})
87
98
  Regular.argTypes = {
88
99
  label: { type: "string" },
89
100
  icon: { control: "select", options: ICON_NAMES },
90
- iconAfter: { control: "select", options: ICON_NAMES },
101
+ iconPosition: { control: "select", options: ["before", "after"] },
91
102
  type: { control: "radio", options: BUTTON_TYPES },
92
103
  size: { control: "radio", options: BUTTON_SIZES },
93
104
  variant: { control: "radio", options: BUTTON_VARIANTS },
@@ -101,7 +112,7 @@ Regular.args = {
101
112
  inverted: false,
102
113
 
103
114
  icon: null,
104
- iconAfter: null,
115
+ iconPosition: null,
105
116
  size: null,
106
117
  variant: null,
107
118
  type: null,
@@ -116,9 +127,14 @@ const items = [
116
127
  { label: "Active", icon: "calendar", active: true },
117
128
  { label: "Disabled", icon: "calendar", disabled: true },
118
129
 
119
- { label: "Normal", iconAfter: "calendar" },
120
- { label: "Active", iconAfter: "calendar", active: true },
121
- { label: "Disabled", iconAfter: "calendar", disabled: true },
130
+ { label: "Normal", icon: "calendar", iconPosition: "after" },
131
+ { label: "Active", icon: "calendar", iconPosition: "after", active: true },
132
+ {
133
+ label: "Disabled",
134
+ icon: "calendar",
135
+ iconPosition: "after",
136
+ disabled: true,
137
+ },
122
138
 
123
139
  { icon: "calendar" },
124
140
  { icon: "calendar", active: true },
@@ -138,14 +154,19 @@ const ghostItems = [
138
154
  { label: "Active", icon: "calendar", active: true, expanded: "closed" },
139
155
  { label: "Disabled", icon: "calendar", disabled: true, expanded: "closed" },
140
156
 
141
- { label: "Normal", iconAfter: "calendar" },
142
- { label: "Active", iconAfter: "calendar", active: true },
143
- { label: "Disabled", iconAfter: "calendar", disabled: true },
157
+ { label: "Normal", icon: "calendar", iconPosition: "after" },
158
+ { label: "Active", icon: "calendar", iconPosition: "after", active: true },
159
+ {
160
+ label: "Disabled",
161
+ icon: "calendar",
162
+ iconPosition: "after",
163
+ disabled: true,
164
+ },
144
165
  ]
145
166
 
146
167
  const sizes = [
147
168
  {
148
- size: "normal",
169
+ size: "regular",
149
170
  items,
150
171
  },
151
172
  {
@@ -168,7 +189,7 @@ const groups = [
168
189
  {
169
190
  inverted: false,
170
191
  variant: "ghost",
171
- sizes: [{ size: "normal", items: ghostItems }],
192
+ sizes: [{ size: "regular", items: ghostItems }],
172
193
  },
173
194
  {
174
195
  inverted: true,
@@ -183,11 +204,11 @@ const groups = [
183
204
  {
184
205
  inverted: true,
185
206
  variant: "ghost",
186
- sizes: [{ size: "normal", items: ghostItems }],
207
+ sizes: [{ size: "regular", items: ghostItems }],
187
208
  },
188
209
  ]
189
210
 
190
- function TemplateDev() {
211
+ function TemplateOverview() {
191
212
  return html` <style>
192
213
  .codeblock {
193
214
  position: relative;
@@ -267,7 +288,7 @@ function TemplateDev() {
267
288
  (size) =>
268
289
  html`
269
290
  <div>
270
- <div class=${classMap({ table: true })}>
291
+ <div class=${classMap({ table: true })} data-root>
271
292
  ${size.items.map((item) => {
272
293
  const params = {
273
294
  label: item.label
@@ -280,8 +301,8 @@ function TemplateDev() {
280
301
  ? ` variant="${group.variant}"`
281
302
  : undefined,
282
303
  icon: item.icon ? ` icon="${item.icon}"` : undefined,
283
- iconAfter: item.iconAfter
284
- ? ` icon="${item.iconAfter}"`
304
+ iconPosition: item.iconPosition
305
+ ? ` iconPosition="${item.iconPosition}"`
285
306
  : undefined,
286
307
  round: item.round ? " round" : undefined,
287
308
  active: item.active ? " active" : undefined,
@@ -297,7 +318,7 @@ function TemplateDev() {
297
318
  size=${ifDefined(size.size)}
298
319
  variant=${ifDefined(group.variant)}
299
320
  icon=${ifDefined(item.icon)}
300
- iconAfter=${ifDefined(item.iconAfter)}
321
+ iconPosition=${ifDefined(item.iconPosition)}
301
322
  expanded=${ifDefined(item.expanded)}
302
323
  ?round=${item.round}
303
324
  ?active=${item.active}
@@ -318,11 +339,11 @@ function TemplateDev() {
318
339
  )}`
319
340
  }
320
341
 
321
- export const Dev = TemplateDev.bind({})
322
- Dev.argTypes = {
342
+ export const Overview = TemplateOverview.bind({})
343
+ Overview.argTypes = {
323
344
  label: { table: { disable: true } },
324
345
  icon: { table: { disable: true } },
325
- iconAfter: { table: { disable: true } },
346
+ iconPosition: { table: { disable: true } },
326
347
  size: { table: { disable: true } },
327
348
  variant: { table: { disable: true } },
328
349
  type: { table: { disable: true } },
@@ -1,5 +1,5 @@
1
1
  import { html } from "lit"
2
- import { fixture, expect } from "@open-wc/testing"
2
+ import { fixture, expect, elementUpdated, oneEvent } from "@open-wc/testing"
3
3
 
4
4
  import "../leu-button.js"
5
5
 
@@ -9,7 +9,7 @@ async function defaultFixture() {
9
9
 
10
10
  describe("LeuButton", () => {
11
11
  it("is a defined element", async () => {
12
- const el = await customElements.get("leu-button")
12
+ const el = customElements.get("leu-button")
13
13
 
14
14
  await expect(el).not.to.be.undefined
15
15
  })
@@ -19,4 +19,114 @@ describe("LeuButton", () => {
19
19
 
20
20
  await expect(el).shadowDom.to.be.accessible()
21
21
  })
22
+
23
+ it("renders the label", async () => {
24
+ const el = await fixture(html` <leu-button label="Sichern"></leu-button>`)
25
+ const button = el.shadowRoot.querySelector("button")
26
+
27
+ expect(button).to.have.trimmed.text("Sichern")
28
+ })
29
+
30
+ it("renders the icon at the correct position", async () => {
31
+ const el = await fixture(
32
+ html` <leu-button icon="addNew" label="Sichern"></leu-button>`
33
+ )
34
+
35
+ const button = el.shadowRoot.querySelector("button")
36
+
37
+ expect(button).dom.to.equal(
38
+ "<button><div><svg><path /></svg></div>Sichern</div>",
39
+ { ignoreAttributes: ["d", "class", "type"] }
40
+ )
41
+
42
+ el.iconPosition = "after"
43
+
44
+ await elementUpdated(el)
45
+
46
+ expect(button).dom.to.equal(
47
+ "<button>Sichern<div><svg><path /></svg></div></div>",
48
+ { ignoreAttributes: ["d", "class", "type"] }
49
+ )
50
+ })
51
+
52
+ it("renders the icon at the correct size", async () => {
53
+ const el = await fixture(
54
+ html` <leu-button icon="addNew" label="Sichern"></leu-button>`
55
+ )
56
+
57
+ const button = el.shadowRoot.querySelector("button")
58
+
59
+ expect(button).dom.to.equal(
60
+ "<button><div><svg width='24' height='24'><path /></svg></div>Sichern</div>",
61
+ { ignoreAttributes: ["d", "class", "type"] }
62
+ )
63
+
64
+ el.size = "small"
65
+
66
+ await elementUpdated(el)
67
+
68
+ expect(button).dom.to.equal(
69
+ "<button><div><svg width='16' height='16'><path /></svg></div>Sichern</div>",
70
+ { ignoreAttributes: ["d", "class", "type"] }
71
+ )
72
+ })
73
+
74
+ it("renders the expanded icon only when the variant is ghost", async () => {
75
+ const el = await fixture(
76
+ html` <leu-button
77
+ icon="addNew"
78
+ label="Sichern"
79
+ variant="ghost"
80
+ expanded="open"
81
+ ></leu-button>`
82
+ )
83
+
84
+ const button = el.shadowRoot.querySelector("button")
85
+
86
+ expect(button).dom.to.equal(
87
+ "<button class='ghost normal'><div class='icon-wrapper icon-wrapper--before'><svg width='24' height='24'><path /></svg></div>Sichern<div class='icon-wrapper icon-wrapper--expanded'><svg width='24' height='24'><path /></svg></div></div>",
88
+ { ignoreAttributes: ["d", "type", "width", "height"] }
89
+ )
90
+
91
+ el.variant = "primary"
92
+
93
+ await elementUpdated(el)
94
+
95
+ expect(button).dom.to.equal(
96
+ "<button class='primary normal'><div class='icon-wrapper icon-wrapper--before'><svg width='24' height='24'><path /></svg></div>Sichern</div>",
97
+ { ignoreAttributes: ["d", "type"] }
98
+ )
99
+ })
100
+
101
+ it("sets the dissabled attrbiute", async () => {
102
+ const el = await fixture(
103
+ html` <leu-button
104
+ icon="addNew"
105
+ label="Sichern"
106
+ variant="ghost"
107
+ expanded="open"
108
+ disabled
109
+ ></leu-button>`
110
+ )
111
+
112
+ const button = el.shadowRoot.querySelector("button")
113
+
114
+ expect(button).to.have.attribute("disabled")
115
+
116
+ el.disabled = false
117
+ await elementUpdated(el)
118
+
119
+ expect(button).to.not.have.attribute("disabled")
120
+ })
121
+
122
+ it("dispatches the click event", async () => {
123
+ const el = await fixture(html` <leu-button label="Sichern"></leu-button>`)
124
+ const button = el.shadowRoot.querySelector("button")
125
+
126
+ setTimeout(() => button.click())
127
+
128
+ const event = await oneEvent(el, "click")
129
+
130
+ expect(event).to.exist
131
+ })
22
132
  })