@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.
Files changed (213) hide show
  1. package/AGENTS.md +38 -14
  2. package/dist/client.cjs +85 -103
  3. package/dist/client.css +610 -601
  4. package/dist/client.d.cts +13 -16
  5. package/dist/client.d.ts +13 -16
  6. package/dist/client.js +95 -113
  7. package/dist/index.cjs +85 -103
  8. package/dist/index.css +610 -601
  9. package/dist/index.d.cts +13 -16
  10. package/dist/index.d.ts +13 -16
  11. package/dist/index.js +95 -113
  12. package/dist/native/index.cjs +9 -8
  13. package/dist/native/index.d.cts +1 -1
  14. package/dist/native/index.d.ts +1 -1
  15. package/dist/native/index.js +9 -8
  16. package/dist/web-components/{chunk-K5CE6HSB.js → chunk-2FGATTGT.js} +79 -17
  17. package/dist/web-components/{chunk-O4UFI2RX.js → chunk-3REOIRDW.js} +13 -11
  18. package/dist/web-components/{chunk-5IPHEONG.js → chunk-6I2DBFQ7.js} +1 -0
  19. package/dist/web-components/{chunk-VM3YHGQ2.js → chunk-AJSXNDAP.js} +1 -2
  20. package/dist/web-components/{chunk-LSC4N56Q.js → chunk-BX3IPVOB.js} +1 -2
  21. package/dist/web-components/{chunk-CAPI25CU.js → chunk-DZRSJGPB.js} +3 -3
  22. package/dist/web-components/{chunk-VSS5ITNE.js → chunk-EBJM3VD4.js} +1 -3
  23. package/dist/web-components/{chunk-O7I63SQX.js → chunk-HHHRF2PS.js} +6 -12
  24. package/dist/web-components/{chunk-OTX4COSV.js → chunk-JUKB3BUP.js} +3 -4
  25. package/dist/web-components/{chunk-IQGLIQSO.js → chunk-N6IMUOY4.js} +2 -5
  26. package/dist/web-components/{chunk-CJ5ZOO42.js → chunk-OCODKRVZ.js} +68 -44
  27. package/dist/web-components/{chunk-QDRH46TF.js → chunk-QLZ2362S.js} +1 -3
  28. package/dist/web-components/{chunk-IK3PTFZ4.js → chunk-T6AETZRP.js} +1 -3
  29. package/dist/web-components/{chunk-4BX6AWXX.js → chunk-X3FKVHLK.js} +2 -4
  30. package/dist/web-components/{chunk-A67LCT7C.js → chunk-XNA6WTXG.js} +3 -4
  31. package/dist/web-components/{chunk-XIENXR7H.js → chunk-YRXCVKHV.js} +1 -3
  32. package/dist/web-components/{chunk-6T3RKUKG.js → chunk-ZTC6GRP7.js} +1 -2
  33. package/dist/web-components/globals.js +1 -1
  34. package/dist/web-components/index.d.ts +571 -1
  35. package/dist/web-components/index.js +1515 -18
  36. package/dist/web-components/interaction/bds-accordion.js +1 -1
  37. package/dist/web-components/interaction/bds-button.d.ts +2 -2
  38. package/dist/web-components/interaction/bds-button.js +1 -1
  39. package/dist/web-components/interaction/bds-collapsible.js +1 -1
  40. package/dist/web-components/interaction/bds-dialog.js +1 -1
  41. package/dist/web-components/interaction/bds-drawer.js +1 -1
  42. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  43. package/dist/web-components/interaction/form/bds-combobox.js +1 -1
  44. package/dist/web-components/interaction/form/bds-number-input.js +1 -1
  45. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  46. package/dist/web-components/interaction/form/bds-segmented-control.d.ts +20 -3
  47. package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
  48. package/dist/web-components/interaction/form/bds-select.js +1 -1
  49. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  50. package/dist/web-components/interaction/form/bds-textarea.js +1 -1
  51. package/dist/web-components/ui/bds-alert.js +1 -1
  52. package/dist/web-components/ui/bds-card.js +1 -1
  53. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  54. package/package.json +2 -2
  55. package/src/components/interaction/Button/Button.module.css +12 -11
  56. package/src/components/interaction/Button/Button.native.tsx +10 -9
  57. package/src/components/interaction/Button/Button.tsx +1 -1
  58. package/src/components/interaction/Command/Command.module.css +3 -7
  59. package/src/components/interaction/Dialog/Dialog.module.css +7 -5
  60. package/src/components/interaction/Drawer/Drawer.module.css +48 -25
  61. package/src/components/interaction/Drawer/Drawer.tsx +21 -17
  62. package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +1 -3
  63. package/src/components/interaction/Popover/Popover.module.css +1 -3
  64. package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -3
  65. package/src/components/interaction/form/Combobox/Combobox.module.css +2 -6
  66. package/src/components/interaction/form/FormInput/FormInput.module.css +1 -3
  67. package/src/components/interaction/form/NumberInput/NumberInput.module.css +16 -4
  68. package/src/components/interaction/form/Radio/Radio.module.css +6 -16
  69. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +74 -25
  70. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +65 -36
  71. package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +127 -56
  72. package/src/components/interaction/form/SegmentedControl/SegmentedControl.stories.tsx +89 -72
  73. package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +40 -62
  74. package/src/components/interaction/form/SegmentedControl/index.ts +1 -1
  75. package/src/components/interaction/form/Select/Select.module.css +2 -4
  76. package/src/components/interaction/form/Switch/Switch.module.css +5 -7
  77. package/src/components/interaction/form/Switch/Switch.native.spec.tsx +9 -9
  78. package/src/components/interaction/form/Switch/Switch.native.tsx +2 -2
  79. package/src/components/interaction/form/Textarea/Textarea.module.css +1 -3
  80. package/src/components/interaction/form/atoms/InputContainer.stories.tsx +64 -0
  81. package/src/components/interaction/form/atoms/Label.stories.tsx +33 -0
  82. package/src/components/interaction/form/atoms/Message.stories.tsx +33 -0
  83. package/src/components/layout/Card/Card.module.css +1 -3
  84. package/src/components/ui/Accordion/Accordion.module.css +1 -2
  85. package/src/components/ui/Alert/Alert.module.css +1 -2
  86. package/src/components/ui/Calendar/Calendar.module.css +2 -5
  87. package/src/components/ui/Carousel/Carousel.module.css +1 -3
  88. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -2
  89. package/src/components/ui/Pagination/Pagination.module.css +1 -2
  90. package/src/components/ui/SkipLink/SkipLink.module.css +1 -2
  91. package/src/components/ui/Table/Table.module.css +1 -2
  92. package/src/css/bdc.css +16 -11
  93. package/src/index.ts +1 -1
  94. package/src/stories/Introduction.mdx +2 -1
  95. package/src/web-components/globals.ts +3 -3
  96. package/src/web-components/index.ts +12 -0
  97. package/src/web-components/interaction/BdsAccordion.mdx +103 -0
  98. package/src/web-components/interaction/BdsAccordion.stories.tsx +94 -0
  99. package/src/web-components/interaction/BdsCollapsible.mdx +116 -0
  100. package/src/web-components/interaction/BdsCollapsible.stories.tsx +68 -0
  101. package/src/web-components/interaction/BdsDialog.mdx +110 -0
  102. package/src/web-components/interaction/BdsDialog.stories.tsx +157 -0
  103. package/src/web-components/interaction/BdsDrawer.mdx +108 -0
  104. package/src/web-components/interaction/BdsDrawer.stories.tsx +196 -0
  105. package/src/web-components/interaction/BdsDropdownMenu.mdx +108 -0
  106. package/src/web-components/interaction/BdsDropdownMenu.stories.tsx +91 -0
  107. package/src/web-components/interaction/BdsSkipLink.mdx +90 -0
  108. package/src/web-components/interaction/BdsSkipLink.stories.tsx +68 -0
  109. package/src/web-components/interaction/BdsTabs.mdx +117 -0
  110. package/src/web-components/interaction/BdsTabs.stories.tsx +94 -0
  111. package/src/web-components/interaction/BdsTooltip.mdx +104 -0
  112. package/src/web-components/interaction/BdsTooltip.stories.tsx +87 -0
  113. package/src/web-components/interaction/bds-accordion.ts +1 -2
  114. package/src/web-components/interaction/bds-button.ts +15 -13
  115. package/src/web-components/interaction/bds-collapsible.ts +1 -0
  116. package/src/web-components/interaction/bds-dialog.ts +2 -5
  117. package/src/web-components/interaction/bds-drawer.ts +70 -44
  118. package/src/web-components/interaction/bds-dropdown-menu-item.ts +124 -0
  119. package/src/web-components/interaction/bds-dropdown-menu.spec.ts +102 -0
  120. package/src/web-components/interaction/bds-dropdown-menu.ts +200 -0
  121. package/src/web-components/interaction/form/BdsCheckbox.mdx +76 -0
  122. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +72 -0
  123. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +70 -0
  124. package/src/web-components/interaction/form/BdsCheckboxGroup.stories.tsx +81 -0
  125. package/src/web-components/interaction/form/BdsCombobox.mdx +71 -0
  126. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +93 -0
  127. package/src/web-components/interaction/form/BdsFileInput.mdx +79 -0
  128. package/src/web-components/interaction/form/BdsFileInput.stories.tsx +69 -0
  129. package/src/web-components/interaction/form/BdsFormInput.mdx +98 -0
  130. package/src/web-components/interaction/form/BdsFormInput.stories.tsx +139 -0
  131. package/src/web-components/interaction/form/BdsNumberInput.mdx +70 -0
  132. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +68 -0
  133. package/src/web-components/interaction/form/BdsRadio.mdx +72 -0
  134. package/src/web-components/interaction/form/BdsRadio.stories.tsx +58 -0
  135. package/src/web-components/interaction/form/BdsRadioGroup.mdx +73 -0
  136. package/src/web-components/interaction/form/BdsRadioGroup.stories.tsx +88 -0
  137. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +95 -0
  138. package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +102 -0
  139. package/src/web-components/interaction/form/BdsSelect.mdx +76 -0
  140. package/src/web-components/interaction/form/BdsSelect.stories.tsx +84 -0
  141. package/src/web-components/interaction/form/BdsSlider.mdx +77 -0
  142. package/src/web-components/interaction/form/BdsSlider.stories.tsx +68 -0
  143. package/src/web-components/interaction/form/BdsSwitch.mdx +72 -0
  144. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +58 -0
  145. package/src/web-components/interaction/form/BdsTextarea.mdx +73 -0
  146. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +70 -0
  147. package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +55 -0
  148. package/src/web-components/interaction/form/bds-checkbox-group.ts +117 -0
  149. package/src/web-components/interaction/form/bds-checkbox.ts +1 -3
  150. package/src/web-components/interaction/form/bds-combobox.ts +1 -3
  151. package/src/web-components/interaction/form/bds-form-input.spec.ts +83 -0
  152. package/src/web-components/interaction/form/bds-form-input.ts +268 -0
  153. package/src/web-components/interaction/form/bds-number-input.ts +3 -4
  154. package/src/web-components/interaction/form/bds-radio-group.spec.ts +62 -0
  155. package/src/web-components/interaction/form/bds-radio-group.ts +142 -0
  156. package/src/web-components/interaction/form/bds-radio.ts +6 -12
  157. package/src/web-components/interaction/form/bds-segmented-control.ts +96 -20
  158. package/src/web-components/interaction/form/bds-select.ts +2 -4
  159. package/src/web-components/interaction/form/bds-switch.ts +3 -4
  160. package/src/web-components/interaction/form/bds-textarea.ts +1 -3
  161. package/src/web-components/ui/BdsAvatar.mdx +76 -0
  162. package/src/web-components/ui/BdsAvatar.stories.tsx +48 -0
  163. package/src/web-components/ui/BdsBreadcrumb.mdx +66 -0
  164. package/src/web-components/ui/BdsBreadcrumb.stories.tsx +49 -0
  165. package/src/web-components/ui/BdsButtonGroup.mdx +69 -0
  166. package/src/web-components/ui/BdsButtonGroup.stories.tsx +66 -0
  167. package/src/web-components/ui/BdsCalendar.mdx +93 -0
  168. package/src/web-components/ui/BdsCalendar.stories.tsx +63 -0
  169. package/src/web-components/ui/BdsCard.mdx +88 -0
  170. package/src/web-components/ui/BdsCard.stories.tsx +67 -0
  171. package/src/web-components/ui/BdsCarousel.mdx +83 -0
  172. package/src/web-components/ui/BdsCarousel.stories.tsx +96 -0
  173. package/src/web-components/ui/BdsDescriptionList.mdx +64 -0
  174. package/src/web-components/ui/BdsDescriptionList.stories.tsx +64 -0
  175. package/src/web-components/ui/BdsIconWrapper.mdx +70 -0
  176. package/src/web-components/ui/BdsIconWrapper.stories.tsx +81 -0
  177. package/src/web-components/ui/BdsLink.mdx +79 -0
  178. package/src/web-components/ui/BdsLink.stories.tsx +63 -0
  179. package/src/web-components/ui/BdsLoading.mdx +58 -0
  180. package/src/web-components/ui/BdsLoading.stories.tsx +35 -0
  181. package/src/web-components/ui/BdsNotificationBanner.mdx +85 -0
  182. package/src/web-components/ui/BdsNotificationBanner.stories.tsx +84 -0
  183. package/src/web-components/ui/BdsPagination.mdx +74 -0
  184. package/src/web-components/ui/BdsPagination.stories.tsx +36 -0
  185. package/src/web-components/ui/BdsProgress.mdx +70 -0
  186. package/src/web-components/ui/BdsProgress.stories.tsx +96 -0
  187. package/src/web-components/ui/BdsProgressCircle.mdx +70 -0
  188. package/src/web-components/ui/BdsProgressCircle.stories.tsx +57 -0
  189. package/src/web-components/ui/BdsRating.mdx +61 -0
  190. package/src/web-components/ui/BdsRating.stories.tsx +45 -0
  191. package/src/web-components/ui/BdsSectionHeader.mdx +72 -0
  192. package/src/web-components/ui/BdsSectionHeader.stories.tsx +54 -0
  193. package/src/web-components/ui/BdsSeparator.mdx +77 -0
  194. package/src/web-components/ui/BdsSeparator.stories.tsx +55 -0
  195. package/src/web-components/ui/BdsSkeleton.mdx +61 -0
  196. package/src/web-components/ui/BdsSkeleton.stories.tsx +50 -0
  197. package/src/web-components/ui/BdsTable.mdx +81 -0
  198. package/src/web-components/ui/BdsTable.stories.tsx +83 -0
  199. package/src/web-components/ui/BdsTypography.mdx +74 -0
  200. package/src/web-components/ui/BdsTypography.stories.tsx +52 -0
  201. package/src/web-components/ui/bds-alert.ts +1 -2
  202. package/src/web-components/ui/bds-button-group.spec.ts +40 -0
  203. package/src/web-components/ui/bds-button-group.ts +78 -0
  204. package/src/web-components/ui/bds-calendar.spec.ts +91 -0
  205. package/src/web-components/ui/bds-calendar.ts +427 -0
  206. package/src/web-components/ui/bds-card.ts +1 -3
  207. package/src/web-components/ui/bds-carousel.spec.ts +64 -0
  208. package/src/web-components/ui/bds-carousel.ts +296 -0
  209. package/src/web-components/ui/bds-notification-banner.ts +1 -2
  210. package/src/web-components/ui/bds-pagination.spec.ts +67 -0
  211. package/src/web-components/ui/bds-pagination.ts +197 -0
  212. package/src/web-components/ui/bds-table.spec.ts +45 -0
  213. package/src/web-components/ui/bds-table.ts +96 -0
