@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.
Files changed (30) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +4736 -4470
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +206 -21
  4. package/dist/components/checkbox-item/checkbox-item.css.js +137 -12
  5. package/dist/components/checkbox-item/checkbox-item.css.js.map +1 -1
  6. package/dist/components/checkbox-item/checkbox-item.d.ts +68 -39
  7. package/dist/components/checkbox-item/checkbox-item.d.ts.map +1 -1
  8. package/dist/components/checkbox-item/checkbox-item.js +66 -25
  9. package/dist/components/checkbox-item/checkbox-item.js.map +1 -1
  10. package/dist/components/checkbox-list/checkbox-list-visibility.d.ts +16 -0
  11. package/dist/components/checkbox-list/checkbox-list-visibility.d.ts.map +1 -0
  12. package/dist/components/checkbox-list/checkbox-list-visibility.js +12 -0
  13. package/dist/components/checkbox-list/checkbox-list-visibility.js.map +1 -0
  14. package/dist/components/checkbox-list/checkbox-list.css.js +23 -0
  15. package/dist/components/checkbox-list/checkbox-list.css.js.map +1 -0
  16. package/dist/components/checkbox-list/checkbox-list.d.ts +66 -0
  17. package/dist/components/checkbox-list/checkbox-list.d.ts.map +1 -0
  18. package/dist/components/checkbox-list/checkbox-list.js +81 -0
  19. package/dist/components/checkbox-list/checkbox-list.js.map +1 -0
  20. package/package.json +1 -1
  21. package/src/components/checkbox-item/checkbox-item.css +63 -17
  22. package/src/components/checkbox-item/checkbox-item.spec.ts +115 -0
  23. package/src/components/checkbox-item/checkbox-item.stories.ts +82 -97
  24. package/src/components/checkbox-item/checkbox-item.ts +118 -64
  25. package/src/components/checkbox-list/checkbox-list-visibility.spec.ts +68 -0
  26. package/src/components/checkbox-list/checkbox-list-visibility.ts +23 -0
  27. package/src/components/checkbox-list/checkbox-list.css +13 -0
  28. package/src/components/checkbox-list/checkbox-list.spec.ts +93 -0
  29. package/src/components/checkbox-list/checkbox-list.stories.ts +161 -0
  30. 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-item wrapper for `<obc-checkbox>` with label
27
- * and optional nested indentation affordances.
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
- * Combines checkbox interaction with a row-like container used in menus and
31
- * hierarchical selection lists. The component proxies checkbox state changes,
32
- * supports touch-target or visual-target interaction behavior, and can render
33
- * nested structure indicators.
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 checkbox statuses: `unchecked`, `checked`, `mixed`.
37
- * - Item state control: `enabled` or `disabled`.
38
- * - Two hover/focus interaction modes: `touch-target` and `visual-target`.
39
- * - Optional nested layout controls via `isNested`, `isLevel1`, `isLevel2`.
40
- * - Forwards `aria-describedby` to the inner checkbox for assistive context.
41
- *
42
- * ### Variants
43
- * - **Nested level 1:** Chevron icon is shown.
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
- * - Use for checkbox rows that require text labels and optional hierarchy.
48
- * - Keep `status` as the source of truth for checked/mixed/unchecked value.
49
- * - Use `state="disabled"` or `disabled` to lock interaction.
50
- * - Prefer `hoverStyle="touch-target"` for standard list behavior.
51
- *
52
- * ### Slots / Content
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
- * ### Events
56
- * - `change` Fired when status changes (from row click or inner checkbox).
57
- * **detail:** `{ status, disabled }`
58
- *
59
- * ### Best Practices
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="Include archived items"
70
- * hoverStyle="touch-target"
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
- * @availableWhen isLevel1 isNested==true || hoverStyle==visual-target
75
- * @availableWhen isLevel2 isNested==true || hoverStyle==visual-target
76
- * @slot - No named slots.
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: Boolean, reflect: true}) isNested = false;
107
+ @property({type: String}) description = '';
108
+
109
+ @property({type: Number, reflect: true}) level = 0;
92
110
 
93
- @property({type: Boolean, reflect: true}) isLevel1 = false;
111
+ @property({type: Boolean, reflect: true}) expandable = false;
94
112
 
95
- @property({type: Boolean, reflect: true}) isLevel2 = false;
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
- private toggleStatusFromItem() {
106
- const isDisabled =
107
- this.disabled || this.state === ObcCheckboxItemState.disabled;
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.disabled || this.state === ObcCheckboxItemState.disabled) return;
147
+ if (this.isDisabled) return;
127
148
 
128
149
  const path = event.composedPath();
129
- const checkboxElement = this.checkboxElement;
130
- if (checkboxElement && path.includes(checkboxElement)) return;
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 shouldRenderNestedSpacer = this.isNested && this.isLevel2;
157
- const shouldRenderChevronContainer = this.isNested;
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': this.isNested,
169
- 'is-level-1': this.isLevel1,
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
- ${shouldRenderChevronContainer
176
- ? html`<div class="chevron-container" aria-hidden="true">
177
- ${shouldRenderChevronIcon
178
- ? html`<obi-chevron-right-google
179
- class="chevron-icon"
180
- ></obi-chevron-right-google>`
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
- ${shouldRenderNestedSpacer
185
- ? html`<div class="nested-spacer" aria-hidden="true"></div>`
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,13 @@
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ .list {
6
+ display: flex;
7
+ flex-direction: column;
8
+ align-items: stretch;
9
+ }
10
+
11
+ ::slotted([hidden]) {
12
+ display: none; /* collapsed rows leave layout; :host is display:block so [hidden] alone would not win */
13
+ }
@@ -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
+ };