@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
package/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ export * from "./src/components/accordion/Accordion.js"
2
+ export * from "./src/components/breadcrumb/Breadcrumb.js"
1
3
  export * from "./src/components/button/Button.js"
2
4
  export * from "./src/components/button-group/ButtonGroup.js"
3
5
  export * from "./src/components/checkbox/Checkbox.js"
@@ -8,6 +10,7 @@ export * from "./src/components/input/Input.js"
8
10
  export * from "./src/components/menu/Menu.js"
9
11
  export * from "./src/components/menu/MenuItem.js"
10
12
  export * from "./src/components/pagination/Pagination.js"
13
+ export * from "./src/components/popup/Popup.js"
11
14
  export * from "./src/components/radio/Radio.js"
12
15
  export * from "./src/components/radio/RadioGroup.js"
13
16
  export * from "./src/components/select/Select.js"
package/package.json CHANGED
@@ -3,25 +3,37 @@
3
3
  "description": "UI component library of the canton of zurich",
4
4
  "license": "MIT",
5
5
  "author": "statistikzh",
6
- "version": "0.4.0",
6
+ "version": "0.5.1",
7
7
  "type": "module",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "customElements": "dist/custom-elements.json",
12
+ "web-types": "./dist/web-types.json",
13
+ "exports": {
14
+ ".": {
15
+ "default": "./dist/index.js",
16
+ "types": "./dist/index.d.ts"
17
+ },
18
+ "./*": "./dist/*"
19
+ },
10
20
  "repository": {
11
21
  "type": "git",
12
22
  "url": "https://github.com/statistikzh/leu.git"
13
23
  },
14
24
  "homepage": "https://github.com/statistikzh/leu/",
15
25
  "scripts": {
16
- "analyze": "cem analyze --litelement --globs \"src/**/*.js\"",
17
- "build": "rimraf dist && npm run build:js && npm run build:css",
26
+ "analyze": "cem analyze --config custom-elements-manifest.config.js",
27
+ "build": "rimraf dist && npm run build:js && npm run build:types && npm run build:css && npm run analyze",
18
28
  "build:js": "rollup -c rollup.config.js",
29
+ "build:types": "tsc -p tsconfig.build.json",
19
30
  "build:css": "postcss src/styles/theme.css -o dist/theme.css && cp dist/theme.css .storybook/static/",
20
31
  "watch:css": "nodemon --watch 'src/styles/*' -e css --exec npm run build:css",
21
32
  "lint": "npm run lint:eslint && npm run lint:prettier",
22
33
  "lint:eslint": "eslint --ext .js,.mjs,.html . --ignore-path .gitignore ",
23
34
  "lint:prettier": "prettier \"**/*.{js,mjs,md,html,json}\" --check --ignore-path .gitignore",
24
35
  "lint:stylelint": "stylelint \"**/*.{js,css}\" --ignore-path .gitignore",
36
+ "lint:types": "tsc",
25
37
  "format": "npm run format:eslint && npm run format:prettier",
26
38
  "format:eslint": "eslint --ext .js,.mjs,.html . --fix --ignore-path .gitignore",
27
39
  "format:prettier": "prettier \"**/*.{js,mjs,md,html,json}\" --write --ignore-path .gitignore",
@@ -40,31 +52,36 @@
40
52
  "@babel/preset-env": "^7.23.3",
41
53
  "@commitlint/cli": "^17.7.1",
42
54
  "@commitlint/config-conventional": "^17.7.0",
43
- "@custom-elements-manifest/analyzer": "^0.4.17",
55
+ "@custom-elements-manifest/analyzer": "^0.9.2",
44
56
  "@open-wc/eslint-config": "^9.2.1",
45
57
  "@open-wc/testing": "^4.0.0",
46
58
  "@rollup/plugin-babel": "^6.0.4",
47
59
  "@rollup/plugin-commonjs": "^25.0.7",
48
60
  "@rollup/plugin-json": "^6.0.0",
61
+ "@rollup/plugin-typescript": "^11.1.6",
49
62
  "@storybook/addon-designs": "^7.0.9",
50
- "@storybook/addon-essentials": "^7.6.10",
51
- "@storybook/addon-links": "^7.6.10",
52
- "@storybook/blocks": "^7.6.10",
53
- "@storybook/web-components": "^7.6.10",
63
+ "@storybook/addon-essentials": "^7.6.17",
64
+ "@storybook/addon-links": "^7.6.17",
65
+ "@storybook/blocks": "^7.6.17",
66
+ "@storybook/web-components": "^7.6.17",
54
67
  "@web/dev-server": "^0.1.34",
55
68
  "@web/dev-server-rollup": "^0.5.2",
56
- "@web/storybook-builder": "^0.1.2",
69
+ "@web/storybook-builder": "^0.1.6",
57
70
  "@web/storybook-framework-web-components": "^0.1.1",
58
71
  "@web/test-runner": "^0.18.0",
59
72
  "@web/test-runner-commands": "^0.9.0",
60
73
  "@web/test-runner-playwright": "^0.11.0",
61
74
  "@whitespace/storybook-addon-html": "^5.1.6",
62
75
  "arg": "^5.0.2",
76
+ "custom-element-jet-brains-integration": "^1.4.4",
77
+ "custom-element-vs-code-integration": "^1.2.3",
78
+ "custom-element-vuejs-integration": "^1.1.0",
63
79
  "es-dev-server": "^2.1.0",
64
80
  "esbuild": "^0.20.0",
65
81
  "eslint": "^8.31.0",
66
82
  "eslint-config-prettier": "^8.3.0",
67
83
  "eslint-plugin-storybook": "^0.6.14",
84
+ "glob": "^10.3.10",
68
85
  "husky": "^8.0.0",
69
86
  "lint-staged": "^10.5.4",
70
87
  "nodemon": "^3.0.2",
@@ -83,11 +100,12 @@
83
100
  "rollup-plugin-postcss": "^4.0.2",
84
101
  "rollup-plugin-postcss-lit": "^2.1.0",
85
102
  "sinon": "^17.0.1",
86
- "storybook": "^7.6.10",
103
+ "storybook": "^7.6.17",
87
104
  "stylelint": "^15.10.3",
88
- "stylelint-config-standard": "^34.0.0"
105
+ "stylelint-config-standard": "^34.0.0",
106
+ "tslib": "^2.6.2",
107
+ "typescript": "^5.4.3"
89
108
  },
