@statistikzh/leu 0.13.1 → 0.14.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.
- package/.eslintrc.json +8 -0
- package/.github/workflows/ci.yml +78 -0
- package/.github/workflows/deploy-github-pages.yaml +2 -1
- package/.github/workflows/release-please.yml +2 -1
- package/.nvmrc +1 -0
- package/.prettierignore +1 -0
- package/.storybook/main.js +19 -3
- package/.storybook/preview.js +11 -0
- package/CHANGELOG.md +27 -0
- package/README.md +0 -67
- package/custom-elements-manifest.config.js +2 -2
- package/dist/Accordion.d.ts +1 -1
- package/dist/Accordion.js +8 -8
- package/dist/Button.d.ts +2 -2
- package/dist/Button.js +2 -2
- package/dist/ButtonGroup.d.ts +1 -1
- package/dist/ButtonGroup.js +1 -1
- package/dist/Checkbox.d.ts +1 -1
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +2 -3
- package/dist/CheckboxGroup.d.ts +1 -1
- package/dist/CheckboxGroup.d.ts.map +1 -1
- package/dist/CheckboxGroup.js +1 -3
- package/dist/Chip.d.ts +1 -1
- package/dist/Chip.d.ts.map +1 -1
- package/dist/Chip.js +1 -3
- package/dist/ChipGroup.d.ts +1 -1
- package/dist/ChipGroup.d.ts.map +1 -1
- package/dist/ChipGroup.js +2 -2
- package/dist/ChipLink.js +1 -1
- package/dist/ChipRemovable.js +1 -1
- package/dist/ChipSelectable.js +1 -1
- package/dist/Dialog.d.ts +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +3 -5
- package/dist/Dropdown.d.ts +1 -1
- package/dist/Dropdown.js +3 -3
- package/dist/Icon.d.ts +2 -98
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Icon.js +1 -1
- package/dist/Input.d.ts +8 -3
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +18 -12
- package/dist/{LeuElement-b670d77c.d.ts → LeuElement-DH0PPSMq.d.ts} +1 -1
- package/dist/LeuElement-DH0PPSMq.d.ts.map +1 -0
- package/dist/{LeuElement-b670d77c.js → LeuElement-DH0PPSMq.js} +2 -2
- package/dist/Menu.d.ts +2 -2
- package/dist/Menu.js +1 -1
- package/dist/MenuItem.d.ts +3 -3
- package/dist/MenuItem.js +1 -1
- package/dist/Pagination.d.ts +1 -1
- package/dist/Pagination.js +3 -3
- package/dist/Popup.d.ts +2 -2
- package/dist/Popup.d.ts.map +1 -1
- package/dist/Popup.js +1 -3
- package/dist/Radio.d.ts +1 -1
- package/dist/Radio.d.ts.map +1 -1
- package/dist/Radio.js +1 -3
- package/dist/RadioGroup.d.ts +1 -1
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +1 -3
- package/dist/Range.d.ts +1 -1
- package/dist/Range.d.ts.map +1 -1
- package/dist/Range.js +17 -19
- package/dist/ScrollTop.d.ts +1 -1
- package/dist/ScrollTop.d.ts.map +1 -1
- package/dist/ScrollTop.js +27 -3
- package/dist/Select.d.ts +3 -7
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +7 -18
- package/dist/Spinner.d.ts +1 -1
- package/dist/Spinner.js +1 -1
- package/dist/Table.d.ts +1 -1
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +3 -4
- package/dist/VisuallyHidden.d.ts +1 -1
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +3 -5
- package/dist/{hasSlotController-c09741c5.d.ts → hasSlotController-CYd5tWew.d.ts} +1 -1
- package/dist/hasSlotController-CYd5tWew.d.ts.map +1 -0
- package/dist/{hasSlotController-c09741c5.js → hasSlotController-CYd5tWew.js} +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +5 -7
- package/dist/leu-accordion.js +1 -1
- package/dist/leu-button-group.js +1 -1
- package/dist/leu-button.js +2 -2
- package/dist/leu-checkbox-group.js +1 -1
- package/dist/leu-checkbox.js +1 -1
- package/dist/leu-chip-group.js +1 -1
- package/dist/leu-chip-link.js +1 -1
- package/dist/leu-chip-removable.js +1 -1
- package/dist/leu-chip-selectable.js +1 -1
- package/dist/leu-dialog.js +2 -2
- package/dist/leu-dropdown.js +2 -2
- package/dist/leu-icon.js +1 -1
- package/dist/leu-input.js +1 -1
- package/dist/leu-menu-item.js +1 -1
- package/dist/leu-menu.js +1 -1
- package/dist/leu-pagination.js +2 -2
- package/dist/leu-popup.js +1 -1
- package/dist/leu-radio-group.js +1 -1
- package/dist/leu-radio.js +1 -1
- package/dist/leu-range.js +1 -1
- package/dist/leu-scroll-top.js +2 -3
- package/dist/leu-select.js +2 -2
- package/dist/leu-spinner.js +1 -1
- package/dist/leu-table.js +2 -2
- package/dist/leu-visually-hidden.js +1 -1
- package/dist/theme.css +143 -107
- package/dist/vscode.html-custom-data.json +4 -33
- package/dist/vue/index.d.ts +11 -78
- package/dist/web-types.json +247 -243
- package/index.js +0 -1
- package/package.json +55 -51
- package/rollup.config.js +3 -3
- package/scripts/generate-component/generate.js +5 -5
- package/scripts/generate-component/templates/stories/[name].stories.js +1 -1
- package/src/components/accordion/Accordion.js +1 -1
- package/src/components/accordion/accordion.css +6 -3
- package/src/components/accordion/stories/accordion.stories.js +7 -6
- package/src/components/accordion/test/accordion.test.js +24 -20
- package/src/components/button/Button.js +1 -1
- package/src/components/button/stories/button.stories.js +44 -46
- package/src/components/button/test/button.test.js +10 -10
- package/src/components/button-group/ButtonGroup.js +1 -1
- package/src/components/button-group/stories/button-group.stories.js +3 -3
- package/src/components/checkbox/checkbox.css +1 -0
- package/src/components/checkbox/stories/checkbox-group.stories.js +1 -1
- package/src/components/checkbox/stories/checkbox.stories.js +1 -1
- package/src/components/chip/ChipSelectable.js +1 -1
- package/src/components/chip/stories/chip-group.stories.js +5 -5
- package/src/components/chip/stories/chip-link.stories.js +1 -1
- package/src/components/chip/stories/chip-removable.stories.js +1 -1
- package/src/components/chip/stories/chip-selectable.stories.js +1 -1
- package/src/components/chip/test/chip-group.test.js +25 -33
- package/src/components/chip/test/chip-link.test.js +5 -5
- package/src/components/chip/test/chip-removable.test.js +6 -8
- package/src/components/chip/test/chip-selectable.test.js +9 -11
- package/src/components/dialog/stories/dialog.stories.js +1 -1
- package/src/components/dialog/test/dialog.test.js +1 -1
- package/src/components/dropdown/stories/dropdown.stories.js +1 -1
- package/src/components/dropdown/test/dropdown.test.js +12 -13
- package/src/components/icon/stories/icon.stories.js +1 -1
- package/src/components/input/Input.js +26 -18
- package/src/components/input/input.css +2 -2
- package/src/components/input/stories/input.stories.js +1 -4
- package/src/components/input/test/input.test.js +26 -0
- package/src/components/menu/stories/menu-item.stories.js +3 -1
- package/src/components/menu/stories/menu.stories.js +1 -1
- package/src/components/menu/test/menu-item.test.js +3 -2
- package/src/components/menu/test/menu.test.js +24 -22
- package/src/components/pagination/Pagination.js +1 -1
- package/src/components/pagination/pagination.css +1 -1
- package/src/components/pagination/stories/pagination.stories.js +3 -2
- package/src/components/pagination/test/pagination.test.js +8 -6
- package/src/components/popup/Popup.js +4 -4
- package/src/components/popup/stories/popup.stories.js +1 -1
- package/src/components/popup/test/popup.test.js +6 -8
- package/src/components/radio/RadioGroup.js +2 -2
- package/src/components/radio/stories/radio-group.stories.js +1 -1
- package/src/components/radio/stories/radio.stories.js +1 -1
- package/src/components/range/Range.js +20 -21
- package/src/components/range/stories/range-slider.stories.js +1 -1
- package/src/components/scroll-top/stories/scroll-top.stories.js +1 -1
- package/src/components/select/Select.js +7 -18
- package/src/components/select/stories/select.stories.js +3 -3
- package/src/components/select/test/select.test.js +18 -16
- package/src/components/spinner/stories/spinner.stories.js +1 -1
- package/src/components/table/Table.js +4 -4
- package/src/components/table/stories/table.stories.js +1 -1
- package/src/components/table/test/table.test.js +3 -2
- package/src/components/visually-hidden/stories/visually-hidden.stories.js +1 -1
- package/src/components/visually-hidden/test/visually-hidden.test.js +6 -8
- package/src/docs/contributing.mdx +154 -0
- package/src/docs/installation.mdx +35 -0
- package/src/docs/theme.mdx +349 -0
- package/src/docs/usage.mdx +73 -0
- package/src/lib/LeuElement.js +2 -2
- package/src/lib/hasSlotController.js +1 -1
- package/src/styles/style.stories.js +4 -2
- package/tsconfig.build.json +4 -3
- package/web-dev-server.config.mjs +1 -0
- package/web-test-runner.config.mjs +1 -1
- package/.github/workflows/test.yml +0 -38
- package/.storybook/preview-head.html +0 -2
- package/dist/Breadcrumb.d.ts +0 -69
- package/dist/Breadcrumb.d.ts.map +0 -1
- package/dist/Breadcrumb.js +0 -391
- package/dist/LeuElement-b670d77c.d.ts.map +0 -1
- package/dist/hasSlotController-c09741c5.d.ts.map +0 -1
- package/dist/leu-breadcrumb.d.ts +0 -3
- package/dist/leu-breadcrumb.d.ts.map +0 -1
- package/dist/leu-breadcrumb.js +0 -17
- package/dist/utils-65469421.d.ts +0 -16
- package/dist/utils-65469421.d.ts.map +0 -1
- package/dist/utils-65469421.js +0 -35
- package/src/components/breadcrumb/Breadcrumb.js +0 -324
- package/src/components/breadcrumb/breadcrumb.css +0 -98
- package/src/components/breadcrumb/leu-breadcrumb.js +0 -5
- package/src/components/breadcrumb/stories/breadcrumb.stories.js +0 -73
- package/src/components/breadcrumb/test/breadcrumb.test.js +0 -141
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
import { html, nothing } from "lit"
|
|
2
|
-
import { createRef, ref } from "lit/directives/ref.js"
|
|
3
|
-
import { classMap } from "lit/directives/class-map.js"
|
|
4
|
-
|
|
5
|
-
import { LeuElement } from "../../lib/LeuElement.js"
|
|
6
|
-
import { debounce } from "../../lib/utils.js"
|
|
7
|
-
import { LeuIcon } from "../icon/Icon.js"
|
|
8
|
-
import { LeuMenu } from "../menu/Menu.js"
|
|
9
|
-
import { LeuMenuItem } from "../menu/MenuItem.js"
|
|
10
|
-
import { LeuPopup } from "../popup/Popup.js"
|
|
11
|
-
import { LeuVisuallyHidden } from "../visually-hidden/VisuallyHidden.js"
|
|
12
|
-
|
|
13
|
-
import styles from "./breadcrumb.css"
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* A Breadcrumb Navigation.
|
|
17
|
-
*
|
|
18
|
-
* The breadcrumbs can be displayed in two different layouts.
|
|
19
|
-
* Only the back link (the last item / parent of the current page)
|
|
20
|
-
* is displayed when…
|
|
21
|
-
* - … the width of the container is smaller
|
|
22
|
-
* than the BACK_ONLY_BREAKPOINT.
|
|
23
|
-
* - … less then two breadcrumb items could be displayed
|
|
24
|
-
* without overflowing the container.
|
|
25
|
-
*
|
|
26
|
-
* Otherwise as many items as possible are displayed in an inline list
|
|
27
|
-
* without overflowing the container. The remaining items are displayed
|
|
28
|
-
* in a dropdown menu.
|
|
29
|
-
*
|
|
30
|
-
* In order to determine the exact numbers of items that have to be
|
|
31
|
-
* hidden inside the dropdown, all of them have to be rendered first.
|
|
32
|
-
* 1. Render all items
|
|
33
|
-
* 2. Calculate (measure) the number of items that can be displayed
|
|
34
|
-
* without overflowing the container.
|
|
35
|
-
* 3. Updating the state (_hiddeItems) which will trigger a rerender
|
|
36
|
-
* 4. Render the items again with the new state.
|
|
37
|
-
*
|
|
38
|
-
* This results in multiple updates scheduled one after another. Lit
|
|
39
|
-
* will also print a waring in the console beacause of that.
|
|
40
|
-
* It's no a nice behaviour but the only one that works without
|
|
41
|
-
* having duplicate and hidden markup to derive the sizes from that.
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* @prop {Array} items - Object array with { label, href }
|
|
45
|
-
* @prop {boolean} inverted - invert color on dark background
|
|
46
|
-
*
|
|
47
|
-
* @tagname leu-breadcrumb
|
|
48
|
-
*/
|
|
49
|
-
export class LeuBreadcrumb extends LeuElement {
|
|
50
|
-
static dependencies = {
|
|
51
|
-
"leu-icon": LeuIcon,
|
|
52
|
-
"leu-menu": LeuMenu,
|
|
53
|
-
"leu-menu-item": LeuMenuItem,
|
|
54
|
-
"leu-popup": LeuPopup,
|
|
55
|
-
"leu-visually-hidden": LeuVisuallyHidden,
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static styles = [LeuElement.styles, styles]
|
|
59
|
-
|
|
60
|
-
static properties = {
|
|
61
|
-
items: { type: Array },
|
|
62
|
-
inverted: { type: Boolean, reflect: true },
|
|
63
|
-
|
|
64
|
-
_hiddenItems: { state: true },
|
|
65
|
-
_showBackOnly: { state: true },
|
|
66
|
-
_isRecalculating: { state: true },
|
|
67
|
-
_isDropdownOpen: { state: true },
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
static BACK_ONLY_BREAKPOINT = 320
|
|
71
|
-
|
|
72
|
-
constructor() {
|
|
73
|
-
super()
|
|
74
|
-
/** @type {Array} */
|
|
75
|
-
this.items = []
|
|
76
|
-
/** @type {boolean} - will be used on dark Background */
|
|
77
|
-
this.inverted = false
|
|
78
|
-
|
|
79
|
-
/** @internal */
|
|
80
|
-
this._containerRef = createRef()
|
|
81
|
-
/** @internal */
|
|
82
|
-
this._hiddenItems = 0
|
|
83
|
-
/** @internal */
|
|
84
|
-
this._showBackOnly = null
|
|
85
|
-
/** @internal */
|
|
86
|
-
this._lastContainerWidth = null
|
|
87
|
-
/**
|
|
88
|
-
* @internal
|
|
89
|
-
* Forces the toggle button to be rendered
|
|
90
|
-
* so that all possible inline items will be measured.
|
|
91
|
-
* */
|
|
92
|
-
this._isRecalculating = true
|
|
93
|
-
/** @internal */
|
|
94
|
-
this._isDropdownOpen = false
|
|
95
|
-
|
|
96
|
-
this.resizeObserver = new ResizeObserver(
|
|
97
|
-
debounce(() => {
|
|
98
|
-
this._handleResize()
|
|
99
|
-
}, 500)
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
firstUpdated() {
|
|
104
|
-
this.resizeObserver.observe(this._containerRef.value)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async updated(changedProperties) {
|
|
108
|
-
if (changedProperties.has("items")) {
|
|
109
|
-
this._hiddenItems = 0
|
|
110
|
-
this._isRecalculating = true
|
|
111
|
-
await this.updateComplete
|
|
112
|
-
this._checkWidth()
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
disconnectedCallback() {
|
|
117
|
-
super.disconnectedCallback()
|
|
118
|
-
|
|
119
|
-
window.removeEventListener("click", this._closeDropdown)
|
|
120
|
-
this.resizeObserver.disconnect()
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** @internal */
|
|
124
|
-
get _listItems() {
|
|
125
|
-
return this.items.toSpliced(1, this._hiddenItems)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** @internal */
|
|
129
|
-
get _dropdownItems() {
|
|
130
|
-
return this.items.slice(1, 1 + this._hiddenItems)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
_handleResize = async () => {
|
|
134
|
-
const containerOffsetWidth = this._containerRef.value.offsetWidth
|
|
135
|
-
const sizeIsGrowing = containerOffsetWidth > this._lastContainerWidth
|
|
136
|
-
this._lastContainerWidth = containerOffsetWidth
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Show only the back link (parent of the current page)
|
|
140
|
-
* when the width of the container is smaller than the BACK_ONLY_BREAKPOINT
|
|
141
|
-
*/
|
|
142
|
-
if (containerOffsetWidth <= LeuBreadcrumb.BACK_ONLY_BREAKPOINT) {
|
|
143
|
-
this._showBackOnly = true
|
|
144
|
-
this._isRecalculating = false
|
|
145
|
-
return
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
this._showBackOnly = false
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* In order to calculate how many items can be displayed
|
|
152
|
-
* when the container is growing, all items have to
|
|
153
|
-
* be marked as displayed (_hiddenItems = 0) and
|
|
154
|
-
* rendered.
|
|
155
|
-
*/
|
|
156
|
-
if (sizeIsGrowing && this._hiddenItems > 0) {
|
|
157
|
-
this._hiddenItems = 0
|
|
158
|
-
this._isRecalculating = true
|
|
159
|
-
await this.updateComplete
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
this._checkWidth()
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Calculate the number of items that can be displayed
|
|
167
|
-
* without overflowing the container.
|
|
168
|
-
* @internal
|
|
169
|
-
* @returns {void}
|
|
170
|
-
*/
|
|
171
|
-
_checkWidth() {
|
|
172
|
-
const containerOffsetWidth = this._containerRef.value.offsetWidth
|
|
173
|
-
const containerScrollWidth = this._containerRef.value.scrollWidth
|
|
174
|
-
this._lastContainerWidth = containerOffsetWidth
|
|
175
|
-
|
|
176
|
-
/** When the container is not overflowing, nothing has to be done */
|
|
177
|
-
if (containerOffsetWidth === containerScrollWidth) {
|
|
178
|
-
this._isRecalculating = false
|
|
179
|
-
return
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const listItems = this._containerRef.value.querySelectorAll(
|
|
183
|
-
"li:not([data-dropdown-toggle])"
|
|
184
|
-
)
|
|
185
|
-
const listItemWidths = [...listItems].map((o) => o.offsetWidth)
|
|
186
|
-
|
|
187
|
-
let hiddenItems = 0
|
|
188
|
-
let hiddenItemsWidth = 0
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Remove item by item until the sum of the remaining items
|
|
192
|
-
* is smaller than the width of the container.
|
|
193
|
-
* The first item will not be removed.
|
|
194
|
-
*/
|
|
195
|
-
while (
|
|
196
|
-
hiddenItems < listItemWidths.length &&
|
|
197
|
-
containerOffsetWidth < containerScrollWidth - hiddenItemsWidth
|
|
198
|
-
) {
|
|
199
|
-
hiddenItems += 1
|
|
200
|
-
|
|
201
|
-
hiddenItemsWidth = listItemWidths
|
|
202
|
-
.slice(1, 1 + hiddenItems)
|
|
203
|
-
.reduce((sum, itemWidth) => sum + itemWidth, 0)
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
this._hiddenItems += hiddenItems
|
|
207
|
-
this._isRecalculating = false
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** @internal */
|
|
211
|
-
_handleDropdownToggle = (e) => {
|
|
212
|
-
e.stopPropagation()
|
|
213
|
-
|
|
214
|
-
this._isDropdownOpen = !this._isDropdownOpen
|
|
215
|
-
|
|
216
|
-
if (this._isDropdownOpen) {
|
|
217
|
-
window.addEventListener("click", this._closeDropdown)
|
|
218
|
-
} else {
|
|
219
|
-
window.removeEventListener("click", this._closeDropdown)
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
_closeDropdown = () => {
|
|
224
|
-
this._isDropdownOpen = false
|
|
225
|
-
window.removeEventListener("click", this._closeDropdown)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Render the dropdown menu
|
|
230
|
-
* @returns
|
|
231
|
-
*/
|
|
232
|
-
renderDropdown() {
|
|
233
|
-
if (this._dropdownItems.length === 0 && !this._isRecalculating)
|
|
234
|
-
return nothing
|
|
235
|
-
|
|
236
|
-
return html`
|
|
237
|
-
<li class="breadcrumbs__item" data-dropdown-toggle>
|
|
238
|
-
<span class="breadcrumbs__icon"
|
|
239
|
-
><leu-icon name="angleRight"></leu-icon
|
|
240
|
-
></span>
|
|
241
|
-
<leu-popup
|
|
242
|
-
?active=${this._isDropdownOpen}
|
|
243
|
-
placement="bottom-start"
|
|
244
|
-
shift
|
|
245
|
-
shiftPadding="8"
|
|
246
|
-
autoSize="width"
|
|
247
|
-
autoSizePadding="8"
|
|
248
|
-
>
|
|
249
|
-
<button
|
|
250
|
-
slot="anchor"
|
|
251
|
-
class="menu"
|
|
252
|
-
@click=${this._handleDropdownToggle}
|
|
253
|
-
tabindex="0"
|
|
254
|
-
>
|
|
255
|
-
…
|
|
256
|
-
</button>
|
|
257
|
-
<div class="dropdown">
|
|
258
|
-
${html`
|
|
259
|
-
<leu-menu>
|
|
260
|
-
${this._dropdownItems.map(
|
|
261
|
-
(item) =>
|
|
262
|
-
html`
|
|
263
|
-
<leu-menu-item href=${item.href}
|
|
264
|
-
>${item.label}</leu-menu-item
|
|
265
|
-
>
|
|
266
|
-
`
|
|
267
|
-
)}
|
|
268
|
-
</leu-menu>
|
|
269
|
-
`}
|
|
270
|
-
</div>
|
|
271
|
-
</leu-popup>
|
|
272
|
-
</li>
|
|
273
|
-
`
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
render() {
|
|
277
|
-
if (this.items.length < 2) return nothing
|
|
278
|
-
|
|
279
|
-
const parentItem = this.items[this.items.length - 2]
|
|
280
|
-
|
|
281
|
-
const showBackOnly =
|
|
282
|
-
this._showBackOnly || this.items.length - this._hiddenItems < 2
|
|
283
|
-
|
|
284
|
-
const wrapperClasses = {
|
|
285
|
-
breadcrumbs: true,
|
|
286
|
-
"breadcrumbs--back-only": showBackOnly,
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return html`
|
|
290
|
-
<nav class=${classMap(wrapperClasses)}>
|
|
291
|
-
<leu-visually-hidden><h2>Sie sind hier:</h2></leu-visually-hidden>
|
|
292
|
-
<ol class="breadcrumbs__list" ref=${ref(this._containerRef)}>
|
|
293
|
-
${showBackOnly
|
|
294
|
-
? html` <li class="breadcrumbs__item breadcrumbs__item--back">
|
|
295
|
-
<span class="breadcrumbs__icon"
|
|
296
|
-
><leu-icon name="arrowLeft"></leu-icon
|
|
297
|
-
></span>
|
|
298
|
-
<a class="breadcrumbs__link" href=${parentItem.href}
|
|
299
|
-
>${parentItem.label}</a
|
|
300
|
-
>
|
|
301
|
-
</li>`
|
|
302
|
-
: this._listItems.map(
|
|
303
|
-
(item, index, list) =>
|
|
304
|
-
html`
|
|
305
|
-
<li class="breadcrumbs__item">
|
|
306
|
-
${index > 0
|
|
307
|
-
? html`<span class="breadcrumbs__icon"
|
|
308
|
-
><leu-icon name="angleRight"></leu-icon
|
|
309
|
-
></span>` // First list item doesn't have an arrow
|
|
310
|
-
: nothing}
|
|
311
|
-
${index === list.length - 1
|
|
312
|
-
? item.label // Last list item doesn't contain a link
|
|
313
|
-
: html`<a class="breadcrumbs__link" href=${item.href}
|
|
314
|
-
>${item.label}</a
|
|
315
|
-
>`}
|
|
316
|
-
</li>
|
|
317
|
-
${index === 0 ? this.renderDropdown() : nothing}
|
|
318
|
-
`
|
|
319
|
-
)}
|
|
320
|
-
</ol>
|
|
321
|
-
</nav>
|
|
322
|
-
`
|
|
323
|
-
}
|
|
324
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
:host {
|
|
2
|
-
--breadcrumb-font-regular: var(--leu-font-family-regular);
|
|
3
|
-
--breadcrumb-font-black: var(--leu-font-family-black);
|
|
4
|
-
|
|
5
|
-
font-family: var(--breadcrumb-font-regular);
|
|
6
|
-
line-height: 1.5;
|
|
7
|
-
color: var(--leu-color-black-100);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
:host([inverted]) {
|
|
11
|
-
color: var(--leu-color-black-0);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.breadcrumbs__list {
|
|
15
|
-
display: flex;
|
|
16
|
-
align-items: center;
|
|
17
|
-
list-style-type: none;
|
|
18
|
-
margin: 0;
|
|
19
|
-
padding: 0;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.breadcrumbs--back-only .breadcrumbs__list {
|
|
23
|
-
overflow: hidden;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.breadcrumbs__item,
|
|
27
|
-
.breadcrumbs__icon {
|
|
28
|
-
align-items: center;
|
|
29
|
-
display: flex;
|
|
30
|
-
min-height: 1.875rem;
|
|
31
|
-
white-space: nowrap;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.breadcrumbs__item:first-child:not(.breadcrumbs__item--back) {
|
|
35
|
-
font-family: var(--breadcrumb-font-black);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.breadcrumbs__item--back {
|
|
39
|
-
max-width: 100%;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.breadcrumbs__link {
|
|
43
|
-
color: inherit;
|
|
44
|
-
text-decoration: none;
|
|
45
|
-
transition: color 0.1s ease;
|
|
46
|
-
white-space: nowrap;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.breadcrumbs__item--back .breadcrumbs__link {
|
|
50
|
-
overflow: hidden;
|
|
51
|
-
text-overflow: ellipsis;
|
|
52
|
-
margin-right: 0.25rem;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.menu {
|
|
56
|
-
background: none;
|
|
57
|
-
color: inherit;
|
|
58
|
-
cursor: pointer;
|
|
59
|
-
border: 2px solid transparent;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.menu:focus-visible {
|
|
63
|
-
outline: 2px solid var(--leu-color-func-cyan);
|
|
64
|
-
outline-offset: 2px;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.dropdown {
|
|
68
|
-
background-color: var(--leu-color-black-0);
|
|
69
|
-
box-shadow: var(--leu-box-shadow-short);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.breadcrumbs {
|
|
73
|
-
font-size: 1rem;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
@media (width >= 320px) {
|
|
77
|
-
.breadcrumbs {
|
|
78
|
-
font-size: calc(2.5vw + 8px);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@media (width >= 400px) {
|
|
83
|
-
.breadcrumbs {
|
|
84
|
-
font-size: 18px;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
@media (width >= 1024px) {
|
|
89
|
-
.breadcrumbs {
|
|
90
|
-
font-size: calc(0.7813vw + 10px);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
@media (width >= 1280px) {
|
|
95
|
-
.breadcrumbs {
|
|
96
|
-
font-size: 20px;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
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
|
-
})
|