@@ -0,0 +1,139 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../../index'; // auto-registers all custom elements
4
+
5
+ function BdsFormInput({
6
+ name,
7
+ type,
8
+ value,
9
+ placeholder,
10
+ label,
11
+ hint,
12
+ error,
13
+ disabled,
14
+ required,
15
+ prefix,
16
+ suffix,
17
+ }: {
18
+ name?: string;
19
+ type?: string;
20
+ value?: string;
21
+ placeholder?: string;
22
+ label?: string;
23
+ hint?: string;
24
+ error?: string;
25
+ disabled?: boolean;
26
+ required?: boolean;
27
+ prefix?: React.ReactNode;
28
+ suffix?: React.ReactNode;
29
+ }) {
30
+ const prefixSlot = prefix
31
+ ? React.createElement('span', { slot: 'prefix' }, prefix)
32
+ : undefined;
33
+ const suffixSlot = suffix
34
+ ? React.createElement('span', { slot: 'suffix' }, suffix)
35
+ : undefined;
36
+
37
+ return React.createElement(
38
+ 'bds-form-input',
39
+ {
40
+ name,
41
+ type,
42
+ value,
43
+ placeholder,
44
+ label,
45
+ hint,
46
+ error,
47
+ disabled: disabled || undefined,
48
+ required: required || undefined,
49
+ },
50
+ prefixSlot,
51
+ suffixSlot,
52
+ );
53
+ }
54
+
55
+ const meta = {
56
+ title: 'Web Components/Interaction/Form/FormInput',
57
+ component: BdsFormInput,
58
+ tags: ['!stable', 'experimental'],
59
+ parameters: { layout: 'centered' },
60
+ argTypes: {
61
+ type: {
62
+ control: 'select',
63
+ options: ['text', 'email', 'password', 'search', 'url', 'tel'],
64
+ },
65
+ disabled: { control: 'boolean' },
66
+ required: { control: 'boolean' },
67
+ },
68
+ decorators: [
69
+ (Story: React.ComponentType) => (
70
+ <div style={{ width: '320px' }}>
71
+ <Story />
72
+ </div>
73
+ ),
74
+ ],
75
+ } satisfies Meta<typeof BdsFormInput>;
76
+
77
+ export default meta;
78
+ type Story = StoryObj<typeof meta>;
79
+
80
+ export const Default: Story = {
81
+ args: { name: 'text', placeholder: 'Enter text…' },
82
+ };
83
+
84
+ export const WithLabel: Story = {
85
+ args: { name: 'username', label: 'Username', placeholder: 'e.g. johndoe' },
86
+ };
87
+
88
+ export const WithHint: Story = {
89
+ args: {
90
+ name: 'username',
91
+ label: 'Username',
92
+ placeholder: 'e.g. johndoe',
93
+ hint: 'Must be 3–20 characters.',
94
+ },
95
+ };
96
+
97
+ export const WithError: Story = {
98
+ args: {
99
+ name: 'username',
100
+ label: 'Username',
101
+ placeholder: 'e.g. johndoe',
102
+ error: 'Username is already taken.',
103
+ },
104
+ };
105
+
106
+ export const WithPrefix: Story = {
107
+ render: () => (
108
+ <div style={{ width: '320px' }}>
109
+ <BdsFormInput name="price" label="Price" placeholder="0.00" prefix="€" />
110
+ </div>
111
+ ),
112
+ };
113
+
114
+ export const WithSuffix: Story = {
115
+ render: () => (
116
+ <div style={{ width: '320px' }}>
117
+ <BdsFormInput name="weight" label="Weight" placeholder="0" suffix="kg" />
118
+ </div>
119
+ ),
120
+ };
121
+
122
+ export const Email: Story = {
123
+ args: {
124
+ name: 'email',
125
+ type: 'email',
126
+ label: 'Email address',
127
+ placeholder: 'you@example.com',
128
+ required: true,
129
+ },
130
+ };
131
+
132
+ export const Disabled: Story = {
133
+ args: {
134
+ name: 'username',
135
+ label: 'Username',
136
+ value: 'johndoe',
137
+ disabled: true,
138
+ },
139
+ };
@@ -0,0 +1,70 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsNumberInput.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-number-input&gt;
7
+
8
+ Form-associated number input with increment and decrement stepper buttons. Hides the browser's native spinners and provides styled stepper controls instead.
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
+ Use `<bds-number-input>` for quantity selectors, counters, or any numeric field where step-by-step incrementing is a common interaction pattern.
21
+
22
+ ## Examples
23
+
24
+ ### Default
25
+ <Canvas of={Stories.Default} />
26
+
27
+ ### With min and max
28
+ <Canvas of={Stories.WithMinMax} />
29
+
30
+ ### With custom step (5)
31
+ <Canvas of={Stories.WithStep} />
32
+
33
+ ### Disabled
34
+ <Canvas of={Stories.Disabled} />
35
+
36
+ ## Props
37
+
38
+ <ArgTypes of={Stories} />
39
+
40
+ ## Attributes
41
+
42
+ | Attribute | Type | Default | Description |
43
+ |------------|---------|-------------|------------------------------------------|
44
+ | `name` | string | `""` | Form field name |
45
+ | `value` | number | `0` | Current numeric value |
46
+ | `min` | number | — | Minimum allowed value |
47
+ | `max` | number | — | Maximum allowed value |
48
+ | `step` | number | `1` | Increment/decrement step |
49
+ | `disabled` | boolean | `false` | Disables the input and steppers |
50
+
51
+ ## Events
52
+
53
+ | Event | Detail | Description |
54
+ |----------|--------|-------------------------------------------------------|
55
+ | `input` | — | Fired on stepper click and native input |
56
+ | `change` | — | Native change event from the inner `<input type="number">` |
57
+
58
+ ## Usage in plain HTML
59
+
60
+ ```html
61
+ <bds-number-input name="qty" value="1" min="0" max="99" step="1"></bds-number-input>
62
+ ```
63
+
64
+ ## Accessibility
65
+
66
+ - Decrement button has `aria-label="Decrease"` and increment has `aria-label="Increase"`
67
+ - Stepper buttons are disabled when the value is at `min` or `max`
68
+ - The stepper buttons use `tabindex="-1"` so keyboard users navigate directly to the numeric input
69
+ - `disabled` disables both the input and the stepper buttons
70
+ - Participates in HTML forms via the Form-Associated Custom Elements API
@@ -0,0 +1,68 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../../index'; // auto-registers all custom elements
4
+
5
+ function BdsNumberInput({
6
+ name,
7
+ value,
8
+ min,
9
+ max,
10
+ step,
11
+ disabled,
12
+ }: {
13
+ name?: string;
14
+ value?: number;
15
+ min?: number;
16
+ max?: number;
17
+ step?: number;
18
+ disabled?: boolean;
19
+ }) {
20
+ return React.createElement('bds-number-input', {
21
+ name,
22
+ value,
23
+ min,
24
+ max,
25
+ step,
26
+ disabled: disabled || undefined,
27
+ });
28
+ }
29
+
30
+ const meta = {
31
+ title: 'Web Components/Interaction/Form/NumberInput',
32
+ component: BdsNumberInput,
33
+ tags: ['!stable', 'experimental'],
34
+ parameters: { layout: 'centered' },
35
+ argTypes: {
36
+ disabled: { control: 'boolean' },
37
+ value: { control: 'number' },
38
+ min: { control: 'number' },
39
+ max: { control: 'number' },
40
+ step: { control: 'number' },
41
+ },
42
+ decorators: [
43
+ (Story: React.ComponentType) => (
44
+ <div style={{ width: '200px' }}>
45
+ <Story />
46
+ </div>
47
+ ),
48
+ ],
49
+ } satisfies Meta<typeof BdsNumberInput>;
50
+
51
+ export default meta;
52
+ type Story = StoryObj<typeof meta>;
53
+
54
+ export const Default: Story = {
55
+ args: { name: 'quantity', value: 0 },
56
+ };
57
+
58
+ export const WithMinMax: Story = {
59
+ args: { name: 'quantity', value: 5, min: 0, max: 10 },
60
+ };
61
+
62
+ export const WithStep: Story = {
63
+ args: { name: 'quantity', value: 0, step: 5, min: 0, max: 100 },
64
+ };
65
+
66
+ export const Disabled: Story = {
67
+ args: { name: 'quantity', value: 3, disabled: true },
68
+ };
@@ -0,0 +1,72 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsRadio.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-radio&gt;
7
+
8
+ Form-associated radio button custom element. Use multiple `<bds-radio>` elements with the same `name` to form a mutually exclusive group. For a labelled group with error/hint support, use `<bds-radio-group>`.
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
+ Use `<bds-radio>` for single-choice selection from a set of options. Always group radios that belong to the same choice under `<bds-radio-group>` for accessibility.
21
+
22
+ ## Examples
23
+
24
+ ### Default
25
+ <Canvas of={Stories.Default} />
26
+
27
+ ### Checked
28
+ <Canvas of={Stories.Checked} />
29
+
30
+ ### Disabled
31
+ <Canvas of={Stories.Disabled} />
32
+
33
+ ## Props
34
+
35
+ <ArgTypes of={Stories} />
36
+
37
+ ## Attributes
38
+
39
+ | Attribute | Type | Default | Description |
40
+ |------------|---------|---------|--------------------------------------------------|
41
+ | `name` | string | `""` | Form field name (groups radio buttons) |
42
+ | `value` | string | `""` | Value submitted when this option is selected |
43
+ | `checked` | boolean | `false` | Whether this option is selected |
44
+ | `required` | boolean | `false` | Marks the field as required |
45
+ | `disabled` | boolean | `false` | Disables this radio option |
46
+
47
+ ## Slots
48
+
49
+ | Slot | Description |
50
+ |-------------|--------------------|
51
+ | `(default)` | Label text content |
52
+
53
+ ## Events
54
+
55
+ | Event | Detail | Description |
56
+ |----------|--------|------------------------------------------------|
57
+ | `change` | — | Native change event forwarded from the inner `<input>` |
58
+
59
+ ## Usage in plain HTML
60
+
61
+ ```html
62
+ <bds-radio name="size" value="s">Small</bds-radio>
63
+ <bds-radio name="size" value="m" checked>Medium</bds-radio>
64
+ <bds-radio name="size" value="l">Large</bds-radio>
65
+ ```
66
+
67
+ ## Accessibility
68
+
69
+ - The inner `<input type="radio">` is associated with a `<label>` via matching `id`/`for` attributes
70
+ - Radios with the same `name` form a mutually exclusive group for keyboard navigation
71
+ - Use `<bds-radio-group>` to wrap related radios in a `<fieldset>`/`<legend>` for proper screen reader announcements
72
+ - Participates in HTML forms via the Form-Associated Custom Elements API
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../../index'; // auto-registers all custom elements
4
+
5
+ function BdsRadio({
6
+ name,
7
+ value,
8
+ checked,
9
+ required,
10
+ disabled,
11
+ children,
12
+ }: {
13
+ name?: string;
14
+ value?: string;
15
+ checked?: boolean;
16
+ required?: boolean;
17
+ disabled?: boolean;
18
+ children?: React.ReactNode;
19
+ }) {
20
+ return React.createElement(
21
+ 'bds-radio',
22
+ {
23
+ name,
24
+ value,
25
+ checked: checked || undefined,
26
+ required: required || undefined,
27
+ disabled: disabled || undefined,
28
+ },
29
+ children,
30
+ );
31
+ }
32
+
33
+ const meta = {
34
+ title: 'Web Components/Interaction/Form/Radio',
35
+ component: BdsRadio,
36
+ tags: ['!stable', 'experimental'],
37
+ parameters: { layout: 'centered' },
38
+ argTypes: {
39
+ checked: { control: 'boolean' },
40
+ required: { control: 'boolean' },
41
+ disabled: { control: 'boolean' },
42
+ },
43
+ } satisfies Meta<typeof BdsRadio>;
44
+
45
+ export default meta;
46
+ type Story = StoryObj<typeof meta>;
47
+
48
+ export const Default: Story = {
49
+ args: { name: 'size', value: 'm', children: 'Medium' },
50
+ };
51
+
52
+ export const Checked: Story = {
53
+ args: { name: 'size', value: 'm', checked: true, children: 'Medium (checked)' },
54
+ };
55
+
56
+ export const Disabled: Story = {
57
+ args: { name: 'size', value: 'm', disabled: true, children: 'Medium (disabled)' },
58
+ };
@@ -0,0 +1,73 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsRadioGroup.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-radio-group&gt;
7
+
8
+ Groups related radio buttons with a shared label and name. Renders a `<fieldset>` with a `<legend>`, and propagates the `name` attribute to all slotted `<bds-radio>` children so they form a mutually exclusive set.
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
+ Use `<bds-radio-group>` whenever you have a set of mutually exclusive options. The `<fieldset>`/`<legend>` structure ensures screen readers announce the group label alongside each radio option.
21
+
22
+ ## Examples
23
+
24
+ ### Default
25
+ <Canvas of={Stories.Default} />
26
+
27
+ ### With error
28
+ <Canvas of={Stories.WithError} />
29
+
30
+ ### With hint
31
+ <Canvas of={Stories.WithHint} />
32
+
33
+ ### Disabled
34
+ <Canvas of={Stories.Disabled} />
35
+
36
+ ## Props
37
+
38
+ <ArgTypes of={Stories} />
39
+
40
+ ## Attributes
41
+
42
+ | Attribute | Type | Default | Description |
43
+ |------------|---------|---------|-------------------------------------------------------------------|
44
+ | `label` | string | `""` | Group label rendered as `<legend>` |
45
+ | `name` | string | `""` | Shared name propagated to all slotted `<bds-radio>` elements |
46
+ | `error` | string | — | Error message shown below items; takes priority over `hint` |
47
+ | `hint` | string | — | Helper text shown below items |
48
+ | `required` | boolean | `false` | Shows a required indicator on the legend |
49
+ | `disabled` | boolean | `false` | Disables the entire fieldset |
50
+
51
+ ## Slots
52
+
53
+ | Slot | Description |
54
+ |-------------|---------------------------|
55
+ | `(default)` | `<bds-radio>` elements |
56
+
57
+ ## Usage in plain HTML
58
+
59
+ ```html
60
+ <bds-radio-group label="Preferred contact" name="contact" required>
61
+ <bds-radio value="email">Email</bds-radio>
62
+ <bds-radio value="phone">Phone</bds-radio>
63
+ <bds-radio value="post">Post</bds-radio>
64
+ </bds-radio-group>
65
+ ```
66
+
67
+ ## Accessibility
68
+
69
+ - Renders a `<fieldset>` with a `<legend>`, which is announced as a group by screen readers
70
+ - The `name` attribute is automatically propagated to all slotted `<bds-radio>` elements
71
+ - `required` adds a visual asterisk to the legend
72
+ - `disabled` on the group disables all contained radios via the native `<fieldset disabled>` behaviour
73
+ - Error messages use `role="alert"` so they are announced immediately
@@ -0,0 +1,88 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../../index'; // auto-registers all custom elements
4
+
5
+ function BdsRadioGroup({
6
+ label,
7
+ name,
8
+ error,
9
+ hint,
10
+ required,
11
+ disabled,
12
+ children,
13
+ }: {
14
+ label?: string;
15
+ name?: string;
16
+ error?: string;
17
+ hint?: string;
18
+ required?: boolean;
19
+ disabled?: boolean;
20
+ children?: React.ReactNode;
21
+ }) {
22
+ return React.createElement(
23
+ 'bds-radio-group',
24
+ {
25
+ label,
26
+ name,
27
+ error,
28
+ hint,
29
+ required: required || undefined,
30
+ disabled: disabled || undefined,
31
+ },
32
+ children,
33
+ );
34
+ }
35
+
36
+ const meta = {
37
+ title: 'Web Components/Interaction/Form/RadioGroup',
38
+ component: BdsRadioGroup,
39
+ tags: ['!stable', 'experimental'],
40
+ parameters: { layout: 'centered' },
41
+ argTypes: {
42
+ required: { control: 'boolean' },
43
+ disabled: { control: 'boolean' },
44
+ },
45
+ } satisfies Meta<typeof BdsRadioGroup>;
46
+
47
+ export default meta;
48
+ type Story = StoryObj<typeof meta>;
49
+
50
+ export const Default: Story = {
51
+ render: () => (
52
+ <BdsRadioGroup label="Preferred contact" name="contact">
53
+ {React.createElement('bds-radio', { value: 'email' }, 'Email')}
54
+ {React.createElement('bds-radio', { value: 'phone' }, 'Phone')}
55
+ {React.createElement('bds-radio', { value: 'post' }, 'Post')}
56
+ </BdsRadioGroup>
57
+ ),
58
+ };
59
+
60
+ export const WithError: Story = {
61
+ render: () => (
62
+ <BdsRadioGroup label="Preferred contact" name="contact" error="Please select a contact method.">
63
+ {React.createElement('bds-radio', { value: 'email' }, 'Email')}
64
+ {React.createElement('bds-radio', { value: 'phone' }, 'Phone')}
65
+ {React.createElement('bds-radio', { value: 'post' }, 'Post')}
66
+ </BdsRadioGroup>
67
+ ),
68
+ };
69
+
70
+ export const WithHint: Story = {
71
+ render: () => (
72
+ <BdsRadioGroup label="Preferred contact" name="contact" hint="We will only contact you via the selected method.">
73
+ {React.createElement('bds-radio', { value: 'email' }, 'Email')}
74
+ {React.createElement('bds-radio', { value: 'phone' }, 'Phone')}
75
+ {React.createElement('bds-radio', { value: 'post' }, 'Post')}
76
+ </BdsRadioGroup>
77
+ ),
78
+ };
79
+
80
+ export const Disabled: Story = {
81
+ render: () => (
82
+ <BdsRadioGroup label="Preferred contact" name="contact" disabled>
83
+ {React.createElement('bds-radio', { value: 'email' }, 'Email')}
84
+ {React.createElement('bds-radio', { value: 'phone' }, 'Phone')}
85
+ {React.createElement('bds-radio', { value: 'post' }, 'Post')}
86
+ </BdsRadioGroup>
87
+ ),
88
+ };
@@ -0,0 +1,95 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsSegmentedControl.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-segmented-control&gt;
7
+
8
+ Form-associated segmented control. Renders a group of radio buttons (or anchor links) styled as a unified segmented bar. Supports two visual variants: `outline` (sliding inset-border indicator) and `filled` (sliding filled thumb).
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
+ Use `<bds-segmented-control>` for mutually exclusive view or mode toggles where all options are visible simultaneously — for example, switching between List, Grid, and Map views. When used with `href` options it renders `<a>` links for navigation.
21
+
22
+ ## Examples
23
+
24
+ ### Default (outline variant)
25
+ <Canvas of={Stories.Default} />
26
+
27
+ ### Filled variant
28
+ <Canvas of={Stories.Filled} />
29
+
30
+ ### With a disabled option
31
+ <Canvas of={Stories.WithDisabledOption} />
32
+
33
+ ### As navigation links
34
+ <Canvas of={Stories.AsNavLinks} />
35
+
36
+ ### Disabled
37
+ <Canvas of={Stories.Disabled} />
38
+
39
+ ## Props
40
+
41
+ <ArgTypes of={Stories} />
42
+
43
+ ## Attributes
44
+
45
+ | Attribute | Type | Default | Description |
46
+ |------------|---------------------------|-------------|----------------------------------------------------------------|
47
+ | `name` | string | `""` | Form field name; also used as the internal radio group name |
48
+ | `value` | string | `""` | Currently selected value |
49
+ | `options` | string | `"[]"` | JSON array of `{ value, label, disabled?, href? }` objects |
50
+ | `disabled` | boolean | `false` | Disables all options |
51
+ | `variant` | `"outline" \| "filled"` | `"outline"` | Visual style — sliding inset-border or sliding filled thumb |
52
+
53
+ ## Events
54
+
55
+ | Event | Detail | Description |
56
+ |----------|--------|----------------------------------------------------------|
57
+ | `change` | — | Fired when a new segment is selected (radio mode only) |
58
+
59
+ ## Usage in plain HTML
60
+
61
+ ```html
62
+ <!-- Radio mode -->
63
+ <bds-segmented-control
64
+ name="view"
65
+ value="list"
66
+ options='[{"value":"list","label":"List"},{"value":"grid","label":"Grid"}]'
67
+ ></bds-segmented-control>
68
+
69
+ <!-- Link mode -->
70
+ <bds-segmented-control
71
+ variant="outline"
72
+ value="home"
73
+ options='[{"value":"home","label":"Home","href":"/"},{"value":"about","label":"About","href":"/about"}]'
74
+ ></bds-segmented-control>
75
+ ```
76
+
77
+ ## CSS Custom Properties
78
+
79
+ | Property | Default | Description |
80
+ |----------|---------|-------------|
81
+ | `--segmented_color_bg` | `var(--bds-color_bg--subtle)` | Track background colour (both variants) |
82
+ | `--segmented_item-bg` | `transparent` | Inactive item background (outline variant) |
83
+ | `--segmented_item-bg--active` | `var(--bds-color_bg)` | Active item background (outline variant) |
84
+ | `--segmented_thumb-color` | `var(--bds-color_interactive)` | Filled thumb colour (filled variant) |
85
+ | `--segmented_color` | `var(--bds-color_on-bg)` | Item text colour |
86
+ | `--segmented_color--active` | `var(--bds-color_on-interactive)` (filled) / `var(--bds-color_interactive)` (outline) | Active item text colour |
87
+
88
+ ## Accessibility
89
+
90
+ - In radio mode, each option renders as a visually hidden `<input type="radio">` inside a `<label>`, so keyboard users can navigate with arrow keys
91
+ - In link mode, options render as `<a>` elements with `aria-current="page"` on the active item
92
+ - Disabled options have `aria-disabled="true"` and remove the `href` from link mode items
93
+ - `disabled` on the host element disables all options
94
+ - The sliding thumb and indicator use `aria-hidden="true"` so they are not announced by screen readers
95
+ - Participates in HTML forms via the Form-Associated Custom Elements API (radio mode only)