@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.144 → 2.0.0-next.145
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/bundle/openbridge-webcomponents.bundle.js +4736 -4470
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +206 -21
- package/dist/components/checkbox-item/checkbox-item.css.js +137 -12
- package/dist/components/checkbox-item/checkbox-item.css.js.map +1 -1
- package/dist/components/checkbox-item/checkbox-item.d.ts +68 -39
- package/dist/components/checkbox-item/checkbox-item.d.ts.map +1 -1
- package/dist/components/checkbox-item/checkbox-item.js +66 -25
- package/dist/components/checkbox-item/checkbox-item.js.map +1 -1
- package/dist/components/checkbox-list/checkbox-list-visibility.d.ts +16 -0
- package/dist/components/checkbox-list/checkbox-list-visibility.d.ts.map +1 -0
- package/dist/components/checkbox-list/checkbox-list-visibility.js +12 -0
- package/dist/components/checkbox-list/checkbox-list-visibility.js.map +1 -0
- package/dist/components/checkbox-list/checkbox-list.css.js +23 -0
- package/dist/components/checkbox-list/checkbox-list.css.js.map +1 -0
- package/dist/components/checkbox-list/checkbox-list.d.ts +66 -0
- package/dist/components/checkbox-list/checkbox-list.d.ts.map +1 -0
- package/dist/components/checkbox-list/checkbox-list.js +81 -0
- package/dist/components/checkbox-list/checkbox-list.js.map +1 -0
- package/package.json +1 -1
- package/src/components/checkbox-item/checkbox-item.css +63 -17
- package/src/components/checkbox-item/checkbox-item.spec.ts +115 -0
- package/src/components/checkbox-item/checkbox-item.stories.ts +82 -97
- package/src/components/checkbox-item/checkbox-item.ts +118 -64
- package/src/components/checkbox-list/checkbox-list-visibility.spec.ts +68 -0
- package/src/components/checkbox-list/checkbox-list-visibility.ts +23 -0
- package/src/components/checkbox-list/checkbox-list.css +13 -0
- package/src/components/checkbox-list/checkbox-list.spec.ts +93 -0
- package/src/components/checkbox-list/checkbox-list.stories.ts +161 -0
- package/src/components/checkbox-list/checkbox-list.ts +130 -0
|
@@ -2,10 +2,12 @@ import {LitElement, html, nothing, unsafeCSS} from 'lit';
|
|
|
2
2
|
import {property, query} from 'lit/decorators.js';
|
|
3
3
|
import {classMap} from 'lit/directives/class-map.js';
|
|
4
4
|
import {ifDefined} from 'lit/directives/if-defined.js';
|
|
5
|
+
import {styleMap} from 'lit/directives/style-map.js';
|
|
5
6
|
import {customElement} from '../../decorator.js';
|
|
6
7
|
import componentStyle from './checkbox-item.css?inline';
|
|
7
8
|
import '../checkbox/checkbox.js';
|
|
8
9
|
import '../../icons/icon-chevron-right-google.js';
|
|
10
|
+
import '../../icons/icon-chevron-down-google.js';
|
|
9
11
|
import {
|
|
10
12
|
CheckboxState,
|
|
11
13
|
CheckboxStatus,
|
|
@@ -22,59 +24,73 @@ export enum ObcCheckboxItemHoverStyle {
|
|
|
22
24
|
visualTarget = 'visual-target',
|
|
23
25
|
}
|
|
24
26
|
|
|
27
|
+
export type ObcCheckboxItemExpandToggleEvent = CustomEvent<boolean>;
|
|
28
|
+
|
|
25
29
|
/**
|
|
26
|
-
* `<obc-checkbox-item>` – A list
|
|
27
|
-
*
|
|
30
|
+
* `<obc-checkbox-item>` – A list row that pairs `<obc-checkbox>` with a label,
|
|
31
|
+
* an optional description, and hierarchy affordances for nested lists.
|
|
28
32
|
*
|
|
29
33
|
* ### Overview
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
+
* The row is the touch target: clicking anywhere on it toggles the checkbox,
|
|
35
|
+
* except on the chevron button, which only asks to expand or collapse. Depth
|
|
36
|
+
* is a number (`level`); the row indents itself so a flat sequence of rows
|
|
37
|
+
* reads as a tree. `<obc-checkbox-list>` builds on this to hide the rows
|
|
38
|
+
* under a collapsed parent.
|
|
34
39
|
*
|
|
35
40
|
* ### Features
|
|
36
|
-
* - Three
|
|
37
|
-
* -
|
|
38
|
-
* -
|
|
39
|
-
*
|
|
40
|
-
* -
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* -
|
|
44
|
-
* - **Nested level 2:** Chevron slot is reserved and nested spacer is shown.
|
|
41
|
+
* - Three statuses: `unchecked`, `checked`, `mixed`.
|
|
42
|
+
* - `touch-target` or `visual-target` hover treatment.
|
|
43
|
+
* - `level` indentation: level 1 reserves the chevron slot, each further
|
|
44
|
+
* level adds a spacer.
|
|
45
|
+
* - `expandable` rows show a chevron button that fires `expand-toggle`; the
|
|
46
|
+
* host owns `expanded`.
|
|
47
|
+
* - Optional `description` line under the label.
|
|
48
|
+
* - Forwards `aria-describedby` to the inner checkbox.
|
|
45
49
|
*
|
|
46
50
|
* ### Usage Guidelines
|
|
47
|
-
* -
|
|
48
|
-
* -
|
|
49
|
-
*
|
|
50
|
-
* -
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* - No named slots. Label content is provided through the `label` property.
|
|
51
|
+
* - Keep `status` as the source of truth; update it from the `change` event.
|
|
52
|
+
* - Set `expanded` in response to `expand-toggle` — the row never flips it
|
|
53
|
+
* itself, so a parent (or `<obc-checkbox-list>`) can veto or persist it.
|
|
54
|
+
* - Use `level` 0 for a plain list; start at 1 when any row in the list is
|
|
55
|
+
* expandable so chevrons and checkboxes line up.
|
|
56
|
+
* - Prefer `hoverStyle="touch-target"` for standard list behaviour.
|
|
54
57
|
*
|
|
55
|
-
* ###
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* - Provide non-empty `label` for accessible naming.
|
|
61
|
-
* - Use `aria-describedby` when additional contextual text exists outside.
|
|
62
|
-
* - For deep hierarchies, use `isNested` with `isLevel1` / `isLevel2`
|
|
63
|
-
* consistently to preserve spacing and alignment.
|
|
58
|
+
* ### Accessibility
|
|
59
|
+
* The checkbox and the chevron are separate controls in the natural tab
|
|
60
|
+
* order. The chevron is a native button named by the row's label, with the
|
|
61
|
+
* state in `aria-expanded`, following the WAI-ARIA checkbox and disclosure
|
|
62
|
+
* button patterns.
|
|
64
63
|
*
|
|
65
64
|
* ### Example
|
|
66
65
|
* ```html
|
|
67
66
|
* <obc-checkbox-item
|
|
67
|
+
* level="1"
|
|
68
|
+
* expandable
|
|
69
|
+
* expanded
|
|
68
70
|
* status="mixed"
|
|
69
|
-
* label="
|
|
70
|
-
*
|
|
71
|
+
* label="Reports"
|
|
72
|
+
* ></obc-checkbox-item>
|
|
73
|
+
* <obc-checkbox-item
|
|
74
|
+
* level="2"
|
|
75
|
+
* status="checked"
|
|
76
|
+
* label="Monthly"
|
|
77
|
+
* description="Sent on the 1st"
|
|
71
78
|
* ></obc-checkbox-item>
|
|
72
79
|
* ```
|
|
73
80
|
*
|
|
74
|
-
* @
|
|
75
|
-
* @
|
|
76
|
-
* @
|
|
81
|
+
* @property status - Checkbox status: `unchecked`, `checked` or `mixed`.
|
|
82
|
+
* @property state - Item state: `enabled` or `disabled`.
|
|
83
|
+
* @property disabled - Disables the row and the inner checkbox.
|
|
84
|
+
* @property label - Text label; also the checkbox's accessible name.
|
|
85
|
+
* @property description - Secondary line under the label; hidden when empty.
|
|
86
|
+
* @property level - Depth in a nested list. 0 is a plain row; 1 reserves the chevron slot; each level above 1 adds a spacer.
|
|
87
|
+
* @property expandable - Shows the chevron button that fires `expand-toggle`.
|
|
88
|
+
* @property expanded - Whether the row's children are shown; drives the chevron direction and `aria-expanded`.
|
|
89
|
+
* @availableWhen expanded expandable==true
|
|
90
|
+
* @property hoverStyle - Which box shows hover and focus: the whole row (`touch-target`) or the checkbox (`visual-target`).
|
|
91
|
+
* @property ariaDescribedBy - Forwarded to the inner checkbox as `aria-describedby`.
|
|
77
92
|
* @fires {ObcCheckboxChangeEvent} change - Emitted when status changes.
|
|
93
|
+
* @fires {ObcCheckboxItemExpandToggleEvent} expand-toggle - Emitted when the chevron is activated; detail is the next `expanded` value. Bubbles and is composed.
|
|
78
94
|
* @stable
|
|
79
95
|
*/
|
|
80
96
|
@customElement('obc-checkbox-item')
|
|
@@ -88,11 +104,13 @@ export class ObcCheckboxItem extends LitElement {
|
|
|
88
104
|
|
|
89
105
|
@property({type: String}) label = '';
|
|
90
106
|
|
|
91
|
-
@property({type:
|
|
107
|
+
@property({type: String}) description = '';
|
|
108
|
+
|
|
109
|
+
@property({type: Number, reflect: true}) level = 0;
|
|
92
110
|
|
|
93
|
-
@property({type: Boolean, reflect: true})
|
|
111
|
+
@property({type: Boolean, reflect: true}) expandable = false;
|
|
94
112
|
|
|
95
|
-
@property({type: Boolean, reflect: true})
|
|
113
|
+
@property({type: Boolean, reflect: true}) expanded = false;
|
|
96
114
|
|
|
97
115
|
@property({type: String}) hoverStyle: ObcCheckboxItemHoverStyle =
|
|
98
116
|
ObcCheckboxItemHoverStyle.touchTarget;
|
|
@@ -102,10 +120,13 @@ export class ObcCheckboxItem extends LitElement {
|
|
|
102
120
|
|
|
103
121
|
@query('obc-checkbox') private checkboxElement?: HTMLElement;
|
|
104
122
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
123
|
+
@query('.chevron-button') private chevronButton?: HTMLElement;
|
|
124
|
+
|
|
125
|
+
private get isDisabled(): boolean {
|
|
126
|
+
return this.disabled || this.state === ObcCheckboxItemState.disabled;
|
|
127
|
+
}
|
|
108
128
|
|
|
129
|
+
private toggleStatusFromItem() {
|
|
109
130
|
if (this.status === CheckboxStatus.checked) {
|
|
110
131
|
this.status = CheckboxStatus.unchecked;
|
|
111
132
|
} else {
|
|
@@ -116,22 +137,33 @@ export class ObcCheckboxItem extends LitElement {
|
|
|
116
137
|
new CustomEvent('change', {
|
|
117
138
|
detail: {
|
|
118
139
|
status: this.status,
|
|
119
|
-
disabled: isDisabled,
|
|
140
|
+
disabled: this.isDisabled,
|
|
120
141
|
},
|
|
121
142
|
})
|
|
122
143
|
);
|
|
123
144
|
}
|
|
124
145
|
|
|
125
146
|
private handleItemClick(event: MouseEvent) {
|
|
126
|
-
if (this.
|
|
147
|
+
if (this.isDisabled) return;
|
|
127
148
|
|
|
128
149
|
const path = event.composedPath();
|
|
129
|
-
|
|
130
|
-
if (
|
|
150
|
+
if (this.checkboxElement && path.includes(this.checkboxElement)) return;
|
|
151
|
+
if (this.chevronButton && path.includes(this.chevronButton)) return;
|
|
131
152
|
|
|
132
153
|
this.toggleStatusFromItem();
|
|
133
154
|
}
|
|
134
155
|
|
|
156
|
+
private handleChevronClick(event: MouseEvent) {
|
|
157
|
+
event.stopPropagation();
|
|
158
|
+
this.dispatchEvent(
|
|
159
|
+
new CustomEvent<boolean>('expand-toggle', {
|
|
160
|
+
detail: !this.expanded,
|
|
161
|
+
bubbles: true,
|
|
162
|
+
composed: true,
|
|
163
|
+
})
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
135
167
|
private handleCheckboxChange(event: Event) {
|
|
136
168
|
const checkboxEvent = event as ObcCheckboxChangeEvent;
|
|
137
169
|
this.status = checkboxEvent.detail.status;
|
|
@@ -147,15 +179,35 @@ export class ObcCheckboxItem extends LitElement {
|
|
|
147
179
|
this.checkboxElement?.focus(options);
|
|
148
180
|
}
|
|
149
181
|
|
|
182
|
+
private renderChevron() {
|
|
183
|
+
if (!this.expandable) return nothing;
|
|
184
|
+
return html`<button
|
|
185
|
+
type="button"
|
|
186
|
+
class="chevron-button"
|
|
187
|
+
aria-expanded=${this.expanded ? 'true' : 'false'}
|
|
188
|
+
aria-label=${ifDefined(this.label.trim() || undefined)}
|
|
189
|
+
?disabled=${this.isDisabled}
|
|
190
|
+
@click=${this.handleChevronClick}
|
|
191
|
+
>
|
|
192
|
+
<span class="chevron-visible">
|
|
193
|
+
${this.expanded
|
|
194
|
+
? html`<obi-chevron-down-google
|
|
195
|
+
class="chevron-icon"
|
|
196
|
+
></obi-chevron-down-google>`
|
|
197
|
+
: html`<obi-chevron-right-google
|
|
198
|
+
class="chevron-icon"
|
|
199
|
+
></obi-chevron-right-google>`}
|
|
200
|
+
</span>
|
|
201
|
+
</button>`;
|
|
202
|
+
}
|
|
203
|
+
|
|
150
204
|
override render() {
|
|
151
|
-
const isDisabled =
|
|
152
|
-
this.disabled || this.state === ObcCheckboxItemState.disabled;
|
|
205
|
+
const isDisabled = this.isDisabled;
|
|
153
206
|
const hasCheckboxHoverEffects = !(
|
|
154
207
|
this.hoverStyle === ObcCheckboxItemHoverStyle.touchTarget && !isDisabled
|
|
155
208
|
);
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
const shouldRenderChevronIcon = this.isNested && this.isLevel1;
|
|
209
|
+
const depth = Math.max(0, Math.floor(this.level) - 1);
|
|
210
|
+
const hasChevronSlot = this.level >= 1 || this.expandable;
|
|
159
211
|
const checkboxAriaLabel =
|
|
160
212
|
this.label.trim().length > 0 ? this.label : undefined;
|
|
161
213
|
|
|
@@ -165,24 +217,21 @@ export class ObcCheckboxItem extends LitElement {
|
|
|
165
217
|
'checkbox-item-container': true,
|
|
166
218
|
[`status-${this.status}`]: true,
|
|
167
219
|
[`hover-style-${this.hoverStyle}`]: true,
|
|
168
|
-
'is-nested':
|
|
169
|
-
'
|
|
170
|
-
'is-level-2': this.isLevel2,
|
|
220
|
+
'is-nested': hasChevronSlot,
|
|
221
|
+
'has-description': this.description !== '',
|
|
171
222
|
disabled: isDisabled,
|
|
172
223
|
})}
|
|
173
224
|
@click=${this.handleItemClick}
|
|
174
225
|
>
|
|
175
|
-
${
|
|
176
|
-
? html`<div
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
: nothing}
|
|
182
|
-
</div>`
|
|
226
|
+
${depth > 0
|
|
227
|
+
? html`<div
|
|
228
|
+
class="nested-spacer"
|
|
229
|
+
aria-hidden="true"
|
|
230
|
+
style=${styleMap({'--checkbox-item-depth': String(depth)})}
|
|
231
|
+
></div>`
|
|
183
232
|
: nothing}
|
|
184
|
-
${
|
|
185
|
-
? html`<div class="
|
|
233
|
+
${hasChevronSlot
|
|
234
|
+
? html`<div class="chevron-container">${this.renderChevron()}</div>`
|
|
186
235
|
: nothing}
|
|
187
236
|
<div class="content-container">
|
|
188
237
|
<obc-checkbox
|
|
@@ -196,6 +245,11 @@ export class ObcCheckboxItem extends LitElement {
|
|
|
196
245
|
></obc-checkbox>
|
|
197
246
|
<div class="checkbox-label-container">
|
|
198
247
|
<span class="checkbox-label">${this.label}</span>
|
|
248
|
+
${this.description
|
|
249
|
+
? html`<span class="checkbox-description"
|
|
250
|
+
>${this.description}</span
|
|
251
|
+
>`
|
|
252
|
+
: nothing}
|
|
199
253
|
</div>
|
|
200
254
|
</div>
|
|
201
255
|
</div>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {describe, expect, it} from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
computeHiddenRows,
|
|
4
|
+
type CheckboxListRow,
|
|
5
|
+
} from './checkbox-list-visibility.js';
|
|
6
|
+
|
|
7
|
+
const row = (
|
|
8
|
+
level: number,
|
|
9
|
+
expandable = false,
|
|
10
|
+
expanded = false
|
|
11
|
+
): CheckboxListRow => ({level, expandable, expanded});
|
|
12
|
+
|
|
13
|
+
describe('computeHiddenRows', () => {
|
|
14
|
+
it('shows every row when nothing is collapsed', () => {
|
|
15
|
+
expect(
|
|
16
|
+
computeHiddenRows([row(1, true, true), row(2), row(2), row(1)])
|
|
17
|
+
).toEqual([false, false, false, false]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('hides descendants of a collapsed row until a sibling or ancestor', () => {
|
|
21
|
+
expect(
|
|
22
|
+
computeHiddenRows([row(1, true, false), row(2), row(3), row(1)])
|
|
23
|
+
).toEqual([false, true, true, false]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('a collapsed row nested under an open one hides only its own subtree', () => {
|
|
27
|
+
expect(
|
|
28
|
+
computeHiddenRows([
|
|
29
|
+
row(1, true, true),
|
|
30
|
+
row(2, true, false),
|
|
31
|
+
row(3),
|
|
32
|
+
row(2),
|
|
33
|
+
row(1),
|
|
34
|
+
])
|
|
35
|
+
).toEqual([false, false, true, false, false]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('a collapsed row that is itself hidden does not change the cut level', () => {
|
|
39
|
+
expect(
|
|
40
|
+
computeHiddenRows([
|
|
41
|
+
row(1, true, false),
|
|
42
|
+
row(2, true, true),
|
|
43
|
+
row(3),
|
|
44
|
+
row(1),
|
|
45
|
+
])
|
|
46
|
+
).toEqual([false, true, true, false]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('non-expandable rows never collapse anything', () => {
|
|
50
|
+
expect(computeHiddenRows([row(1), row(2), row(2)])).toEqual([
|
|
51
|
+
false,
|
|
52
|
+
false,
|
|
53
|
+
false,
|
|
54
|
+
]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('treats level 0 like any other depth', () => {
|
|
58
|
+
expect(computeHiddenRows([row(0, true, false), row(1), row(0)])).toEqual([
|
|
59
|
+
false,
|
|
60
|
+
true,
|
|
61
|
+
false,
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('returns an empty array for no rows', () => {
|
|
66
|
+
expect(computeHiddenRows([])).toEqual([]);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visibility of a flat checkbox-item sequence
|
|
3
|
+
*
|
|
4
|
+
* `<obc-checkbox-list>` keeps its rows flat and infers the tree from each
|
|
5
|
+
* row's `level`. A row is hidden while a preceding, visible, collapsed
|
|
6
|
+
* expandable row of smaller level is still "open" — that is, until a row of
|
|
7
|
+
* equal or smaller level closes it. Kept free of DOM so it can be unit-tested.
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
export interface CheckboxListRow {
|
|
11
|
+
level: number;
|
|
12
|
+
expandable: boolean;
|
|
13
|
+
expanded: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function computeHiddenRows(rows: readonly CheckboxListRow[]): boolean[] {
|
|
17
|
+
let cutLevel: number | null = null;
|
|
18
|
+
return rows.map((row) => {
|
|
19
|
+
if (cutLevel !== null && row.level > cutLevel) return true;
|
|
20
|
+
cutLevel = row.expandable && !row.expanded ? row.level : null;
|
|
21
|
+
return false;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {afterEach, describe, expect, it} from 'vitest';
|
|
2
|
+
import './checkbox-list.js';
|
|
3
|
+
import '../checkbox-item/checkbox-item.js';
|
|
4
|
+
import type {ObcCheckboxItem} from '../checkbox-item/checkbox-item.js';
|
|
5
|
+
import {ObcCheckboxItemHoverStyle} from '../checkbox-item/checkbox-item.js';
|
|
6
|
+
|
|
7
|
+
const nextTick = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
8
|
+
|
|
9
|
+
function item(level: number, expandable = false, expanded = false) {
|
|
10
|
+
const el = document.createElement('obc-checkbox-item');
|
|
11
|
+
el.label = `Level ${level}`;
|
|
12
|
+
el.level = level;
|
|
13
|
+
el.expandable = expandable;
|
|
14
|
+
el.expanded = expanded;
|
|
15
|
+
return el;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function mount(items: ObcCheckboxItem[]) {
|
|
19
|
+
const list = document.createElement('obc-checkbox-list');
|
|
20
|
+
items.forEach((i) => list.appendChild(i));
|
|
21
|
+
document.body.appendChild(list);
|
|
22
|
+
await list.updateComplete;
|
|
23
|
+
await nextTick();
|
|
24
|
+
return list;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
document.body.innerHTML = '';
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('obc-checkbox-list', () => {
|
|
32
|
+
it('hides rows under a collapsed parent', async () => {
|
|
33
|
+
const rows = [item(1, true, false), item(2), item(1)];
|
|
34
|
+
await mount(rows);
|
|
35
|
+
expect(rows.map((r) => r.hidden)).toEqual([false, true, false]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('applies expand-toggle to the item and recomputes', async () => {
|
|
39
|
+
const rows = [item(1, true, false), item(2)];
|
|
40
|
+
await mount(rows);
|
|
41
|
+
rows[0]
|
|
42
|
+
.shadowRoot!.querySelector<HTMLButtonElement>('.chevron-button')!
|
|
43
|
+
.click();
|
|
44
|
+
await rows[0].updateComplete;
|
|
45
|
+
await nextTick();
|
|
46
|
+
expect(rows[0].expanded).toBe(true);
|
|
47
|
+
expect(rows[1].hidden).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('recomputes when expanded is changed from outside', async () => {
|
|
51
|
+
const rows = [item(1, true, true), item(2)];
|
|
52
|
+
await mount(rows);
|
|
53
|
+
rows[0].expanded = false;
|
|
54
|
+
await rows[0].updateComplete;
|
|
55
|
+
await nextTick();
|
|
56
|
+
expect(rows[1].hidden).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('forwards hoverStyle to every item, including late ones', async () => {
|
|
60
|
+
const rows = [item(0), item(0)];
|
|
61
|
+
const list = await mount(rows);
|
|
62
|
+
list.hoverStyle = ObcCheckboxItemHoverStyle.visualTarget;
|
|
63
|
+
await list.updateComplete;
|
|
64
|
+
expect(rows.map((r) => r.hoverStyle)).toEqual([
|
|
65
|
+
'visual-target',
|
|
66
|
+
'visual-target',
|
|
67
|
+
]);
|
|
68
|
+
const late = item(0);
|
|
69
|
+
list.appendChild(late);
|
|
70
|
+
await nextTick();
|
|
71
|
+
expect(late.hoverStyle).toBe('visual-target');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('recomputes when a collapsed row stops being expandable', async () => {
|
|
75
|
+
const rows = [item(1, true, false), item(2)];
|
|
76
|
+
await mount(rows);
|
|
77
|
+
expect(rows[1].hidden).toBe(true);
|
|
78
|
+
rows[0].expandable = false;
|
|
79
|
+
await rows[0].updateComplete;
|
|
80
|
+
await nextTick();
|
|
81
|
+
expect(rows[1].hidden).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('is the group and keeps a role the consumer set', async () => {
|
|
85
|
+
const list = await mount([]);
|
|
86
|
+
expect(list.getAttribute('role')).toBe('group');
|
|
87
|
+
const custom = document.createElement('obc-checkbox-list');
|
|
88
|
+
custom.setAttribute('role', 'presentation');
|
|
89
|
+
document.body.appendChild(custom);
|
|
90
|
+
await custom.updateComplete;
|
|
91
|
+
expect(custom.getAttribute('role')).toBe('presentation');
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type {Meta, StoryObj} from '@storybook/web-components-vite';
|
|
2
|
+
import {html} from 'lit';
|
|
3
|
+
import {ObcCheckboxList} from './checkbox-list.js';
|
|
4
|
+
import './checkbox-list.js';
|
|
5
|
+
import '../checkbox-item/checkbox-item.js';
|
|
6
|
+
import {ObcCheckboxItemHoverStyle} from '../checkbox-item/checkbox-item.js';
|
|
7
|
+
import {CheckboxStatus} from '../checkbox/checkbox.js';
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'UI Components/Selection Controls and Switches/Checkbox List',
|
|
11
|
+
tags: ['autodocs', '6.1', 'beta'],
|
|
12
|
+
component: 'obc-checkbox-list',
|
|
13
|
+
parameters: {
|
|
14
|
+
layout: 'centered',
|
|
15
|
+
actions: {
|
|
16
|
+
handles: ['change', 'expand-toggle'],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
hoverStyle: {
|
|
21
|
+
name: 'Hover style',
|
|
22
|
+
options: Object.values(ObcCheckboxItemHoverStyle),
|
|
23
|
+
control: {type: 'select'},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
args: {
|
|
27
|
+
hoverStyle: ObcCheckboxItemHoverStyle.touchTarget,
|
|
28
|
+
},
|
|
29
|
+
} satisfies Meta<ObcCheckboxList>;
|
|
30
|
+
|
|
31
|
+
export default meta;
|
|
32
|
+
type Story = StoryObj<ObcCheckboxList>;
|
|
33
|
+
|
|
34
|
+
const regularRows = html`
|
|
35
|
+
<obc-checkbox-item label="Label"></obc-checkbox-item>
|
|
36
|
+
<obc-checkbox-item
|
|
37
|
+
label="Label"
|
|
38
|
+
status=${CheckboxStatus.checked}
|
|
39
|
+
></obc-checkbox-item>
|
|
40
|
+
<obc-checkbox-item
|
|
41
|
+
label="Label"
|
|
42
|
+
status=${CheckboxStatus.checked}
|
|
43
|
+
></obc-checkbox-item>
|
|
44
|
+
<obc-checkbox-item label="Label"></obc-checkbox-item>
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
const nestedRows = html`
|
|
48
|
+
<obc-checkbox-item
|
|
49
|
+
level="1"
|
|
50
|
+
expandable
|
|
51
|
+
expanded
|
|
52
|
+
label="Label"
|
|
53
|
+
status=${CheckboxStatus.mixed}
|
|
54
|
+
></obc-checkbox-item>
|
|
55
|
+
<obc-checkbox-item
|
|
56
|
+
level="2"
|
|
57
|
+
label="Label"
|
|
58
|
+
status=${CheckboxStatus.checked}
|
|
59
|
+
></obc-checkbox-item>
|
|
60
|
+
<obc-checkbox-item level="2" label="Label"></obc-checkbox-item>
|
|
61
|
+
<obc-checkbox-item level="1" expandable label="Label"></obc-checkbox-item>
|
|
62
|
+
<obc-checkbox-item
|
|
63
|
+
level="2"
|
|
64
|
+
label="Hidden until expanded"
|
|
65
|
+
></obc-checkbox-item>
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
/** The Figma frame widths: 240px for a regular list, 320px for a nested one. */
|
|
69
|
+
const renderRegular: Story['render'] = (args) =>
|
|
70
|
+
html`<obc-checkbox-list style="width:240px" .hoverStyle=${args.hoverStyle}>
|
|
71
|
+
${regularRows}
|
|
72
|
+
</obc-checkbox-list>`;
|
|
73
|
+
|
|
74
|
+
const renderNested: Story['render'] = (args) =>
|
|
75
|
+
html`<obc-checkbox-list style="width:320px" .hoverStyle=${args.hoverStyle}>
|
|
76
|
+
${nestedRows}
|
|
77
|
+
</obc-checkbox-list>`;
|
|
78
|
+
|
|
79
|
+
export const Regular: Story = {
|
|
80
|
+
render: renderRegular,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const Nested: Story = {
|
|
84
|
+
render: renderNested,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const RegularVisualTarget: Story = {
|
|
88
|
+
args: {hoverStyle: ObcCheckboxItemHoverStyle.visualTarget},
|
|
89
|
+
render: renderRegular,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const NestedVisualTarget: Story = {
|
|
93
|
+
args: {hoverStyle: ObcCheckboxItemHoverStyle.visualTarget},
|
|
94
|
+
render: renderNested,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const WithDescriptions: Story = {
|
|
98
|
+
render: (args) =>
|
|
99
|
+
html`<obc-checkbox-list style="width:320px" .hoverStyle=${args.hoverStyle}>
|
|
100
|
+
<obc-checkbox-item
|
|
101
|
+
level="1"
|
|
102
|
+
expandable
|
|
103
|
+
expanded
|
|
104
|
+
label="Reports"
|
|
105
|
+
description="All report types"
|
|
106
|
+
status=${CheckboxStatus.mixed}
|
|
107
|
+
></obc-checkbox-item>
|
|
108
|
+
<obc-checkbox-item
|
|
109
|
+
level="2"
|
|
110
|
+
label="Monthly"
|
|
111
|
+
description="Sent on the 1st"
|
|
112
|
+
status=${CheckboxStatus.checked}
|
|
113
|
+
></obc-checkbox-item>
|
|
114
|
+
<obc-checkbox-item
|
|
115
|
+
level="2"
|
|
116
|
+
label="Quarterly"
|
|
117
|
+
description="Sent every third month"
|
|
118
|
+
></obc-checkbox-item>
|
|
119
|
+
</obc-checkbox-list>`,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/** `level` is not capped at 2: each level above 1 adds one more spacer. */
|
|
123
|
+
export const DeepNesting: Story = {
|
|
124
|
+
render: (args) =>
|
|
125
|
+
html`<obc-checkbox-list style="width:320px" .hoverStyle=${args.hoverStyle}>
|
|
126
|
+
<obc-checkbox-item
|
|
127
|
+
level="1"
|
|
128
|
+
expandable
|
|
129
|
+
expanded
|
|
130
|
+
label="Documents"
|
|
131
|
+
status=${CheckboxStatus.mixed}
|
|
132
|
+
></obc-checkbox-item>
|
|
133
|
+
<obc-checkbox-item
|
|
134
|
+
level="2"
|
|
135
|
+
expandable
|
|
136
|
+
expanded
|
|
137
|
+
label="Reports"
|
|
138
|
+
status=${CheckboxStatus.mixed}
|
|
139
|
+
></obc-checkbox-item>
|
|
140
|
+
<obc-checkbox-item
|
|
141
|
+
level="3"
|
|
142
|
+
label="Monthly"
|
|
143
|
+
status=${CheckboxStatus.checked}
|
|
144
|
+
></obc-checkbox-item>
|
|
145
|
+
<obc-checkbox-item level="3" label="Quarterly"></obc-checkbox-item>
|
|
146
|
+
<obc-checkbox-item
|
|
147
|
+
level="2"
|
|
148
|
+
expandable
|
|
149
|
+
label="Presentations"
|
|
150
|
+
></obc-checkbox-item>
|
|
151
|
+
<obc-checkbox-item
|
|
152
|
+
level="3"
|
|
153
|
+
label="Hidden until expanded"
|
|
154
|
+
></obc-checkbox-item>
|
|
155
|
+
<obc-checkbox-item
|
|
156
|
+
level="1"
|
|
157
|
+
expandable
|
|
158
|
+
label="Images"
|
|
159
|
+
></obc-checkbox-item>
|
|
160
|
+
</obc-checkbox-list>`,
|
|
161
|
+
};
|