@boostdev/design-system-components 1.1.2 → 1.2.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/AGENTS.md +38 -14
- package/dist/client.cjs +85 -103
- package/dist/client.css +610 -601
- package/dist/client.d.cts +13 -16
- package/dist/client.d.ts +13 -16
- package/dist/client.js +95 -113
- package/dist/index.cjs +85 -103
- package/dist/index.css +610 -601
- package/dist/index.d.cts +13 -16
- package/dist/index.d.ts +13 -16
- package/dist/index.js +95 -113
- package/dist/native/index.cjs +9 -8
- package/dist/native/index.d.cts +1 -1
- package/dist/native/index.d.ts +1 -1
- package/dist/native/index.js +9 -8
- package/dist/web-components/{chunk-K5CE6HSB.js → chunk-2FGATTGT.js} +79 -17
- package/dist/web-components/{chunk-O4UFI2RX.js → chunk-3REOIRDW.js} +13 -11
- package/dist/web-components/{chunk-5IPHEONG.js → chunk-6I2DBFQ7.js} +1 -0
- package/dist/web-components/{chunk-VM3YHGQ2.js → chunk-AJSXNDAP.js} +1 -2
- package/dist/web-components/{chunk-LSC4N56Q.js → chunk-BX3IPVOB.js} +1 -2
- package/dist/web-components/{chunk-CAPI25CU.js → chunk-DZRSJGPB.js} +3 -3
- package/dist/web-components/{chunk-VSS5ITNE.js → chunk-EBJM3VD4.js} +1 -3
- package/dist/web-components/{chunk-O7I63SQX.js → chunk-HHHRF2PS.js} +6 -12
- package/dist/web-components/{chunk-OTX4COSV.js → chunk-JUKB3BUP.js} +3 -4
- package/dist/web-components/{chunk-IQGLIQSO.js → chunk-N6IMUOY4.js} +2 -5
- package/dist/web-components/{chunk-CJ5ZOO42.js → chunk-OCODKRVZ.js} +68 -44
- package/dist/web-components/{chunk-QDRH46TF.js → chunk-QLZ2362S.js} +1 -3
- package/dist/web-components/{chunk-IK3PTFZ4.js → chunk-T6AETZRP.js} +1 -3
- package/dist/web-components/{chunk-4BX6AWXX.js → chunk-X3FKVHLK.js} +2 -4
- package/dist/web-components/{chunk-A67LCT7C.js → chunk-XNA6WTXG.js} +3 -4
- package/dist/web-components/{chunk-XIENXR7H.js → chunk-YRXCVKHV.js} +1 -3
- package/dist/web-components/{chunk-6T3RKUKG.js → chunk-ZTC6GRP7.js} +1 -2
- package/dist/web-components/globals.js +1 -1
- package/dist/web-components/index.d.ts +571 -1
- package/dist/web-components/index.js +1515 -18
- package/dist/web-components/interaction/bds-accordion.js +1 -1
- package/dist/web-components/interaction/bds-button.d.ts +2 -2
- package/dist/web-components/interaction/bds-button.js +1 -1
- package/dist/web-components/interaction/bds-collapsible.js +1 -1
- package/dist/web-components/interaction/bds-dialog.js +1 -1
- package/dist/web-components/interaction/bds-drawer.js +1 -1
- package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
- package/dist/web-components/interaction/form/bds-combobox.js +1 -1
- package/dist/web-components/interaction/form/bds-number-input.js +1 -1
- package/dist/web-components/interaction/form/bds-radio.js +1 -1
- package/dist/web-components/interaction/form/bds-segmented-control.d.ts +20 -3
- package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
- package/dist/web-components/interaction/form/bds-select.js +1 -1
- package/dist/web-components/interaction/form/bds-switch.js +1 -1
- package/dist/web-components/interaction/form/bds-textarea.js +1 -1
- package/dist/web-components/ui/bds-alert.js +1 -1
- package/dist/web-components/ui/bds-card.js +1 -1
- package/dist/web-components/ui/bds-notification-banner.js +1 -1
- package/package.json +2 -2
- package/src/components/interaction/Button/Button.module.css +12 -11
- package/src/components/interaction/Button/Button.native.tsx +10 -9
- package/src/components/interaction/Button/Button.tsx +1 -1
- package/src/components/interaction/Command/Command.module.css +3 -7
- package/src/components/interaction/Dialog/Dialog.module.css +7 -5
- package/src/components/interaction/Drawer/Drawer.module.css +48 -25
- package/src/components/interaction/Drawer/Drawer.tsx +21 -17
- package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +1 -3
- package/src/components/interaction/Popover/Popover.module.css +1 -3
- package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -3
- package/src/components/interaction/form/Combobox/Combobox.module.css +2 -6
- package/src/components/interaction/form/FormInput/FormInput.module.css +1 -3
- package/src/components/interaction/form/NumberInput/NumberInput.module.css +16 -4
- package/src/components/interaction/form/Radio/Radio.module.css +6 -16
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +74 -25
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +65 -36
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +127 -56
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.stories.tsx +89 -72
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +40 -62
- package/src/components/interaction/form/SegmentedControl/index.ts +1 -1
- package/src/components/interaction/form/Select/Select.module.css +2 -4
- package/src/components/interaction/form/Switch/Switch.module.css +5 -7
- package/src/components/interaction/form/Switch/Switch.native.spec.tsx +9 -9
- package/src/components/interaction/form/Switch/Switch.native.tsx +2 -2
- package/src/components/interaction/form/Textarea/Textarea.module.css +1 -3
- package/src/components/interaction/form/atoms/InputContainer.stories.tsx +64 -0
- package/src/components/interaction/form/atoms/Label.stories.tsx +33 -0
- package/src/components/interaction/form/atoms/Message.stories.tsx +33 -0
- package/src/components/layout/Card/Card.module.css +1 -3
- package/src/components/ui/Accordion/Accordion.module.css +1 -2
- package/src/components/ui/Alert/Alert.module.css +1 -2
- package/src/components/ui/Calendar/Calendar.module.css +2 -5
- package/src/components/ui/Carousel/Carousel.module.css +1 -3
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -2
- package/src/components/ui/Pagination/Pagination.module.css +1 -2
- package/src/components/ui/SkipLink/SkipLink.module.css +1 -2
- package/src/components/ui/Table/Table.module.css +1 -2
- package/src/css/bdc.css +16 -11
- package/src/index.ts +1 -1
- package/src/stories/Introduction.mdx +2 -1
- package/src/web-components/globals.ts +3 -3
- package/src/web-components/index.ts +12 -0
- package/src/web-components/interaction/BdsAccordion.mdx +103 -0
- package/src/web-components/interaction/BdsAccordion.stories.tsx +94 -0
- package/src/web-components/interaction/BdsCollapsible.mdx +116 -0
- package/src/web-components/interaction/BdsCollapsible.stories.tsx +68 -0
- package/src/web-components/interaction/BdsDialog.mdx +110 -0
- package/src/web-components/interaction/BdsDialog.stories.tsx +157 -0
- package/src/web-components/interaction/BdsDrawer.mdx +108 -0
- package/src/web-components/interaction/BdsDrawer.stories.tsx +196 -0
- package/src/web-components/interaction/BdsDropdownMenu.mdx +108 -0
- package/src/web-components/interaction/BdsDropdownMenu.stories.tsx +91 -0
- package/src/web-components/interaction/BdsSkipLink.mdx +90 -0
- package/src/web-components/interaction/BdsSkipLink.stories.tsx +68 -0
- package/src/web-components/interaction/BdsTabs.mdx +117 -0
- package/src/web-components/interaction/BdsTabs.stories.tsx +94 -0
- package/src/web-components/interaction/BdsTooltip.mdx +104 -0
- package/src/web-components/interaction/BdsTooltip.stories.tsx +87 -0
- package/src/web-components/interaction/bds-accordion.ts +1 -2
- package/src/web-components/interaction/bds-button.ts +15 -13
- package/src/web-components/interaction/bds-collapsible.ts +1 -0
- package/src/web-components/interaction/bds-dialog.ts +2 -5
- package/src/web-components/interaction/bds-drawer.ts +70 -44
- package/src/web-components/interaction/bds-dropdown-menu-item.ts +124 -0
- package/src/web-components/interaction/bds-dropdown-menu.spec.ts +102 -0
- package/src/web-components/interaction/bds-dropdown-menu.ts +200 -0
- package/src/web-components/interaction/form/BdsCheckbox.mdx +76 -0
- package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +72 -0
- package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +70 -0
- package/src/web-components/interaction/form/BdsCheckboxGroup.stories.tsx +81 -0
- package/src/web-components/interaction/form/BdsCombobox.mdx +71 -0
- package/src/web-components/interaction/form/BdsCombobox.stories.tsx +93 -0
- package/src/web-components/interaction/form/BdsFileInput.mdx +79 -0
- package/src/web-components/interaction/form/BdsFileInput.stories.tsx +69 -0
- package/src/web-components/interaction/form/BdsFormInput.mdx +98 -0
- package/src/web-components/interaction/form/BdsFormInput.stories.tsx +139 -0
- package/src/web-components/interaction/form/BdsNumberInput.mdx +70 -0
- package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +68 -0
- package/src/web-components/interaction/form/BdsRadio.mdx +72 -0
- package/src/web-components/interaction/form/BdsRadio.stories.tsx +58 -0
- package/src/web-components/interaction/form/BdsRadioGroup.mdx +73 -0
- package/src/web-components/interaction/form/BdsRadioGroup.stories.tsx +88 -0
- package/src/web-components/interaction/form/BdsSegmentedControl.mdx +95 -0
- package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +102 -0
- package/src/web-components/interaction/form/BdsSelect.mdx +76 -0
- package/src/web-components/interaction/form/BdsSelect.stories.tsx +84 -0
- package/src/web-components/interaction/form/BdsSlider.mdx +77 -0
- package/src/web-components/interaction/form/BdsSlider.stories.tsx +68 -0
- package/src/web-components/interaction/form/BdsSwitch.mdx +72 -0
- package/src/web-components/interaction/form/BdsSwitch.stories.tsx +58 -0
- package/src/web-components/interaction/form/BdsTextarea.mdx +73 -0
- package/src/web-components/interaction/form/BdsTextarea.stories.tsx +70 -0
- package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +55 -0
- package/src/web-components/interaction/form/bds-checkbox-group.ts +117 -0
- package/src/web-components/interaction/form/bds-checkbox.ts +1 -3
- package/src/web-components/interaction/form/bds-combobox.ts +1 -3
- package/src/web-components/interaction/form/bds-form-input.spec.ts +83 -0
- package/src/web-components/interaction/form/bds-form-input.ts +268 -0
- package/src/web-components/interaction/form/bds-number-input.ts +3 -4
- package/src/web-components/interaction/form/bds-radio-group.spec.ts +62 -0
- package/src/web-components/interaction/form/bds-radio-group.ts +142 -0
- package/src/web-components/interaction/form/bds-radio.ts +6 -12
- package/src/web-components/interaction/form/bds-segmented-control.ts +96 -20
- package/src/web-components/interaction/form/bds-select.ts +2 -4
- package/src/web-components/interaction/form/bds-switch.ts +3 -4
- package/src/web-components/interaction/form/bds-textarea.ts +1 -3
- package/src/web-components/ui/BdsAvatar.mdx +76 -0
- package/src/web-components/ui/BdsAvatar.stories.tsx +48 -0
- package/src/web-components/ui/BdsBreadcrumb.mdx +66 -0
- package/src/web-components/ui/BdsBreadcrumb.stories.tsx +49 -0
- package/src/web-components/ui/BdsButtonGroup.mdx +69 -0
- package/src/web-components/ui/BdsButtonGroup.stories.tsx +66 -0
- package/src/web-components/ui/BdsCalendar.mdx +93 -0
- package/src/web-components/ui/BdsCalendar.stories.tsx +63 -0
- package/src/web-components/ui/BdsCard.mdx +88 -0
- package/src/web-components/ui/BdsCard.stories.tsx +67 -0
- package/src/web-components/ui/BdsCarousel.mdx +83 -0
- package/src/web-components/ui/BdsCarousel.stories.tsx +96 -0
- package/src/web-components/ui/BdsDescriptionList.mdx +64 -0
- package/src/web-components/ui/BdsDescriptionList.stories.tsx +64 -0
- package/src/web-components/ui/BdsIconWrapper.mdx +70 -0
- package/src/web-components/ui/BdsIconWrapper.stories.tsx +81 -0
- package/src/web-components/ui/BdsLink.mdx +79 -0
- package/src/web-components/ui/BdsLink.stories.tsx +63 -0
- package/src/web-components/ui/BdsLoading.mdx +58 -0
- package/src/web-components/ui/BdsLoading.stories.tsx +35 -0
- package/src/web-components/ui/BdsNotificationBanner.mdx +85 -0
- package/src/web-components/ui/BdsNotificationBanner.stories.tsx +84 -0
- package/src/web-components/ui/BdsPagination.mdx +74 -0
- package/src/web-components/ui/BdsPagination.stories.tsx +36 -0
- package/src/web-components/ui/BdsProgress.mdx +70 -0
- package/src/web-components/ui/BdsProgress.stories.tsx +96 -0
- package/src/web-components/ui/BdsProgressCircle.mdx +70 -0
- package/src/web-components/ui/BdsProgressCircle.stories.tsx +57 -0
- package/src/web-components/ui/BdsRating.mdx +61 -0
- package/src/web-components/ui/BdsRating.stories.tsx +45 -0
- package/src/web-components/ui/BdsSectionHeader.mdx +72 -0
- package/src/web-components/ui/BdsSectionHeader.stories.tsx +54 -0
- package/src/web-components/ui/BdsSeparator.mdx +77 -0
- package/src/web-components/ui/BdsSeparator.stories.tsx +55 -0
- package/src/web-components/ui/BdsSkeleton.mdx +61 -0
- package/src/web-components/ui/BdsSkeleton.stories.tsx +50 -0
- package/src/web-components/ui/BdsTable.mdx +81 -0
- package/src/web-components/ui/BdsTable.stories.tsx +83 -0
- package/src/web-components/ui/BdsTypography.mdx +74 -0
- package/src/web-components/ui/BdsTypography.stories.tsx +52 -0
- package/src/web-components/ui/bds-alert.ts +1 -2
- package/src/web-components/ui/bds-button-group.spec.ts +40 -0
- package/src/web-components/ui/bds-button-group.ts +78 -0
- package/src/web-components/ui/bds-calendar.spec.ts +91 -0
- package/src/web-components/ui/bds-calendar.ts +427 -0
- package/src/web-components/ui/bds-card.ts +1 -3
- package/src/web-components/ui/bds-carousel.spec.ts +64 -0
- package/src/web-components/ui/bds-carousel.ts +296 -0
- package/src/web-components/ui/bds-notification-banner.ts +1 -2
- package/src/web-components/ui/bds-pagination.spec.ts +67 -0
- package/src/web-components/ui/bds-pagination.ts +197 -0
- package/src/web-components/ui/bds-table.spec.ts +45 -0
- package/src/web-components/ui/bds-table.ts +96 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { LitElement, css, html } from 'lit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `<bds-radio-group>` — groups related radio buttons with a shared label and name.
|
|
5
|
+
*
|
|
6
|
+
* Renders a `<fieldset>` with a `<legend>`. Propagates the `name` attribute to
|
|
7
|
+
* all slotted `<bds-radio>` elements so radios form a mutually-exclusive set.
|
|
8
|
+
*
|
|
9
|
+
* Attributes:
|
|
10
|
+
* label — visible group label (rendered as `<legend>`)
|
|
11
|
+
* name — shared name forwarded to all slotted `<bds-radio>` elements
|
|
12
|
+
* error — error message shown below items
|
|
13
|
+
* hint — hint text shown below items
|
|
14
|
+
* disabled — disables the entire fieldset
|
|
15
|
+
* required — marks the group as required
|
|
16
|
+
*
|
|
17
|
+
* Slots:
|
|
18
|
+
* (default) — `<bds-radio>` elements
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* <bds-radio-group label="Preferred contact" name="contact">
|
|
22
|
+
* <bds-radio value="email">Email</bds-radio>
|
|
23
|
+
* <bds-radio value="phone">Phone</bds-radio>
|
|
24
|
+
* </bds-radio-group>
|
|
25
|
+
*/
|
|
26
|
+
export class BdsRadioGroup extends LitElement {
|
|
27
|
+
static styles = css`
|
|
28
|
+
:host {
|
|
29
|
+
display: block;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fieldset {
|
|
33
|
+
border: none;
|
|
34
|
+
margin: 0;
|
|
35
|
+
padding: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.legend {
|
|
39
|
+
font-size: var(--bds-font_size--body--s);
|
|
40
|
+
font-family: var(--bds-font_family--body);
|
|
41
|
+
font-weight: var(--bds-font_weight--semibold);
|
|
42
|
+
color: var(--bds-color_on-bg);
|
|
43
|
+
margin-block-end: var(--bds-space_xs);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.required {
|
|
47
|
+
color: var(--bds-color_error);
|
|
48
|
+
margin-inline-start: var(--bds-space_xxxs);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.items {
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
gap: var(--bds-space_xs);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.message {
|
|
58
|
+
margin-block-start: var(--bds-space_xs);
|
|
59
|
+
font-size: var(--bds-font_size--body--s);
|
|
60
|
+
font-family: var(--bds-font_family--body);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.message--error {
|
|
64
|
+
color: var(--bds-color_error);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.message--hint {
|
|
68
|
+
color: var(--bds-color_on-bg--subtle);
|
|
69
|
+
}
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
static properties = {
|
|
73
|
+
label: { type: String },
|
|
74
|
+
name: { type: String, reflect: true },
|
|
75
|
+
error: { type: String },
|
|
76
|
+
hint: { type: String },
|
|
77
|
+
disabled: { type: Boolean, reflect: true },
|
|
78
|
+
required: { type: Boolean, reflect: true },
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
declare label: string;
|
|
82
|
+
declare name: string;
|
|
83
|
+
declare error: string | undefined;
|
|
84
|
+
declare hint: string | undefined;
|
|
85
|
+
declare disabled: boolean;
|
|
86
|
+
declare required: boolean;
|
|
87
|
+
|
|
88
|
+
constructor() {
|
|
89
|
+
super();
|
|
90
|
+
this.label = '';
|
|
91
|
+
this.name = '';
|
|
92
|
+
this.disabled = false;
|
|
93
|
+
this.required = false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private _propagateName = () => {
|
|
97
|
+
if (!this.name) return;
|
|
98
|
+
this.querySelectorAll('bds-radio').forEach(radio => {
|
|
99
|
+
(radio as HTMLElement).setAttribute('name', this.name);
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
connectedCallback() {
|
|
104
|
+
super.connectedCallback();
|
|
105
|
+
// Propagate name after slot content has been parsed
|
|
106
|
+
Promise.resolve().then(this._propagateName);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
updated(changed: Map<string, unknown>) {
|
|
110
|
+
super.updated(changed);
|
|
111
|
+
if (changed.has('name')) {
|
|
112
|
+
this._propagateName();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
render() {
|
|
117
|
+
return html`
|
|
118
|
+
<fieldset ?disabled=${this.disabled}>
|
|
119
|
+
<legend class="legend">
|
|
120
|
+
${this.label}
|
|
121
|
+
${this.required ? html`<span class="required" aria-hidden="true"> *</span>` : ''}
|
|
122
|
+
</legend>
|
|
123
|
+
<div class="items">
|
|
124
|
+
<slot @slotchange=${this._propagateName}></slot>
|
|
125
|
+
</div>
|
|
126
|
+
${this.error
|
|
127
|
+
? html`<p class="message message--error" role="alert">${this.error}</p>`
|
|
128
|
+
: this.hint
|
|
129
|
+
? html`<p class="message message--hint">${this.hint}</p>`
|
|
130
|
+
: ''}
|
|
131
|
+
</fieldset>
|
|
132
|
+
`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
customElements.define('bds-radio-group', BdsRadioGroup);
|
|
137
|
+
|
|
138
|
+
declare global {
|
|
139
|
+
interface HTMLElementTagNameMap {
|
|
140
|
+
'bds-radio-group': BdsRadioGroup;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -50,10 +50,8 @@ export class BdsRadio extends LitElement {
|
|
|
50
50
|
--bdc_color: currentcolor;
|
|
51
51
|
--bdc-outline_radius: 50%;
|
|
52
52
|
|
|
53
|
-
outline: var(--bdc-outline_width) solid var(--bdc_color);
|
|
54
|
-
outline-offset: var(--bdc-outline_offset);
|
|
55
53
|
border-radius: 50%;
|
|
56
|
-
box-shadow: var(--radio_shadow, var(--bdc-outline_shadow));
|
|
54
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--radio_shadow, var(--bdc-outline_shadow));
|
|
57
55
|
border: none;
|
|
58
56
|
appearance: none;
|
|
59
57
|
background-color: var(--radio_color_bg, var(--bds-color_bg));
|
|
@@ -63,18 +61,14 @@ export class BdsRadio extends LitElement {
|
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
.input:checked {
|
|
66
|
-
background
|
|
64
|
+
background: radial-gradient(
|
|
65
|
+
circle,
|
|
66
|
+
var(--radio_color-active, var(--bdc-color_active)) 35%,
|
|
67
|
+
var(--radio_color_bg, var(--bds-color_bg)) 42%
|
|
68
|
+
);
|
|
67
69
|
--bdc_color: var(--radio_color-active, var(--bdc-color_active));
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
.input:checked::after {
|
|
71
|
-
content: '';
|
|
72
|
-
position: absolute;
|
|
73
|
-
inset: 25%;
|
|
74
|
-
border-radius: 50%;
|
|
75
|
-
background-color: var(--radio_color-on-active, var(--bdc-color_on-active));
|
|
76
|
-
}
|
|
77
|
-
|
|
78
72
|
.input:focus-visible {
|
|
79
73
|
outline: var(--bds-outline_default);
|
|
80
74
|
outline-offset: var(--bds-outline_offset);
|
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
import { LitElement, css, html } from 'lit';
|
|
1
|
+
import { LitElement, css, html, nothing } from 'lit';
|
|
2
2
|
|
|
3
3
|
export interface SegmentedOption {
|
|
4
4
|
value: string;
|
|
5
5
|
label: string;
|
|
6
6
|
disabled?: boolean;
|
|
7
|
+
/** When set, renders the option as an <a> link instead of a radio button */
|
|
8
|
+
href?: string;
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* `<bds-segmented-control>` — form-associated Segmented Control custom element.
|
|
11
13
|
*
|
|
12
|
-
* Renders a group of radio buttons styled as a unified segmented control.
|
|
14
|
+
* Renders a group of radio buttons (or links) styled as a unified segmented control.
|
|
13
15
|
* Passes a JSON `options` attribute because reactive slot content can't be
|
|
14
16
|
* easily converted to radio groups.
|
|
15
17
|
*
|
|
16
18
|
* Attributes:
|
|
17
19
|
* name — form field name (also used for the internal radio group)
|
|
18
20
|
* value — currently selected value
|
|
19
|
-
* options — JSON array of `{ value, label, disabled? }` option objects
|
|
21
|
+
* options — JSON array of `{ value, label, disabled?, href? }` option objects
|
|
20
22
|
* disabled — boolean; disables all options
|
|
23
|
+
* variant — "outline" (inset border on active item, default) | "filled" (sliding thumb)
|
|
21
24
|
*
|
|
22
25
|
* Events:
|
|
23
|
-
* change — fired when a new segment is selected
|
|
26
|
+
* change — fired when a new segment is selected (radio mode only)
|
|
24
27
|
*
|
|
25
28
|
* @example
|
|
26
29
|
* <bds-segmented-control
|
|
@@ -28,6 +31,13 @@ export interface SegmentedOption {
|
|
|
28
31
|
* value="list"
|
|
29
32
|
* options='[{"value":"list","label":"List"},{"value":"grid","label":"Grid"}]'
|
|
30
33
|
* ></bds-segmented-control>
|
|
34
|
+
*
|
|
35
|
+
* @example Outline variant with links
|
|
36
|
+
* <bds-segmented-control
|
|
37
|
+
* variant="outline"
|
|
38
|
+
* value="home"
|
|
39
|
+
* options='[{"value":"home","label":"Home","href":"/"},{"value":"about","label":"About","href":"/about"}]'
|
|
40
|
+
* ></bds-segmented-control>
|
|
31
41
|
*/
|
|
32
42
|
export class BdsSegmentedControl extends LitElement {
|
|
33
43
|
static formAssociated = true;
|
|
@@ -56,7 +66,7 @@ export class BdsSegmentedControl extends LitElement {
|
|
|
56
66
|
position: absolute;
|
|
57
67
|
inset-block: 0.25rem;
|
|
58
68
|
border-radius: calc(var(--bds-border_radius--s) - 2px);
|
|
59
|
-
background-color: var(--segmented_thumb-color, var(--bds-
|
|
69
|
+
background-color: var(--segmented_thumb-color, var(--bds-color_interactive));
|
|
60
70
|
box-shadow: var(--bds-shadow_m);
|
|
61
71
|
transition: inset-inline-start var(--bds-animation_transition-duration) var(--bds-animation_easing),
|
|
62
72
|
inline-size var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
@@ -87,10 +97,11 @@ export class BdsSegmentedControl extends LitElement {
|
|
|
87
97
|
transition: color var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
88
98
|
user-select: none;
|
|
89
99
|
white-space: nowrap;
|
|
100
|
+
text-decoration: none;
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
.item.--active {
|
|
93
|
-
color: var(--segmented_color--active, var(--bds-
|
|
104
|
+
color: var(--segmented_color--active, var(--bds-color_on-interactive));
|
|
94
105
|
}
|
|
95
106
|
|
|
96
107
|
.item.--disabled {
|
|
@@ -102,6 +113,44 @@ export class BdsSegmentedControl extends LitElement {
|
|
|
102
113
|
outline: var(--bds-outline_default);
|
|
103
114
|
outline-offset: var(--bds-outline_offset);
|
|
104
115
|
}
|
|
116
|
+
|
|
117
|
+
/* Outline variant: sliding inset-border indicator (positioned via JS like .thumb) */
|
|
118
|
+
.indicator {
|
|
119
|
+
position: absolute;
|
|
120
|
+
inset-block: 0.25rem;
|
|
121
|
+
border-radius: calc(var(--bds-border_radius--s) - 2px);
|
|
122
|
+
pointer-events: none;
|
|
123
|
+
z-index: 2;
|
|
124
|
+
display: none;
|
|
125
|
+
transition: inset-inline-start var(--bds-animation_transition-duration) var(--bds-animation_easing),
|
|
126
|
+
inline-size var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* Outline variant — no thumb, sliding inset-border indicator, interactive active color */
|
|
130
|
+
:host([variant='outline']) .thumb {
|
|
131
|
+
display: none;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
:host([variant='outline']) .item {
|
|
135
|
+
background-color: var(--segmented_item-bg, transparent);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
:host([variant='outline']) .item.--active {
|
|
139
|
+
color: var(--segmented_color--active, var(--bds-color_interactive));
|
|
140
|
+
background-color: var(--segmented_item-bg--active, var(--bds-color_bg));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
:host([variant='outline']) .indicator {
|
|
144
|
+
display: block;
|
|
145
|
+
box-shadow: inset 0 0 0 2px var(--bds-color_interactive);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@media (prefers-reduced-motion: reduce) {
|
|
149
|
+
.thumb,
|
|
150
|
+
.indicator {
|
|
151
|
+
transition: none;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
105
154
|
`;
|
|
106
155
|
|
|
107
156
|
static properties = {
|
|
@@ -109,12 +158,14 @@ export class BdsSegmentedControl extends LitElement {
|
|
|
109
158
|
value: { type: String },
|
|
110
159
|
options: { type: String },
|
|
111
160
|
disabled: { type: Boolean, reflect: true },
|
|
161
|
+
variant: { type: String, reflect: true },
|
|
112
162
|
};
|
|
113
163
|
|
|
114
164
|
declare name: string;
|
|
115
165
|
declare value: string;
|
|
116
166
|
declare options: string;
|
|
117
167
|
declare disabled: boolean;
|
|
168
|
+
declare variant: 'outline' | 'filled';
|
|
118
169
|
|
|
119
170
|
private _internals!: ElementInternals;
|
|
120
171
|
private readonly _uid = Math.random().toString(36).slice(2, 8);
|
|
@@ -126,6 +177,7 @@ export class BdsSegmentedControl extends LitElement {
|
|
|
126
177
|
this.value = '';
|
|
127
178
|
this.options = '[]';
|
|
128
179
|
this.disabled = false;
|
|
180
|
+
this.variant = 'outline';
|
|
129
181
|
}
|
|
130
182
|
|
|
131
183
|
private get _options(): SegmentedOption[] {
|
|
@@ -140,22 +192,35 @@ export class BdsSegmentedControl extends LitElement {
|
|
|
140
192
|
super.updated(changed);
|
|
141
193
|
if (changed.has('value') || changed.has('options')) {
|
|
142
194
|
this._internals.setFormValue?.(this.value || null);
|
|
143
|
-
this._updateThumb();
|
|
195
|
+
if (this.variant === 'filled') this._updateThumb();
|
|
196
|
+
if (this.variant === 'outline') this._updateIndicator();
|
|
197
|
+
}
|
|
198
|
+
if (changed.has('variant')) {
|
|
199
|
+
if (this.variant === 'filled') this._updateThumb();
|
|
200
|
+
if (this.variant === 'outline') this._updateIndicator();
|
|
144
201
|
}
|
|
145
202
|
}
|
|
146
203
|
|
|
147
|
-
private
|
|
148
|
-
|
|
149
|
-
const selectedIndex = Math.max(0, opts.findIndex(o => o.value === this.value));
|
|
150
|
-
const items = this.shadowRoot?.querySelectorAll<HTMLElement>('.item');
|
|
151
|
-
const thumb = this.shadowRoot?.querySelector<HTMLElement>('.thumb');
|
|
152
|
-
if (!items || !thumb || items.length === 0) return;
|
|
204
|
+
private _positionSlider(el: HTMLElement | null | undefined, items: NodeListOf<HTMLElement>, selectedIndex: number) {
|
|
205
|
+
if (!el || items.length === 0) return;
|
|
153
206
|
const item = items[selectedIndex];
|
|
154
207
|
if (!item) return;
|
|
155
208
|
const controlRect = (item.parentElement as HTMLElement).getBoundingClientRect();
|
|
156
209
|
const itemRect = item.getBoundingClientRect();
|
|
157
|
-
|
|
158
|
-
|
|
210
|
+
el.style.insetInlineStart = `${itemRect.left - controlRect.left}px`;
|
|
211
|
+
el.style.inlineSize = `${itemRect.width}px`;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private _updateThumb() {
|
|
215
|
+
const selectedIndex = Math.max(0, this._options.findIndex(o => o.value === this.value));
|
|
216
|
+
const items = this.shadowRoot?.querySelectorAll<HTMLElement>('.item');
|
|
217
|
+
this._positionSlider(this.shadowRoot?.querySelector<HTMLElement>('.thumb'), items!, selectedIndex);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private _updateIndicator() {
|
|
221
|
+
const selectedIndex = Math.max(0, this._options.findIndex(o => o.value === this.value));
|
|
222
|
+
const items = this.shadowRoot?.querySelectorAll<HTMLElement>('.item');
|
|
223
|
+
this._positionSlider(this.shadowRoot?.querySelector<HTMLElement>('.indicator'), items!, selectedIndex);
|
|
159
224
|
}
|
|
160
225
|
|
|
161
226
|
formResetCallback() {
|
|
@@ -174,15 +239,26 @@ export class BdsSegmentedControl extends LitElement {
|
|
|
174
239
|
return html`
|
|
175
240
|
<div class="control" role="group">
|
|
176
241
|
<span class="thumb" aria-hidden="true"></span>
|
|
242
|
+
<span class="indicator" aria-hidden="true"></span>
|
|
177
243
|
${opts.map((opt, i) => {
|
|
178
|
-
const id = `bds-seg-${this._uid}-${i}`;
|
|
179
244
|
const isActive = opt.value === this.value;
|
|
180
245
|
const isDisabled = this.disabled || opt.disabled;
|
|
246
|
+
const itemClass = `item ${isActive ? '--active' : ''} ${isDisabled ? '--disabled' : ''}`.trim();
|
|
247
|
+
|
|
248
|
+
if (opt.href) {
|
|
249
|
+
return html`
|
|
250
|
+
<a
|
|
251
|
+
class=${itemClass}
|
|
252
|
+
href=${isDisabled ? nothing : opt.href}
|
|
253
|
+
aria-current=${isActive ? 'page' : nothing}
|
|
254
|
+
?aria-disabled=${isDisabled}
|
|
255
|
+
>${opt.label}</a>
|
|
256
|
+
`;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const id = `bds-seg-${this._uid}-${i}`;
|
|
181
260
|
return html`
|
|
182
|
-
<label
|
|
183
|
-
class="item ${isActive ? '--active' : ''} ${isDisabled ? '--disabled' : ''}"
|
|
184
|
-
for=${id}
|
|
185
|
-
>
|
|
261
|
+
<label class=${itemClass} for=${id}>
|
|
186
262
|
<input
|
|
187
263
|
id=${id}
|
|
188
264
|
type="radio"
|
|
@@ -58,10 +58,8 @@ export class BdsSelect extends LitElement {
|
|
|
58
58
|
--bdc_color: currentcolor;
|
|
59
59
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
60
60
|
|
|
61
|
-
outline: var(--bdc-outline_width) solid var(--bdc_color);
|
|
62
|
-
outline-offset: var(--bdc-outline_offset);
|
|
63
61
|
border-radius: var(--select_radius, var(--bdc-outline_radius));
|
|
64
|
-
box-shadow: var(--select_shadow, var(--bdc-outline_shadow));
|
|
62
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--select_shadow, var(--bdc-outline_shadow));
|
|
65
63
|
background-color: var(--select_color_bg, var(--bds-color_bg));
|
|
66
64
|
color: var(--select_color, var(--bds-color_on-bg));
|
|
67
65
|
appearance: none;
|
|
@@ -86,7 +84,7 @@ export class BdsSelect extends LitElement {
|
|
|
86
84
|
pointer-events: none;
|
|
87
85
|
inline-size: 1rem;
|
|
88
86
|
block-size: 1rem;
|
|
89
|
-
color:
|
|
87
|
+
color: var(--select_chevron-color, var(--bds-color_interactive));
|
|
90
88
|
}
|
|
91
89
|
|
|
92
90
|
.chevron svg {
|
|
@@ -48,8 +48,7 @@ export class BdsSwitch extends LitElement {
|
|
|
48
48
|
background-color: var(--switch_color_bg, var(--bds-color_bg--subtle));
|
|
49
49
|
--bdc_color: currentcolor;
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
outline-offset: var(--bdc-outline_offset);
|
|
51
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
53
52
|
transition: background-color 0.2s ease;
|
|
54
53
|
flex-shrink: 0;
|
|
55
54
|
}
|
|
@@ -61,7 +60,7 @@ export class BdsSwitch extends LitElement {
|
|
|
61
60
|
inline-size: 1.1rem;
|
|
62
61
|
block-size: 1.1rem;
|
|
63
62
|
border-radius: 50%;
|
|
64
|
-
background-color: var(--switch_thumb_color, var(--bds-
|
|
63
|
+
background-color: var(--switch_thumb_color, var(--bds-color_interactive));
|
|
65
64
|
transition: inset-inline-start 0.2s ease;
|
|
66
65
|
}
|
|
67
66
|
|
|
@@ -74,7 +73,7 @@ export class BdsSwitch extends LitElement {
|
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
.input:checked + .track {
|
|
77
|
-
background-color: var(--switch_color-active, var(--bdc-color_active));
|
|
76
|
+
background-color: var(--switch_color-active, var(--bdc-color_active--subtle));
|
|
78
77
|
}
|
|
79
78
|
|
|
80
79
|
.input:checked + .track .thumb {
|
|
@@ -44,10 +44,8 @@ export class BdsTextarea extends LitElement {
|
|
|
44
44
|
--bdc_color: currentcolor;
|
|
45
45
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
46
46
|
|
|
47
|
-
outline: var(--bdc-outline_width) solid var(--bdc_color);
|
|
48
|
-
outline-offset: var(--bdc-outline_offset);
|
|
49
47
|
border-radius: var(--textarea_radius, var(--bdc-outline_radius));
|
|
50
|
-
box-shadow: var(--textarea_shadow, var(--bdc-outline_shadow));
|
|
48
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--textarea_shadow, var(--bdc-outline_shadow));
|
|
51
49
|
background-color: var(--textarea_color_bg, var(--bds-color_bg));
|
|
52
50
|
color: var(--textarea_color, var(--bds-color_on-bg));
|
|
53
51
|
resize: vertical;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsAvatar.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# <bds-avatar>
|
|
7
|
+
|
|
8
|
+
Framework-agnostic Avatar custom element. Displays a user photo when `src` is provided, or falls back to initials derived from the `name` attribute.
|
|
9
|
+
|
|
10
|
+
> **Status: experimental** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import '@boostdev/components/web-components';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## When to use
|
|
19
|
+
|
|
20
|
+
- As a user profile image in navigation bars, comment threads, and team lists
|
|
21
|
+
- As an initials fallback when a photo is unavailable
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
### All sizes
|
|
26
|
+
<Canvas of={Stories.AllSizes} />
|
|
27
|
+
|
|
28
|
+
### Default (initials)
|
|
29
|
+
<Canvas of={Stories.Default} />
|
|
30
|
+
|
|
31
|
+
### With image
|
|
32
|
+
<Canvas of={Stories.WithImage} />
|
|
33
|
+
|
|
34
|
+
### Small
|
|
35
|
+
<Canvas of={Stories.Small} />
|
|
36
|
+
|
|
37
|
+
### Large
|
|
38
|
+
<Canvas of={Stories.Large} />
|
|
39
|
+
|
|
40
|
+
## Props
|
|
41
|
+
|
|
42
|
+
<ArgTypes of={Stories} />
|
|
43
|
+
|
|
44
|
+
## Attributes
|
|
45
|
+
|
|
46
|
+
| Attribute | Type | Default | Description |
|
|
47
|
+
|-----------|------|---------|-------------|
|
|
48
|
+
| `src` | string | — | Photo URL; when set the image is shown |
|
|
49
|
+
| `alt` | string | `name` or `"User avatar"` | Alt text for the `<img>` element |
|
|
50
|
+
| `name` | string | — | Full name; used to compute up to two initials and as `aria-label` |
|
|
51
|
+
| `size` | `"small" \| "medium" \| "large"` | `"medium"` | Diameter scale |
|
|
52
|
+
|
|
53
|
+
## CSS Custom Properties
|
|
54
|
+
|
|
55
|
+
| Property | Description |
|
|
56
|
+
|----------|-------------|
|
|
57
|
+
| `--avatar_bg` | Background colour of the fallback initials circle |
|
|
58
|
+
| `--avatar_text` | Text colour of the initials |
|
|
59
|
+
|
|
60
|
+
## Usage in plain HTML
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<!-- With photo -->
|
|
64
|
+
<bds-avatar src="/photo.jpg" name="Jane Doe"></bds-avatar>
|
|
65
|
+
|
|
66
|
+
<!-- Initials only -->
|
|
67
|
+
<bds-avatar name="Jane Doe" size="large"></bds-avatar>
|
|
68
|
+
|
|
69
|
+
<!-- Small -->
|
|
70
|
+
<bds-avatar name="JD" size="small"></bds-avatar>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Accessibility
|
|
74
|
+
|
|
75
|
+
- Without `src`: renders `role="img"` with `aria-label` set to `name` (or "User avatar")
|
|
76
|
+
- With `src`: renders `<img>` with `alt` set to `alt`, `name`, or "User avatar"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import '../index'; // auto-registers all custom elements
|
|
4
|
+
|
|
5
|
+
function BdsAvatar({
|
|
6
|
+
src,
|
|
7
|
+
alt,
|
|
8
|
+
name,
|
|
9
|
+
size = 'medium',
|
|
10
|
+
}: {
|
|
11
|
+
src?: string;
|
|
12
|
+
alt?: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
size?: 'small' | 'medium' | 'large';
|
|
15
|
+
}) {
|
|
16
|
+
return React.createElement('bds-avatar', { src, alt, name, size });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const meta = {
|
|
20
|
+
title: 'Web Components/UI/Avatar',
|
|
21
|
+
component: BdsAvatar,
|
|
22
|
+
tags: ['!stable', 'experimental'],
|
|
23
|
+
parameters: { layout: 'centered' },
|
|
24
|
+
argTypes: {
|
|
25
|
+
size: { control: 'select', options: ['small', 'medium', 'large'] },
|
|
26
|
+
},
|
|
27
|
+
} satisfies Meta<typeof BdsAvatar>;
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof meta>;
|
|
31
|
+
|
|
32
|
+
export const Default: Story = { args: { name: 'Jane Doe', size: 'medium' } };
|
|
33
|
+
export const WithImage: Story = {
|
|
34
|
+
args: { src: 'https://i.pravatar.cc/150?img=47', name: 'Jane Doe', size: 'medium' },
|
|
35
|
+
};
|
|
36
|
+
export const Small: Story = { args: { name: 'Jane Doe', size: 'small' } };
|
|
37
|
+
export const Large: Story = { args: { name: 'Jane Doe', size: 'large' } };
|
|
38
|
+
export const InitialsOnly: Story = { args: { name: 'John Smith', size: 'medium' } };
|
|
39
|
+
|
|
40
|
+
export const AllSizes: Story = {
|
|
41
|
+
render: () => (
|
|
42
|
+
<div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
|
|
43
|
+
{React.createElement('bds-avatar', { name: 'Alice Brown', size: 'small' })}
|
|
44
|
+
{React.createElement('bds-avatar', { name: 'Alice Brown', size: 'medium' })}
|
|
45
|
+
{React.createElement('bds-avatar', { name: 'Alice Brown', size: 'large' })}
|
|
46
|
+
</div>
|
|
47
|
+
),
|
|
48
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsBreadcrumb.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# <bds-breadcrumb>
|
|
7
|
+
|
|
8
|
+
Framework-agnostic Breadcrumb custom element. Renders a horizontal navigation trail from a JSON array of `{ label, href? }` items. The last item is treated as the current page and rendered without a link.
|
|
9
|
+
|
|
10
|
+
> **Status: experimental** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import '@boostdev/components/web-components';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## When to use
|
|
19
|
+
|
|
20
|
+
- On pages more than one level deep in a hierarchy to help users understand their location
|
|
21
|
+
- Always include a link back to the root/home as the first item
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
### Default
|
|
26
|
+
<Canvas of={Stories.Default} />
|
|
27
|
+
|
|
28
|
+
### Short (two levels)
|
|
29
|
+
<Canvas of={Stories.Short} />
|
|
30
|
+
|
|
31
|
+
### Long (five levels)
|
|
32
|
+
<Canvas of={Stories.Long} />
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
<ArgTypes of={Stories} />
|
|
37
|
+
|
|
38
|
+
## Attributes
|
|
39
|
+
|
|
40
|
+
| Attribute | Type | Default | Description |
|
|
41
|
+
|-----------|------|---------|-------------|
|
|
42
|
+
| `items` | `Array<{ label: string; href?: string }>` | `[]` | Breadcrumb items as a JSON-serialisable array. The last item is always the current page. |
|
|
43
|
+
|
|
44
|
+
## Usage in plain HTML
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<bds-breadcrumb
|
|
48
|
+
items='[{"label":"Home","href":"/"},{"label":"Products","href":"/products"},{"label":"Item"}]'>
|
|
49
|
+
</bds-breadcrumb>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or set the property in JavaScript:
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
document.querySelector('bds-breadcrumb').items = [
|
|
56
|
+
{ label: 'Home', href: '/' },
|
|
57
|
+
{ label: 'Products', href: '/products' },
|
|
58
|
+
{ label: 'Item' },
|
|
59
|
+
];
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Accessibility
|
|
63
|
+
|
|
64
|
+
- Wrapped in `<nav aria-label="Breadcrumb">` with an `<ol>` list structure
|
|
65
|
+
- The current page item carries `aria-current="page"`
|
|
66
|
+
- Separator characters are `aria-hidden="true"` to avoid screen reader noise
|