@repobit/dex-system-design 0.22.11 → 0.23.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/CHANGELOG.md +40 -0
- package/package.json +4 -3
- package/src/components/Button/button.stories.js +292 -120
- package/src/components/accordion/accordion-bg.css.js +7 -2
- package/src/components/accordion/accordion-bg.stories.js +268 -449
- package/src/components/accordion/accordion.stories.js +259 -265
- package/src/components/anchor/anchor.stories.js +160 -159
- package/src/components/awards/awards-icon.js +44 -0
- package/src/components/awards/awards.css.js +328 -0
- package/src/components/awards/awards.js +224 -0
- package/src/components/awards/awards.stories.js +447 -0
- package/src/components/back/back.stories.js +100 -375
- package/src/components/badge/badge.stories.js +241 -129
- package/src/components/breadcrumb/breadcrumb.stories.js +218 -219
- package/src/components/cards/card.stories.js +174 -622
- package/src/components/carousel/carousel.stories.js +196 -225
- package/src/components/checkbox/checkbox.stories.js +136 -51
- package/src/components/compare/compare.css.js +237 -0
- package/src/components/compare/compare.js +253 -0
- package/src/components/compare/compare.stories.js +372 -0
- package/src/components/display/display.stories.js +91 -297
- package/src/components/divider/divider.stories.js +160 -342
- package/src/components/footer/footer.stories.js +177 -402
- package/src/components/header/header.stories.js +130 -338
- package/src/components/heading/heading.js +8 -5
- package/src/components/heading/heading.stories.js +162 -471
- package/src/components/highlight/highlight.stories.js +153 -38
- package/src/components/image/image.stories.js +135 -563
- package/src/components/input/custom-form.stories.js +761 -224
- package/src/components/link/link.js +29 -12
- package/src/components/link/link.stories.js +130 -468
- package/src/components/modal/modal.stories.js +174 -28
- package/src/components/paragraph/paragraph.css.js +10 -1
- package/src/components/paragraph/paragraph.stories.js +85 -410
- package/src/components/picture/picture.stories.js +147 -561
- package/src/components/radio/radio.stories.js +230 -81
- package/src/components/tabs/tabs.stories.js +126 -10
- package/src/components/termsOfUse/terms.stories.js +223 -8
- package/src/tokens/tokens.js +1 -0
|
@@ -1,233 +1,204 @@
|
|
|
1
|
-
import { html } from
|
|
2
|
-
import
|
|
3
|
-
import "../paragraph/paragraph.js";
|
|
4
|
-
|
|
5
|
-
import "./carousel.js";
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './carousel.js';
|
|
6
3
|
|
|
7
4
|
export default {
|
|
8
|
-
title
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// Item 8
|
|
64
|
-
item8Title : { control: "text", name: "Item 8 Title" },
|
|
65
|
-
item8SubTitle : { control: "text", name: "Item 8 SubTitle" },
|
|
66
|
-
item8ModalText: { control: "text", name: "Item 8 Modal Text" },
|
|
67
|
-
item8Icon : { control: "text", name: "Item 8 Icon" },
|
|
68
|
-
item8Content : { control: "text", name: "Item 8 Content (use \\n\\n for paragraphs)" }
|
|
5
|
+
title : 'Components/Carousel',
|
|
6
|
+
tags : ['autodocs'],
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component: `
|
|
11
|
+
**CustomCarousel** and **CarouselItem** are Lit components for a scrollable, draggable card carousel with modal support.
|
|
12
|
+
|
|
13
|
+
- \`<bd-carousel-section>\` — scrollable container with left/right arrows and optional title
|
|
14
|
+
- \`<bd-carousel-item>\` — individual card with icon, slotted content, and a \`+\` button to open a modal
|
|
15
|
+
|
|
16
|
+
### Usage
|
|
17
|
+
\`\`\`html
|
|
18
|
+
<bd-carousel-section title="Security Features">
|
|
19
|
+
<bd-carousel-item title="VPN" icon="/assets/vpn.svg" modalText="Our VPN protects your connection.">
|
|
20
|
+
<p>Unlimited VPN included</p>
|
|
21
|
+
</bd-carousel-item>
|
|
22
|
+
</bd-carousel-section>
|
|
23
|
+
\`\`\`
|
|
24
|
+
|
|
25
|
+
### Behavior
|
|
26
|
+
- Left/right arrows scroll by one item width with smooth scroll
|
|
27
|
+
- Arrows disable automatically at scroll boundaries
|
|
28
|
+
- Click and drag (mouse + touch) supported for scrolling
|
|
29
|
+
- Clicking \`+\` on an item fires \`open-modal\` custom event, caught by the carousel to show \`<bd-modal>\`
|
|
30
|
+
- Modal closes via \`close-modal\` event
|
|
31
|
+
|
|
32
|
+
### Keyboard Support
|
|
33
|
+
- Arrow buttons respond to Enter/Space
|
|
34
|
+
- \`+\` button on items responds to Enter/Space
|
|
35
|
+
`
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
argTypes: {
|
|
40
|
+
title: {
|
|
41
|
+
control : 'text',
|
|
42
|
+
description: 'Optional section title rendered as `<h1>` above the carousel track',
|
|
43
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'CarouselSection' }
|
|
44
|
+
},
|
|
45
|
+
itemTitle: {
|
|
46
|
+
control : 'text',
|
|
47
|
+
description: 'Title of a carousel item, shown in the modal header',
|
|
48
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'CarouselItem' }
|
|
49
|
+
},
|
|
50
|
+
itemIcon: {
|
|
51
|
+
control : 'text',
|
|
52
|
+
description: 'Path to the icon image shown at the top of a carousel item',
|
|
53
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'CarouselItem' }
|
|
54
|
+
},
|
|
55
|
+
modalText: {
|
|
56
|
+
control : 'text',
|
|
57
|
+
description: 'Text passed to the modal when the `+` button is clicked',
|
|
58
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'CarouselItem' }
|
|
59
|
+
}
|
|
69
60
|
}
|
|
70
61
|
};
|
|
71
62
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
icon="${args.item1Icon}"
|
|
86
|
-
>
|
|
87
|
-
<bd-h as="h4" padding="10px 0">${args.item1Title}</bd-h>
|
|
88
|
-
${renderParagraphs(args.item1Content)}
|
|
89
|
-
</bd-carousel-item>
|
|
90
|
-
|
|
91
|
-
<bd-carousel-item
|
|
92
|
-
title="${args.item2Title}"
|
|
93
|
-
subTitle="${args.item2SubTitle}"
|
|
94
|
-
modalText="${args.item2ModalText}"
|
|
95
|
-
icon="${args.item2Icon}"
|
|
96
|
-
>
|
|
97
|
-
<bd-h as="h4" padding="10px 0">${args.item2Title}</bd-h>
|
|
98
|
-
${renderParagraphs(args.item2Content)}
|
|
99
|
-
</bd-carousel-item>
|
|
100
|
-
|
|
101
|
-
<bd-carousel-item
|
|
102
|
-
title="${args.item3Title}"
|
|
103
|
-
subTitle="${args.item3SubTitle}"
|
|
104
|
-
modalText="${args.item3ModalText}"
|
|
105
|
-
icon="${args.item3Icon}"
|
|
106
|
-
>
|
|
107
|
-
<bd-h as="h4" padding="10px 0">${args.item3Title}</bd-h>
|
|
108
|
-
${renderParagraphs(args.item3Content)}
|
|
109
|
-
</bd-carousel-item>
|
|
110
|
-
|
|
111
|
-
<bd-carousel-item
|
|
112
|
-
title="${args.item4Title}"
|
|
113
|
-
subTitle="${args.item4SubTitle}"
|
|
114
|
-
modalText="${args.item4ModalText}"
|
|
115
|
-
icon="${args.item4Icon}"
|
|
116
|
-
>
|
|
117
|
-
<bd-h as="h4" padding="10px 0">${args.item4Title}</bd-h>
|
|
118
|
-
${renderParagraphs(args.item4Content)}
|
|
119
|
-
</bd-carousel-item>
|
|
120
|
-
|
|
121
|
-
<bd-carousel-item
|
|
122
|
-
title="${args.item5Title}"
|
|
123
|
-
subTitle="${args.item5SubTitle}"
|
|
124
|
-
modalText="${args.item5ModalText}"
|
|
125
|
-
icon="${args.item5Icon}"
|
|
126
|
-
>
|
|
127
|
-
<bd-h as="h4" padding="10px 0">${args.item5Title}</bd-h>
|
|
128
|
-
${renderParagraphs(args.item5Content)}
|
|
129
|
-
</bd-carousel-item>
|
|
130
|
-
|
|
131
|
-
<bd-carousel-item
|
|
132
|
-
title="${args.item6Title}"
|
|
133
|
-
subTitle="${args.item6SubTitle}"
|
|
134
|
-
modalText="${args.item6ModalText}"
|
|
135
|
-
icon="${args.item6Icon}"
|
|
136
|
-
>
|
|
137
|
-
<bd-h as="h4" padding="10px 0">${args.item6Title}</bd-h>
|
|
138
|
-
${renderParagraphs(args.item6Content)}
|
|
139
|
-
</bd-carousel-item>
|
|
140
|
-
|
|
141
|
-
<bd-carousel-item
|
|
142
|
-
title="${args.item7Title}"
|
|
143
|
-
subTitle="${args.item7SubTitle}"
|
|
144
|
-
modalText="${args.item7ModalText}"
|
|
145
|
-
icon="${args.item7Icon}"
|
|
146
|
-
>
|
|
147
|
-
<bd-h as="h4" padding="10px 0">${args.item7Title}</bd-h>
|
|
148
|
-
${renderParagraphs(args.item7Content)}
|
|
149
|
-
</bd-carousel-item>
|
|
150
|
-
|
|
151
|
-
<bd-carousel-item
|
|
152
|
-
title="${args.item8Title}"
|
|
153
|
-
subTitle="${args.item8SubTitle}"
|
|
154
|
-
modalText="${args.item8ModalText}"
|
|
155
|
-
icon="${args.item8Icon}"
|
|
156
|
-
>
|
|
157
|
-
<bd-h as="h4" padding="10px 0">${args.item8Title}</bd-h>
|
|
158
|
-
${renderParagraphs(args.item8Content)}
|
|
159
|
-
</bd-carousel-item>
|
|
160
|
-
</bd-carousel-section>
|
|
63
|
+
const sampleItems = [
|
|
64
|
+
{ title: 'VPN Protection', icon: '/assets/vpn.svg', modalText: 'Our VPN encrypts your internet traffic and hides your IP address.', content: 'Unlimited encrypted VPN traffic' },
|
|
65
|
+
{ title: 'Antivirus', icon: '/assets/antivirus.svg', modalText: 'Real-time antivirus protection against all known and emerging threats.', content: 'Award-winning threat detection' },
|
|
66
|
+
{ title: 'Password Manager', icon: '/assets/password.svg', modalText: 'Store and autofill all your passwords securely across all devices.', content: 'Secure password vault' },
|
|
67
|
+
{ title: 'Parental Controls', icon: '/assets/parental.svg', modalText: 'Monitor and control your children\'s online activity and screen time.', content: 'Advanced content filtering' },
|
|
68
|
+
{ title: 'Anti-Phishing', icon: '/assets/phishing.svg', modalText: 'Detects and blocks phishing websites before they can steal your data.', content: 'Real-time phishing protection' },
|
|
69
|
+
{ title: 'Webcam Protection', icon: '/assets/webcam.svg', modalText: 'Prevents unauthorized apps from accessing your webcam.', content: 'Webcam & mic access control' }
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const renderItem = (item) => html`
|
|
73
|
+
<bd-carousel-item title="${item.title}" icon="${item.icon}" modalText="${item.modalText}">
|
|
74
|
+
<p>${item.content}</p>
|
|
75
|
+
</bd-carousel-item>
|
|
161
76
|
`;
|
|
162
77
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
78
|
+
// ─── Stories ───────────────────────────────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
export const Default = {
|
|
81
|
+
name : 'Default (6 items)',
|
|
82
|
+
render: () => html`
|
|
83
|
+
<bd-carousel-section title="Security Features">
|
|
84
|
+
${sampleItems.map(renderItem)}
|
|
85
|
+
</bd-carousel-section>
|
|
86
|
+
`,
|
|
87
|
+
parameters: { docs: { description: { story: '6-item carousel with title. Scroll with arrows or drag.' } } }
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const NoTitle = {
|
|
91
|
+
name : 'No Section Title',
|
|
92
|
+
render: () => html`
|
|
93
|
+
<bd-carousel-section>
|
|
94
|
+
${sampleItems.map(renderItem)}
|
|
95
|
+
</bd-carousel-section>
|
|
96
|
+
`,
|
|
97
|
+
parameters: { docs: { description: { story: 'Carousel without a title — the header `<div>` is conditionally omitted.' } } }
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const FewItems = {
|
|
101
|
+
name : 'Few Items (2)',
|
|
102
|
+
render: () => html`
|
|
103
|
+
<bd-carousel-section title="Features">
|
|
104
|
+
${sampleItems.slice(0, 2).map(renderItem)}
|
|
105
|
+
</bd-carousel-section>
|
|
106
|
+
`,
|
|
107
|
+
parameters: { docs: { description: { story: 'Only 2 items — right arrow should be disabled if all items fit in view.' } } }
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const SingleItem = {
|
|
111
|
+
name : 'Single Item (edge case)',
|
|
112
|
+
render: () => html`
|
|
113
|
+
<bd-carousel-section title="Features">
|
|
114
|
+
${renderItem(sampleItems[0])}
|
|
115
|
+
</bd-carousel-section>
|
|
116
|
+
`,
|
|
117
|
+
parameters: { docs: { description: { story: 'Edge case with a single item. Both arrows should be disabled.' } } }
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export const NoIcon = {
|
|
121
|
+
name : 'Items Without Icons',
|
|
122
|
+
render: () => html`
|
|
123
|
+
<bd-carousel-section title="Features">
|
|
124
|
+
${sampleItems.slice(0, 4).map(item => html`
|
|
125
|
+
<bd-carousel-item title="${item.title}" modalText="${item.modalText}">
|
|
126
|
+
<p>${item.content}</p>
|
|
127
|
+
</bd-carousel-item>
|
|
128
|
+
`)}
|
|
129
|
+
</bd-carousel-section>
|
|
130
|
+
`,
|
|
131
|
+
parameters: { docs: { description: { story: 'Items with no `icon` prop — the `<img>` is conditionally omitted.' } } }
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const RichSlottedContent = {
|
|
135
|
+
name : 'Rich Slotted Content',
|
|
136
|
+
render: () => html`
|
|
137
|
+
<bd-carousel-section title="Features">
|
|
138
|
+
<bd-carousel-item title="VPN" icon="/assets/vpn.svg" modalText="Full VPN details here.">
|
|
139
|
+
<ul>
|
|
140
|
+
<li>Unlimited bandwidth</li>
|
|
141
|
+
<li>200+ server locations</li>
|
|
142
|
+
<li>No-log policy</li>
|
|
143
|
+
</ul>
|
|
144
|
+
</bd-carousel-item>
|
|
145
|
+
<bd-carousel-item title="Antivirus" icon="/assets/antivirus.svg" modalText="Antivirus details here.">
|
|
146
|
+
<p>Real-time protection</p>
|
|
147
|
+
<a href="#">Learn more</a>
|
|
148
|
+
</bd-carousel-item>
|
|
149
|
+
<bd-carousel-item title="Parental Controls" icon="/assets/parental.svg" modalText="Parental control details.">
|
|
150
|
+
<p>Safe browsing for kids</p>
|
|
151
|
+
<p>Screen time management</p>
|
|
152
|
+
</bd-carousel-item>
|
|
153
|
+
</bd-carousel-section>
|
|
154
|
+
`,
|
|
155
|
+
parameters: { docs: { description: { story: 'Items with lists, links, and multiple paragraphs as slotted content.' } } }
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export const ModalTrigger = {
|
|
159
|
+
name : 'Modal — Click + to Open',
|
|
160
|
+
render: () => html`
|
|
161
|
+
<p style="font-size:14px; margin-bottom:12px;">Click the <strong>+</strong> button on any card to open the modal.</p>
|
|
162
|
+
<bd-carousel-section title="Features">
|
|
163
|
+
${sampleItems.slice(0, 3).map(renderItem)}
|
|
164
|
+
</bd-carousel-section>
|
|
165
|
+
`,
|
|
166
|
+
parameters: { docs: { description: { story: 'Demonstrates the modal flow. Click `+` on a card to fire `open-modal`, which renders `<bd-modal>` with the item\'s title and modalText.' } } }
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export const MobileView = {
|
|
170
|
+
name : 'Mobile View (375px)',
|
|
171
|
+
render: () => html`
|
|
172
|
+
<bd-carousel-section title="Security Features">
|
|
173
|
+
${sampleItems.map(renderItem)}
|
|
174
|
+
</bd-carousel-section>
|
|
175
|
+
`,
|
|
176
|
+
parameters: {
|
|
177
|
+
viewport: { defaultViewport: 'mobile1' },
|
|
178
|
+
docs : { description: { story: 'Carousel at 375px. Touch drag scrolling is supported.' } }
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const Playground = {
|
|
183
|
+
name: '🛝 Playground',
|
|
184
|
+
args: {
|
|
185
|
+
title : 'Security Features',
|
|
186
|
+
itemTitle: 'VPN Protection',
|
|
187
|
+
itemIcon : '/assets/vpn.svg',
|
|
188
|
+
modalText: 'Our VPN encrypts your connection and protects your privacy.'
|
|
189
|
+
},
|
|
190
|
+
render: (args) => html`
|
|
191
|
+
<bd-carousel-section title="${args.title}">
|
|
192
|
+
<bd-carousel-item title="${args.itemTitle}" icon="${args.itemIcon}" modalText="${args.modalText}">
|
|
193
|
+
<p>Slotted content for this item.</p>
|
|
194
|
+
</bd-carousel-item>
|
|
195
|
+
<bd-carousel-item title="Antivirus" icon="/assets/antivirus.svg" modalText="Real-time antivirus protection.">
|
|
196
|
+
<p>Award-winning threat detection</p>
|
|
197
|
+
</bd-carousel-item>
|
|
198
|
+
<bd-carousel-item title="Parental Controls" icon="/assets/parental.svg" modalText="Monitor your children's activity.">
|
|
199
|
+
<p>Advanced content filtering</p>
|
|
200
|
+
</bd-carousel-item>
|
|
201
|
+
</bd-carousel-section>
|
|
202
|
+
`,
|
|
203
|
+
parameters: { docs: { description: { story: 'Interactive playground. Modify the section title and first item props via Controls.' } } }
|
|
233
204
|
};
|
|
@@ -2,62 +2,147 @@ import { html } from 'lit';
|
|
|
2
2
|
import './checkbox.js';
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
title: '
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
title : 'Components/Checkbox',
|
|
6
|
+
tags : ['autodocs'],
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component: `
|
|
11
|
+
**BdCheckbox** is a fully accessible Lit checkbox component.
|
|
12
|
+
|
|
13
|
+
### Usage
|
|
14
|
+
\`\`\`html
|
|
15
|
+
<bd-checkbox label="Accept terms" name="terms" value="accepted"></bd-checkbox>
|
|
16
|
+
<bd-checkbox label="Disabled" disabled></bd-checkbox>
|
|
17
|
+
<bd-checkbox label="Pre-checked" checked></bd-checkbox>
|
|
18
|
+
\`\`\`
|
|
19
|
+
|
|
20
|
+
### Accessibility
|
|
21
|
+
- Uses \`role="checkbox"\` with \`aria-checked\` and \`aria-disabled\`
|
|
22
|
+
- Keyboard support: Space and Enter toggle the checkbox
|
|
23
|
+
- Focus ring appears only on keyboard navigation (Tab), not on mouse click
|
|
24
|
+
- \`tabindex="-1"\` when disabled
|
|
25
|
+
|
|
26
|
+
### Events
|
|
27
|
+
- \`change\` — fires with \`detail: { value }\` where value is the checkbox's \`value\` prop when checked, or \`null\` when unchecked
|
|
28
|
+
`
|
|
29
|
+
}
|
|
30
|
+
}
|
|
14
31
|
},
|
|
32
|
+
argTypes: {
|
|
33
|
+
label: {
|
|
34
|
+
control : 'text',
|
|
35
|
+
description: 'Visible text label rendered next to the checkbox',
|
|
36
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'Content' }
|
|
37
|
+
},
|
|
38
|
+
name: {
|
|
39
|
+
control : 'text',
|
|
40
|
+
description: 'Form field name',
|
|
41
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'Form' }
|
|
42
|
+
},
|
|
43
|
+
value: {
|
|
44
|
+
control : 'text',
|
|
45
|
+
description: 'Value emitted in the `change` event detail when checked',
|
|
46
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'Form' }
|
|
47
|
+
},
|
|
48
|
+
checked: {
|
|
49
|
+
control : 'boolean',
|
|
50
|
+
description: 'Whether the checkbox is checked',
|
|
51
|
+
table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'State' }
|
|
52
|
+
},
|
|
53
|
+
disabled: {
|
|
54
|
+
control : 'boolean',
|
|
55
|
+
description: 'Disables interaction and applies disabled styles',
|
|
56
|
+
table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'State' }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
15
59
|
};
|
|
16
60
|
|
|
17
|
-
|
|
18
|
-
const Template = ({ name, value, label, checked, disabled }) => html`
|
|
61
|
+
const render = (args) => html`
|
|
19
62
|
<bd-checkbox
|
|
20
|
-
.
|
|
21
|
-
.
|
|
22
|
-
.
|
|
23
|
-
|
|
24
|
-
|
|
63
|
+
label="${args.label}"
|
|
64
|
+
name="${args.name}"
|
|
65
|
+
value="${args.value}"
|
|
66
|
+
?checked="${args.checked}"
|
|
67
|
+
?disabled="${args.disabled}"
|
|
25
68
|
></bd-checkbox>
|
|
26
69
|
`;
|
|
27
70
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export const Checked =
|
|
39
|
-
Checked
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Disabled.args = {
|
|
49
|
-
name: 'group1',
|
|
50
|
-
value: 'disabled',
|
|
51
|
-
label: 'Checkbox disabled',
|
|
52
|
-
checked: false,
|
|
53
|
-
disabled: true,
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export const DisabledChecked = Template.bind({});
|
|
57
|
-
DisabledChecked.args = {
|
|
58
|
-
name: 'group1',
|
|
59
|
-
value: 'disabled-checked',
|
|
60
|
-
label: 'Checkbox disabled & checked',
|
|
61
|
-
checked: true,
|
|
62
|
-
disabled: true,
|
|
71
|
+
const defaultArgs = { label: 'Accept terms and conditions', name: 'terms', value: 'accepted', checked: false, disabled: false };
|
|
72
|
+
|
|
73
|
+
// ─── Stories ───────────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
export const Default = {
|
|
76
|
+
name : 'Default (Unchecked)',
|
|
77
|
+
render : () => html`<bd-checkbox label="Accept terms and conditions" name="terms" value="accepted"></bd-checkbox>`,
|
|
78
|
+
parameters: { docs: { description: { story: 'Default unchecked checkbox.' } } }
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const Checked = {
|
|
82
|
+
name : 'Checked',
|
|
83
|
+
render : () => html`<bd-checkbox label="I agree to the privacy policy" name="privacy" value="agreed" checked></bd-checkbox>`,
|
|
84
|
+
parameters: { docs: { description: { story: 'Checkbox pre-checked via the `checked` attribute.' } } }
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const Disabled = {
|
|
88
|
+
name : 'Disabled (Unchecked)',
|
|
89
|
+
render : () => html`<bd-checkbox label="This option is unavailable" name="unavailable" value="n/a" disabled></bd-checkbox>`,
|
|
90
|
+
parameters: { docs: { description: { story: 'Disabled checkbox — not interactable, `tabindex="-1"`, `aria-disabled="true"`.' } } }
|
|
63
91
|
};
|
|
92
|
+
|
|
93
|
+
export const DisabledChecked = {
|
|
94
|
+
name : 'Disabled (Checked)',
|
|
95
|
+
render : () => html`<bd-checkbox label="Already selected (locked)" name="locked" value="locked" checked disabled></bd-checkbox>`,
|
|
96
|
+
parameters: { docs: { description: { story: 'Disabled checkbox in the checked state — locked selection.' } } }
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const NoLabel = {
|
|
100
|
+
name : 'No Label',
|
|
101
|
+
render : () => html`<bd-checkbox name="no-label" value="yes"></bd-checkbox>`,
|
|
102
|
+
parameters: { docs: { description: { story: 'Checkbox with no visible label text.' } } }
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const AllStates = {
|
|
106
|
+
name : 'All States',
|
|
107
|
+
render: () => html`
|
|
108
|
+
<div style="display:flex; flex-direction:column; gap:12px;">
|
|
109
|
+
<bd-checkbox label="Unchecked" name="s1" value="1"></bd-checkbox>
|
|
110
|
+
<bd-checkbox label="Checked" name="s2" value="2" checked></bd-checkbox>
|
|
111
|
+
<bd-checkbox label="Disabled unchecked" name="s3" value="3" disabled></bd-checkbox>
|
|
112
|
+
<bd-checkbox label="Disabled checked" name="s4" value="4" checked disabled></bd-checkbox>
|
|
113
|
+
</div>
|
|
114
|
+
`,
|
|
115
|
+
parameters: { docs: { description: { story: 'All four checkbox states side by side: unchecked, checked, disabled unchecked, disabled checked.' } } }
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const Group = {
|
|
119
|
+
name : 'Checkbox Group',
|
|
120
|
+
render: () => html`
|
|
121
|
+
<fieldset style="border:none; padding:0;">
|
|
122
|
+
<legend style="font-weight:600; margin-bottom:12px;">Select your platforms</legend>
|
|
123
|
+
<div style="display:flex; flex-direction:column; gap:8px;">
|
|
124
|
+
<bd-checkbox label="Windows" name="platform" value="windows" checked></bd-checkbox>
|
|
125
|
+
<bd-checkbox label="macOS" name="platform" value="macos"></bd-checkbox>
|
|
126
|
+
<bd-checkbox label="Android" name="platform" value="android" checked></bd-checkbox>
|
|
127
|
+
<bd-checkbox label="iOS" name="platform" value="ios"></bd-checkbox>
|
|
128
|
+
</div>
|
|
129
|
+
</fieldset>
|
|
130
|
+
`,
|
|
131
|
+
parameters: { docs: { description: { story: 'A group of checkboxes simulating a multi-select form field.' } } }
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const KeyboardFocus = {
|
|
135
|
+
name : 'Keyboard Focus',
|
|
136
|
+
render: () => html`
|
|
137
|
+
<p style="font-size:14px; margin-bottom:8px;">Tab to focus, Space or Enter to toggle.</p>
|
|
138
|
+
<bd-checkbox label="Keyboard accessible checkbox" name="kb" value="kb"></bd-checkbox>
|
|
139
|
+
`,
|
|
140
|
+
parameters: { docs: { description: { story: 'Focus ring appears only via keyboard Tab navigation. Clicking with mouse does not show the focus ring.' } } }
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export const Playground = {
|
|
144
|
+
name : '🛝 Playground',
|
|
145
|
+
args : { ...defaultArgs },
|
|
146
|
+
render,
|
|
147
|
+
parameters: { docs: { description: { story: 'Interactive playground. Toggle checked, disabled, and edit label/value via Controls.' } } }
|
|
148
|
+
};
|