90
- "customElements": "custom-elements.json",
91
109
  "prettier": {
92
110
  "semi": false
93
111
  },
@@ -1,10 +1,12 @@
1
1
  const postcssPresetEnv = require("postcss-preset-env")
2
2
  const atImport = require("postcss-import")
3
+ const leuFontStyles = require("./scripts/postcss-leu-font-styles.cjs")
3
4
 
4
5
  module.exports = {
5
6
  stage: 2,
6
7
  plugins: [
7
8
  atImport(),
9
+ leuFontStyles(),
8
10
  postcssPresetEnv({
9
11
  features: {
10
12
  "custom-media-queries": true,
package/rollup.config.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { globSync } from "glob"
2
+ import path from "path"
3
+ import { fileURLToPath } from "url"
1
4
  import postcss from "rollup-plugin-postcss"
2
5
  import postcssLit from "rollup-plugin-postcss-lit"
3
6
  import { babel } from "@rollup/plugin-babel"
@@ -17,44 +20,25 @@ export const plugins = [
17
20
  },
18
21
  ]
19
22
 
23
+ /**
24
+ * @type {import("rollup").RollupOptions}
25
+ */
20
26
  export default {
21
- input: [
22
- "index.js",
23
- "./src/components/button/leu-button.js",
24
- "./src/components/button/Button.js",
25
- "./src/components/button-group/leu-button-group.js",
26
- "./src/components/button-group/ButtonGroup.js",
27
- "./src/components/checkbox/leu-checkbox.js",
28
- "./src/components/checkbox/leu-checkbox-group.js",
29
- "./src/components/checkbox/Checkbox.js",
30
- "./src/components/checkbox/CheckboxGroup.js",
31
- "./src/components/chip/leu-chip-group.js",
32
- "./src/components/chip/leu-chip-link.js",
33
- "./src/components/chip/leu-chip-removable.js",
34
- "./src/components/chip/leu-chip-selectable.js",
35
- "./src/components/chip/ChipGroup.js",
36
- "./src/components/chip/ChipLink.js",
37
- "./src/components/chip/ChipRemovable.js",
38
- "./src/components/chip/ChipSelectable.js",
39
- "./src/components/dropdown/leu-dropdown.js",
40
- "./src/components/dropdown/Dropdown.js",
41
- "./src/components/input/leu-input.js",
42
- "./src/components/input/Input.js",
43
- "./src/components/menu/leu-menu.js",
44
- "./src/components/menu/leu-menu-item.js",
45
- "./src/components/menu/Menu.js",
46
- "./src/components/menu/MenuItem.js",
47
- "./src/components/pagination/leu-pagination.js",
48
- "./src/components/pagination/Pagination.js",
49
- "./src/components/radio/leu-radio.js",
50
- "./src/components/radio/leu-radio-group.js",
51
- "./src/components/radio/Radio.js",
52
- "./src/components/radio/RadioGroup.js",
53
- "./src/components/select/leu-select.js",
54
- "./src/components/select/Select.js",
55
- "./src/components/table/leu-table.js",
56
- "./src/components/table/Table.js",
57
- ],
27
+ // Select all files in a direct subdirectory of src/components
28
+ // that have a name starting with
29
+ // - a capital letter
30
+ // - or "leu-"
31
+ input: {
32
+ index: "index.js",
33
+ ...Object.fromEntries(
34
+ globSync("src/components/*/{[A-Z],leu-}*.js", { nocase: false }).map(
35
+ (file) => [
36
+ path.basename(file, path.extname(file)),
37
+ fileURLToPath(new URL(file, import.meta.url)),
38
+ ]
39
+ )
40
+ ),
41
+ },
58
42
  output: {
59
43
  dir: "./dist/",
60
44
  format: "esm",
@@ -66,6 +50,3 @@ export default {
66
50
  ],
67
51
  external: /^lit(\/.*\.js)?$/,
68
52
  }
69
-
70
- // TODO: add a second config for a bundle with esbuild
71
- // import esbuild from "rollup-plugin-esbuild"
@@ -4,8 +4,8 @@
4
4
  }
5
5
 
6
6
  :host {
7
- --[name]-font-regular: var(--leu-font-regular);
8
- --[name]-font-black: var(--leu-font-black);
7
+ --[name]-font-regular: var(--leu-font-family-regular);
8
+ --[name]-font-black: var(--leu-font-family-black);
9
9
 
10
10
  font-family: var(--[name]-font-regular);
11
11
  }
@@ -0,0 +1,160 @@
1
+ const path = require("path")
2
+ const fs = require("fs/promises")
3
+
4
+ /* Plugin logic */
5
+
6
+ function getPixelValue(value) {
7
+ return parseInt(value.replace("px", ""), 10)
8
+ }
9
+
10
+ async function parseFile(file) {
11
+ const string = await fs.readFile(file, "utf-8")
12
+
13
+ return JSON.parse(string)
14
+ }
15
+
16
+ function generateCustomPropertyDeclarations({
17
+ identifier,
18
+ fontSize,
19
+ fontWeight,
20
+ lineHeight,
21
+ spacing,
22
+ }) {
23
+ const customPropertyPrefix = `--leu-t-${identifier}-${fontWeight}`
24
+
25
+ const varFontSize = `${customPropertyPrefix}-font-size`
26
+ const varLineHeight = `${customPropertyPrefix}-line-height`
27
+ const varSpacing = `${customPropertyPrefix}-spacing`
28
+ const varFont = `${customPropertyPrefix}-font`
29
+ const varFontFamily = `--leu-font-family-${fontWeight}`
30
+
31
+ return [
32
+ { type: "fontSize", name: varFontSize, value: `${fontSize / 16}rem` },
33
+ { type: "lineHeight", name: varLineHeight, value: `${lineHeight}` },
34
+ { type: "spacing", name: varSpacing, value: `${spacing}rem` },
35
+ {
36
+ type: "font",
37
+ name: varFont,
38
+ value: `var(${varFontSize}) / var(${varLineHeight}) var(${varFontFamily})`,
39
+ },
40
+ ]
41
+ }
42
+
43
+ function curveStepDeclarations(curvePrefix, stepStyle) {
44
+ const fontSizeVar = stepStyle.declarations.find(
45
+ (s) => s.type === "fontSize"
46
+ ).name
47
+ const lineHeightVar = stepStyle.declarations.find(
48
+ (s) => s.type === "lineHeight"
49
+ ).name
50
+ const spacingVar = stepStyle.declarations.find(
51
+ (s) => s.type === "spacing"
52
+ ).name
53
+ const fontVar = stepStyle.declarations.find((s) => s.type === "font").name
54
+
55
+ return [
56
+ { prop: `${curvePrefix}-font-size`, value: ` var(${fontSizeVar})` },
57
+ { prop: `${curvePrefix}-line-height`, value: ` var(${lineHeightVar})` },
58
+ { prop: `${curvePrefix}-spacing`, value: ` var(${spacingVar})` },
59
+ { prop: `${curvePrefix}-font`, value: ` var(${fontVar})` },
60
+ ]
61
+ }
62
+
63
+ /**
64
+ *
65
+ * @param {*} file
66
+ * @param {import('postcss')} postcss
67
+ * @param {import('postcss').Source} nodeSource
68
+ * @returns
69
+ */
70
+ async function createLeuFontStyleNodes(file, postcss, nodeSource) {
71
+ const { definitions, curves } = await parseFile(file)
72
+
73
+ const fontStyleDeclarations = definitions.flatMap((style) => {
74
+ const fontSize = getPixelValue(style.fontSize)
75
+ const fontWeights = Array.isArray(style.fontWeight)
76
+ ? style.fontWeight
77
+ : [style.fontWeight]
78
+ const spacing = getPixelValue(style.spacing) / 16
79
+
80
+ const identifier = (fontSize / 4) * 10
81
+
82
+ return fontWeights.map((fontWeight) => ({
83
+ name: style.name,
84
+ fontWeight,
85
+ identifier,
86
+ declarations: generateCustomPropertyDeclarations({
87
+ identifier,
88
+ fontSize,
89
+ fontWeight,
90
+ lineHeight: style.lineHeight,
91
+ spacing,
92
+ }),
93
+ }))
94
+ })
95
+
96
+ const fontStyleNodes = fontStyleDeclarations.flatMap((style) =>
97
+ style.declarations.map(
98
+ ({ name, value }) =>
99
+ new postcss.Declaration({ prop: name, value, source: nodeSource })
100
+ )
101
+ )
102
+
103
+ const curveNodes = curves.flatMap((curve) => {
104
+ const [_, lastStepName] = curve.steps.at(-1)
105
+ const { identifier } = fontStyleDeclarations.find(
106
+ (style) => style.name === lastStepName && style.fontWeight === "black"
107
+ )
108
+
109
+ const curvePrefix = `--leu-t-curve-${identifier}-black`
110
+
111
+ return curve.steps.flatMap((step) => {
112
+ const [viewport, styleName] = step
113
+
114
+ const stepStyle = fontStyleDeclarations.find(
115
+ (s) => s.name === styleName && s.fontWeight === "black"
116
+ )
117
+
118
+ const nodes = curveStepDeclarations(curvePrefix, stepStyle).map(
119
+ ({ prop, value }) =>
120
+ new postcss.Declaration({ prop, value, source: nodeSource })
121
+ )
122
+
123
+ return viewport === null
124
+ ? nodes
125
+ : new postcss.AtRule({
126
+ name: "media",
127
+ params: `(${viewport})`,
128
+ nodes,
129
+ source: nodeSource,
130
+ })
131
+ })
132
+ })
133
+
134
+ return [...fontStyleNodes, ...curveNodes]
135
+ }
136
+
137
+ /* Plugin config */
138
+
139
+ /**
140
+ * @type {import('postcss').PluginCreator}
141
+ */
142
+ module.exports = () => ({
143
+ postcssPlugin: "leu-font-styles",
144
+ AtRule: {
145
+ "leu-font-styles": async (atRule, postcss) => {
146
+ const rootDir = path.dirname(atRule.source.input.file)
147
+ const jsonFile = atRule.params.replace(/['"]+/g, "")
148
+
149
+ const nodes = await createLeuFontStyleNodes(
150
+ path.resolve(rootDir, jsonFile),
151
+ postcss,
152
+ atRule.source
153
+ )
154
+
155
+ atRule.replaceWith(nodes)
156
+ },
157
+ },
158
+ })
159
+
160
+ module.exports.postcss = true
@@ -6,8 +6,8 @@
6
6
  }
7
7
 
8
8
  :host {
9
- --accordion-font-regular: var(--leu-font-regular);
10
- --accordion-font-black: var(--leu-font-black);
9
+ --accordion-font-regular: var(--leu-font-family-regular);
10
+ --accordion-font-black: var(--leu-font-family-black);
11
11
 
12
12
  --accordion-toggle-font: var(--accordion-font-black);
13
13
 
@@ -8,7 +8,8 @@ export default {
8
8
  component: "leu-accordion",
9
9
  argTypes: {
10
10
  headingLevel: {
11
- options: [0, 1, 2, 3, 4, 5, 6],
11
+ control: "select",
12
+ options: [1, 2, 3, 4, 5, 6],
12
13
  },
13
14
  content: {
14
15
  control: {
@@ -1,5 +1,5 @@
1
1
  import { html } from "lit"
2
- import { fixture, expect } from "@open-wc/testing"
2
+ import { fixture, expect, elementUpdated, aTimeout } from "@open-wc/testing"
3
3
 
4
4
  import "../leu-accordion.js"
5
5
 
@@ -88,11 +88,13 @@ describe("LeuAccordion", () => {
88
88
  )
89
89
 
90
90
  const button = el.shadowRoot.querySelector("button")
91
- const content = el.shadowRoot.querySelector(".content")
91
+ const content = el.querySelector("[slot=content]")
92
92
 
93
93
  expect(content).not.to.be.visible
94
94
 
95
95
  button.click()
96
+ await elementUpdated(el)
97
+ await aTimeout(100)
96
98
  expect(content).to.be.visible
97
99
  })
98
100
 
@@ -7,6 +7,7 @@ import { Icon } from "../icon/icon.js"
7
7
  import "../menu/leu-menu.js"
8
8
  import "../menu/leu-menu-item.js"
9
9
  import "../popup/leu-popup.js"
10
+ import "../visually-hidden/leu-visually-hidden.js"
10
11
  import { debounce } from "../../lib/utils.js"
11
12
 
12
13
  /**
@@ -276,7 +277,7 @@ export class LeuBreadcrumb extends LitElement {
276
277
 
277
278
  return html`
278
279
  <nav class=${classMap(wrapperClasses)}>
279
- <h2 class="visuallyhidden">Sie sind hier:</h2>
280
+ <leu-visually-hidden><h2>Sie sind hier:</h2></leu-visually-hidden>
280
281
  <ol class="breadcrumbs__list" ref=${ref(this._containerRef)}>
281
282
  ${showBackOnly
282
283
  ? html` <li class="breadcrumbs__item breadcrumbs__item--back">
@@ -4,8 +4,8 @@
4
4
  }
5
5
 
6
6
  :host {
7
- --breadcrumb-font-regular: var(--leu-font-regular);
8
- --breadcrumb-font-black: var(--leu-font-black);
7
+ --breadcrumb-font-regular: var(--leu-font-family-regular);
8
+ --breadcrumb-font-black: var(--leu-font-family-black);
9
9
 
10
10
  font-family: var(--breadcrumb-font-regular);
11
11
  line-height: 1.5;
@@ -74,17 +74,6 @@
74
74
  box-shadow: var(--leu-box-shadow-short);
75
75
  }
76
76
 
77
- .visuallyhidden {
78
- clip: rect(0 0 0 0);
79
- border: 0;
80
- height: 1px;
81
- margin: -1px !important;
82
- overflow: hidden;
83
- padding: 0 !important;
84
- position: absolute;
85
- width: 1px;
86
- }
87
-
88
77
  .breadcrumbs {
89
78
  font-size: 1rem;
90
79
  }
@@ -1,6 +1,9 @@
1
1
  import { html, nothing, LitElement } from "lit"
2
2
  import { classMap } from "lit/directives/class-map.js"
3
+ import { ifDefined } from "lit/directives/if-defined.js"
4
+
3
5
  import { Icon } from "../icon/icon.js"
6
+ import { HasSlotController } from "../../lib/hasSlotController.js"
4
7
 
5
8
  import styles from "./button.css"
6
9
 
@@ -21,9 +24,36 @@ const BUTTON_TYPES = ["button", "submit", "reset"]
21
24
  Object.freeze(BUTTON_TYPES)
22
25
  export { BUTTON_TYPES }
23
26
 
24
- export const BUTTON_EXPANDED_OPTIONS = ["open", "closed"]
27
+ export const BUTTON_EXPANDED_OPTIONS = ["true", "false"]
25
28
  Object.freeze(BUTTON_EXPANDED_OPTIONS)
26
29
 
30
+ /**
31
+ * All roles that are associated with a aria-checked attribute
32
+ * @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-checked
33
+ */
34
+ const ARIA_ROLES_CHECKED = [
35
+ "checkbox",
36
+ "menuitemcheckbox",
37
+ "menuitemradio",
38
+ "option",
39
+ "radio",
40
+ "switch",
41
+ ]
42
+
43
+ /**
44
+ * All roles that are associated with a aria-selected attribute
45
+ * @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-selected
46
+ */
47
+ const ARIA_ROLES_SELECTED = [
48
+ "gridcell",
49
+ "option",
50
+ "row",
51
+ "tab",
52
+ "columnheader",
53
+ "rowheader",
54
+ "treeitem",
55
+ ]
56
+
27
57
  /**
28
58
  * @tagname leu-button
29
59
  */
@@ -38,6 +68,11 @@ export class LeuButton extends LitElement {
38
68
  delegatesFocus: true,
39
69
  }
40
70
 
71
+ /**
72
+ * @internal
73
+ */
74
+ hasSlotController = new HasSlotController(this, ["[default]"])
75
+
41
76
  static properties = {
42
77
  label: { type: String, reflect: true },
43
78
  icon: { type: String, reflect: true },
@@ -45,6 +80,7 @@ export class LeuButton extends LitElement {
45
80
  size: { type: String, reflect: true },
46
81
  variant: { type: String, reflect: true },
47
82
  type: { type: String, reflect: true },
83
+ componentRole: { type: String, reflect: true },
48
84
 
49
85
  disabled: { type: Boolean, reflect: true },
50
86
  round: { type: Boolean, reflect: true },
@@ -66,7 +102,7 @@ export class LeuButton extends LitElement {
66
102
  this.size = "regular"
67
103
  /** @type {string} */
68
104
  this.variant = "primary"
69
- /** @type {string} */
105
+ /** @type {"button" | "submit" | "reset"} */
70
106
  this.type = "button"
71
107
 
72
108
  /** @type {boolean} */
@@ -83,7 +119,7 @@ export class LeuButton extends LitElement {
83
119
 
84
120
  /**
85
121
  * Only taken into account if variant is "ghost"
86
- * @type {("open" | "closed" | undefined)}
122
+ * @type {("true" | "false" | undefined)}
87
123
  */
88
124
  this.expanded = undefined
89
125
  }
@@ -103,7 +139,7 @@ export class LeuButton extends LitElement {
103
139
  }
104
140
 
105
141
  renderIconAfter() {
106
- if (this.icon && this.label && this.iconPosition === "after") {
142
+ if (this.icon && this.iconPosition === "after") {
107
143
  return html`<div class="icon-wrapper icon-wrapper--after">
108
144
  ${Icon(this.icon, this.getIconSize())}
109
145
  </div>`
@@ -122,10 +158,30 @@ export class LeuButton extends LitElement {
122
158
  return nothing
123
159
  }
124
160
 
161
+ getAriaAttributes() {
162
+ const attributes = {
163
+ role: this.componentRole,
164
+ label: this.label,
165
+ }
166
+
167
+ if (this.componentRole) {
168
+ if (ARIA_ROLES_CHECKED.includes(this.componentRole)) {
169
+ attributes.checked = this.active ? "true" : "false"
170
+ } else if (ARIA_ROLES_SELECTED.includes(this.componentRole)) {
171
+ attributes.selected = this.active ? "true" : "false"
172
+ }
173
+ }
174
+
175
+ return attributes
176
+ }
177
+
125
178
  render() {
179
+ const hasContent = this.hasSlotController.test("[default]")
180
+ const aria = this.getAriaAttributes()
181
+
126
182
  const cssClasses = {
127
- icon: !this.label && this.icon,
128
- round: !this.label && this.icon && this.round,
183
+ icon: !hasContent && this.icon,
184
+ round: !hasContent && this.icon && this.round,
129
185
  active: this.active,
130
186
  inverted: this.inverted,
131
187
  [this.variant]: true,
@@ -133,12 +189,17 @@ export class LeuButton extends LitElement {
133
189
  }
134
190
  return html`
135
191
  <button
192
+ aria-label=${ifDefined(aria.label)}
193
+ aria-selected=${ifDefined(aria.selected)}
194
+ aria-checked=${ifDefined(aria.checked)}
195
+ role=${ifDefined(aria.role)}
136
196
  class=${classMap(cssClasses)}
137
197
  ?disabled=${this.disabled}
138
198
  type=${this.type}
139
199
  >
140
- ${this.renderIconBefore()} ${this.label} ${this.renderIconAfter()}
141
- ${this.renderExpandingIcon()}
200
+ ${this.renderIconBefore()}
201
+ <span class="label"><slot></slot></span>
202
+ ${this.renderIconAfter()} ${this.renderExpandingIcon()}
142
203
  </button>
143
204
  `
144
205
  }
@@ -3,18 +3,31 @@
3
3
  }
4
4
 
5
5
  button {
6
- font-family: var(--leu-font-black);
6
+ font-family: var(--leu-font-family-black);
7
7
  text-align: center;
8
8
  appearance: none;
9
9
  transition: background 0.1s ease;
10
10
  cursor: pointer;
11
11
  border: 1px solid transparent;
12
12
  border-radius: 2px;
13
+
14
+ max-width: 100%;
13
15
  display: flex;
14
16
  align-items: center;
15
17
  column-gap: 8px;
16
18
  }
17
19
 
20
+ .label {
21
+ flex: 1 1 0;
22
+ overflow: hidden;
23
+ text-overflow: ellipsis;
24
+ white-space: nowrap;
25
+ }
26
+
27
+ .icon .label {
28
+ display: none;
29
+ }
30
+
18
31
  button.round {
19
32
  border-radius: 50%;
20
33
  }
@@ -76,6 +89,10 @@ button.primary.active {
76
89
  background: var(--leu-color-black-100);
77
90
  }
78
91
 
92
+ button.primary.active:hover {
93
+ background: var(--leu-color-black-transp-80);
94
+ }
95
+
79
96
  button.primary:disabled {
80
97
  color: var(--leu-color-black-0);
81
98
  background: var(--leu-color-black-transp-20);
@@ -97,6 +114,10 @@ button.secondary.active {
97
114
  background: var(--leu-color-black-100);
98
115
  }
99
116
 
117
+ button.secondary.active:hover {
118
+ background: var(--leu-color-black-transp-80);
119
+ }
120
+
100
121
  button.secondary:disabled {
101
122
  color: var(--leu-color-black-transp-20);
102
123
  background: var(--leu-color-black-transp-5);
@@ -107,7 +128,7 @@ button.ghost {
107
128
  background: transparent;
108
129
  padding: 0 0.5rem;
109
130
  color: var(--leu-color-black-60);
110
- font-family: var(--leu-font-regular);
131
+ font-family: var(--leu-font-family-regular);
111
132
  }
112
133
 
113
134
  button.ghost:hover {