@boostdev/design-system-components 1.1.2 → 1.2.0

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 (169) hide show
  1. package/AGENTS.md +13 -10
  2. package/dist/client.cjs +77 -99
  3. package/dist/client.css +611 -580
  4. package/dist/client.d.cts +13 -16
  5. package/dist/client.d.ts +13 -16
  6. package/dist/client.js +87 -109
  7. package/dist/index.cjs +77 -99
  8. package/dist/index.css +611 -580
  9. package/dist/index.d.cts +13 -16
  10. package/dist/index.d.ts +13 -16
  11. package/dist/index.js +87 -109
  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-O4UFI2RX.js → chunk-3REOIRDW.js} +13 -11
  17. package/dist/web-components/{chunk-K5CE6HSB.js → chunk-6MH5UWUD.js} +74 -17
  18. package/dist/web-components/{chunk-VM3YHGQ2.js → chunk-AJSXNDAP.js} +1 -2
  19. package/dist/web-components/{chunk-LSC4N56Q.js → chunk-BX3IPVOB.js} +1 -2
  20. package/dist/web-components/{chunk-CJ5ZOO42.js → chunk-DI46Q2EA.js} +50 -1
  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-QDRH46TF.js → chunk-QLZ2362S.js} +1 -3
  27. package/dist/web-components/{chunk-IK3PTFZ4.js → chunk-T6AETZRP.js} +1 -3
  28. package/dist/web-components/{chunk-4BX6AWXX.js → chunk-X3FKVHLK.js} +2 -4
  29. package/dist/web-components/{chunk-A67LCT7C.js → chunk-XNA6WTXG.js} +3 -4
  30. package/dist/web-components/{chunk-XIENXR7H.js → chunk-YRXCVKHV.js} +1 -3
  31. package/dist/web-components/{chunk-6T3RKUKG.js → chunk-ZTC6GRP7.js} +1 -2
  32. package/dist/web-components/globals.js +1 -1
  33. package/dist/web-components/index.js +16 -16
  34. package/dist/web-components/interaction/bds-accordion.js +1 -1
  35. package/dist/web-components/interaction/bds-button.d.ts +2 -2
  36. package/dist/web-components/interaction/bds-button.js +1 -1
  37. package/dist/web-components/interaction/bds-dialog.js +1 -1
  38. package/dist/web-components/interaction/bds-drawer.js +1 -1
  39. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  40. package/dist/web-components/interaction/form/bds-combobox.js +1 -1
  41. package/dist/web-components/interaction/form/bds-number-input.js +1 -1
  42. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  43. package/dist/web-components/interaction/form/bds-segmented-control.d.ts +20 -3
  44. package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
  45. package/dist/web-components/interaction/form/bds-select.js +1 -1
  46. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  47. package/dist/web-components/interaction/form/bds-textarea.js +1 -1
  48. package/dist/web-components/ui/bds-alert.js +1 -1
  49. package/dist/web-components/ui/bds-card.js +1 -1
  50. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  51. package/package.json +2 -2
  52. package/src/components/interaction/Button/Button.module.css +12 -11
  53. package/src/components/interaction/Button/Button.native.tsx +10 -9
  54. package/src/components/interaction/Button/Button.tsx +1 -1
  55. package/src/components/interaction/Command/Command.module.css +3 -7
  56. package/src/components/interaction/Dialog/Dialog.module.css +7 -5
  57. package/src/components/interaction/Drawer/Drawer.module.css +49 -1
  58. package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +1 -3
  59. package/src/components/interaction/Popover/Popover.module.css +1 -3
  60. package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -3
  61. package/src/components/interaction/form/Combobox/Combobox.module.css +2 -6
  62. package/src/components/interaction/form/FormInput/FormInput.module.css +1 -3
  63. package/src/components/interaction/form/NumberInput/NumberInput.module.css +16 -4
  64. package/src/components/interaction/form/Radio/Radio.module.css +6 -16
  65. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +70 -25
  66. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +55 -33
  67. package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +127 -56
  68. package/src/components/interaction/form/SegmentedControl/SegmentedControl.stories.tsx +89 -72
  69. package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +40 -62
  70. package/src/components/interaction/form/SegmentedControl/index.ts +1 -1
  71. package/src/components/interaction/form/Select/Select.module.css +2 -4
  72. package/src/components/interaction/form/Switch/Switch.module.css +5 -7
  73. package/src/components/interaction/form/Switch/Switch.native.spec.tsx +9 -9
  74. package/src/components/interaction/form/Switch/Switch.native.tsx +2 -2
  75. package/src/components/interaction/form/Textarea/Textarea.module.css +1 -3
  76. package/src/components/interaction/form/atoms/InputContainer.stories.tsx +64 -0
  77. package/src/components/interaction/form/atoms/Label.stories.tsx +33 -0
  78. package/src/components/interaction/form/atoms/Message.stories.tsx +33 -0
  79. package/src/components/layout/Card/Card.module.css +1 -3
  80. package/src/components/ui/Accordion/Accordion.module.css +1 -2
  81. package/src/components/ui/Alert/Alert.module.css +1 -2
  82. package/src/components/ui/Calendar/Calendar.module.css +2 -5
  83. package/src/components/ui/Carousel/Carousel.module.css +1 -3
  84. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -2
  85. package/src/components/ui/Pagination/Pagination.module.css +1 -2
  86. package/src/components/ui/SkipLink/SkipLink.module.css +1 -2
  87. package/src/components/ui/Table/Table.module.css +1 -2
  88. package/src/css/bdc.css +16 -11
  89. package/src/index.ts +1 -1
  90. package/src/web-components/globals.ts +3 -3
  91. package/src/web-components/interaction/BdsAccordion.mdx +51 -0
  92. package/src/web-components/interaction/BdsAccordion.stories.tsx +85 -0
  93. package/src/web-components/interaction/BdsCollapsible.mdx +46 -0
  94. package/src/web-components/interaction/BdsCollapsible.stories.tsx +87 -0
  95. package/src/web-components/interaction/BdsDialog.mdx +49 -0
  96. package/src/web-components/interaction/BdsDialog.stories.tsx +75 -0
  97. package/src/web-components/interaction/BdsDrawer.mdx +50 -0
  98. package/src/web-components/interaction/BdsDrawer.stories.tsx +66 -0
  99. package/src/web-components/interaction/BdsSkipLink.mdx +34 -0
  100. package/src/web-components/interaction/BdsSkipLink.stories.tsx +55 -0
  101. package/src/web-components/interaction/BdsTabs.mdx +47 -0
  102. package/src/web-components/interaction/BdsTabs.stories.tsx +80 -0
  103. package/src/web-components/interaction/BdsTooltip.mdx +38 -0
  104. package/src/web-components/interaction/BdsTooltip.stories.tsx +68 -0
  105. package/src/web-components/interaction/bds-accordion.ts +1 -2
  106. package/src/web-components/interaction/bds-button.ts +15 -13
  107. package/src/web-components/interaction/bds-dialog.ts +2 -5
  108. package/src/web-components/interaction/bds-drawer.ts +50 -1
  109. package/src/web-components/interaction/form/BdsCheckbox.mdx +39 -0
  110. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +73 -0
  111. package/src/web-components/interaction/form/BdsCombobox.mdx +52 -0
  112. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +91 -0
  113. package/src/web-components/interaction/form/BdsFileInput.mdx +44 -0
  114. package/src/web-components/interaction/form/BdsFileInput.stories.tsx +84 -0
  115. package/src/web-components/interaction/form/BdsNumberInput.mdx +41 -0
  116. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +90 -0
  117. package/src/web-components/interaction/form/BdsRadio.mdx +41 -0
  118. package/src/web-components/interaction/form/BdsRadio.stories.tsx +90 -0
  119. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +42 -0
  120. package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +92 -0
  121. package/src/web-components/interaction/form/BdsSelect.mdx +38 -0
  122. package/src/web-components/interaction/form/BdsSelect.stories.tsx +93 -0
  123. package/src/web-components/interaction/form/BdsSlider.mdx +49 -0
  124. package/src/web-components/interaction/form/BdsSlider.stories.tsx +89 -0
  125. package/src/web-components/interaction/form/BdsSwitch.mdx +39 -0
  126. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +73 -0
  127. package/src/web-components/interaction/form/BdsTextarea.mdx +41 -0
  128. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +79 -0
  129. package/src/web-components/interaction/form/bds-checkbox.ts +1 -3
  130. package/src/web-components/interaction/form/bds-combobox.ts +1 -3
  131. package/src/web-components/interaction/form/bds-number-input.ts +3 -4
  132. package/src/web-components/interaction/form/bds-radio.ts +6 -12
  133. package/src/web-components/interaction/form/bds-segmented-control.ts +91 -20
  134. package/src/web-components/interaction/form/bds-select.ts +2 -4
  135. package/src/web-components/interaction/form/bds-switch.ts +3 -4
  136. package/src/web-components/interaction/form/bds-textarea.ts +1 -3
  137. package/src/web-components/ui/BdsAvatar.mdx +67 -0
  138. package/src/web-components/ui/BdsAvatar.stories.tsx +62 -0
  139. package/src/web-components/ui/BdsBreadcrumb.mdx +63 -0
  140. package/src/web-components/ui/BdsBreadcrumb.stories.tsx +59 -0
  141. package/src/web-components/ui/BdsCard.mdx +83 -0
  142. package/src/web-components/ui/BdsCard.stories.tsx +90 -0
  143. package/src/web-components/ui/BdsDescriptionList.mdx +67 -0
  144. package/src/web-components/ui/BdsDescriptionList.stories.tsx +79 -0
  145. package/src/web-components/ui/BdsIconWrapper.mdx +70 -0
  146. package/src/web-components/ui/BdsIconWrapper.stories.tsx +76 -0
  147. package/src/web-components/ui/BdsLink.mdx +75 -0
  148. package/src/web-components/ui/BdsLink.stories.tsx +64 -0
  149. package/src/web-components/ui/BdsLoading.mdx +62 -0
  150. package/src/web-components/ui/BdsLoading.stories.tsx +37 -0
  151. package/src/web-components/ui/BdsNotificationBanner.mdx +90 -0
  152. package/src/web-components/ui/BdsNotificationBanner.stories.tsx +93 -0
  153. package/src/web-components/ui/BdsProgress.mdx +63 -0
  154. package/src/web-components/ui/BdsProgress.stories.tsx +70 -0
  155. package/src/web-components/ui/BdsProgressCircle.mdx +64 -0
  156. package/src/web-components/ui/BdsProgressCircle.stories.tsx +69 -0
  157. package/src/web-components/ui/BdsRating.mdx +61 -0
  158. package/src/web-components/ui/BdsRating.stories.tsx +39 -0
  159. package/src/web-components/ui/BdsSectionHeader.mdx +69 -0
  160. package/src/web-components/ui/BdsSectionHeader.stories.tsx +56 -0
  161. package/src/web-components/ui/BdsSeparator.mdx +63 -0
  162. package/src/web-components/ui/BdsSeparator.stories.tsx +47 -0
  163. package/src/web-components/ui/BdsSkeleton.mdx +67 -0
  164. package/src/web-components/ui/BdsSkeleton.stories.tsx +50 -0
  165. package/src/web-components/ui/BdsTypography.mdx +83 -0
  166. package/src/web-components/ui/BdsTypography.stories.tsx +51 -0
  167. package/src/web-components/ui/bds-alert.ts +1 -2
  168. package/src/web-components/ui/bds-card.ts +1 -3
  169. package/src/web-components/ui/bds-notification-banner.ts +1 -2
@@ -0,0 +1,38 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsSelect.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # Select
7
+
8
+ `<bds-select>` is a form-associated Select custom element. It uses a JSON `options` attribute because slotting `<option>` elements into a shadow DOM `<select>` is not cross-browser supported.
9
+
10
+ ## Usage
11
+
12
+ ```html
13
+ <bds-select
14
+ name="country"
15
+ placeholder="Choose…"
16
+ options='[{"value":"nl","label":"Netherlands"},{"value":"be","label":"Belgium"}]'
17
+ ></bds-select>
18
+ ```
19
+
20
+ ## Attributes
21
+
22
+ | Attribute | Type | Default | Description |
23
+ |---------------|-----------|---------|------------------------------------------------------|
24
+ | `name` | `string` | `""` | Form field name |
25
+ | `value` | `string` | `""` | Currently selected value |
26
+ | `options` | `string` | `"[]"` | JSON array of `{ value, label, disabled? }` objects |
27
+ | `placeholder` | `string` | `""` | Placeholder option label (disabled, empty value) |
28
+ | `required` | `boolean` | `false` | Marks the field as required |
29
+ | `disabled` | `boolean` | `false` | Disables the select |
30
+
31
+ ## Stories
32
+
33
+ <Canvas of={Stories.Default} />
34
+ <Canvas of={Stories.AllVariants} />
35
+
36
+ ## Controls
37
+
38
+ <ArgTypes of={Stories} />
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import type { SelectOption } from './bds-select';
4
+ import '../../index';
5
+
6
+ const COUNTRIES: SelectOption[] = [
7
+ { value: 'nl', label: 'Netherlands' },
8
+ { value: 'be', label: 'Belgium' },
9
+ { value: 'de', label: 'Germany' },
10
+ { value: 'fr', label: 'France' },
11
+ { value: 'gb', label: 'United Kingdom', disabled: true },
12
+ ];
13
+
14
+ function BdsSelect({
15
+ placeholder = 'Choose an option…',
16
+ disabled,
17
+ required,
18
+ }: {
19
+ placeholder?: string;
20
+ disabled?: boolean;
21
+ required?: boolean;
22
+ }) {
23
+ return React.createElement('bds-select', {
24
+ options: JSON.stringify(COUNTRIES),
25
+ placeholder,
26
+ disabled: disabled || undefined,
27
+ required: required || undefined,
28
+ style: { minInlineSize: '200px', display: 'block' },
29
+ });
30
+ }
31
+
32
+ const meta = {
33
+ title: 'Web Components/Interaction/Form/Select',
34
+ component: BdsSelect,
35
+ tags: ['!stable', 'experimental'],
36
+ parameters: { layout: 'padded' },
37
+ argTypes: {
38
+ disabled: { control: 'boolean' },
39
+ required: { control: 'boolean' },
40
+ },
41
+ } satisfies Meta<typeof BdsSelect>;
42
+
43
+ export default meta;
44
+ type Story = StoryObj<typeof meta>;
45
+
46
+ export const Default: Story = { args: { placeholder: 'Select a country…' } };
47
+ export const Disabled: Story = { args: { placeholder: 'Select a country…', disabled: true } };
48
+ export const WithValue: Story = {
49
+ render: () =>
50
+ React.createElement('bds-select', {
51
+ options: JSON.stringify(COUNTRIES),
52
+ value: 'nl',
53
+ style: { minInlineSize: '200px', display: 'block' },
54
+ }),
55
+ };
56
+
57
+ export const AllVariants: Story = {
58
+ render: () => (
59
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxInlineSize: '300px' }}>
60
+ <div>
61
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Default</p>
62
+ {React.createElement('bds-select', { options: JSON.stringify(COUNTRIES), placeholder: 'Choose…' })}
63
+ </div>
64
+ <div>
65
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>With value</p>
66
+ {React.createElement('bds-select', { options: JSON.stringify(COUNTRIES), value: 'be' })}
67
+ </div>
68
+ <div>
69
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Disabled</p>
70
+ {React.createElement('bds-select', { options: JSON.stringify(COUNTRIES), placeholder: 'Choose…', disabled: true })}
71
+ </div>
72
+ </div>
73
+ ),
74
+ };
75
+
76
+ export const Interactive: Story = {
77
+ render: () => {
78
+ const [value, setValue] = React.useState('');
79
+ return (
80
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', maxInlineSize: '300px' }}>
81
+ <p style={{ margin: '0 0 8px', fontSize: '0.875rem' }}>
82
+ Selected: {value ? COUNTRIES.find(c => c.value === value)?.label : '(none)'}
83
+ </p>
84
+ {React.createElement('bds-select', {
85
+ options: JSON.stringify(COUNTRIES),
86
+ placeholder: 'Select a country…',
87
+ value,
88
+ onChange: (e: Event) => setValue((e.target as HTMLSelectElement).value),
89
+ })}
90
+ </div>
91
+ );
92
+ },
93
+ };
@@ -0,0 +1,49 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsSlider.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # Slider
7
+
8
+ `<bds-slider>` is a form-associated range input. The fill track is driven by the `--slider_fill` CSS custom property and updates as the user drags.
9
+
10
+ ## Usage
11
+
12
+ ```html
13
+ <bds-slider name="volume" value="50" min="0" max="100" step="5"></bds-slider>
14
+ ```
15
+
16
+ ## Attributes
17
+
18
+ | Attribute | Type | Default | Description |
19
+ |------------|-----------|---------|----------------------------------|
20
+ | `name` | `string` | `""` | Form field name |
21
+ | `value` | `number` | `0` | Current value |
22
+ | `min` | `number` | `0` | Minimum value |
23
+ | `max` | `number` | `100` | Maximum value |
24
+ | `step` | `number` | `1` | Step increment |
25
+ | `disabled` | `boolean` | `false` | Disables interaction |
26
+
27
+ ## Events
28
+
29
+ | Event | Description |
30
+ |----------|-------------------------------|
31
+ | `input` | Fired as the user drags |
32
+ | `change` | Fired when the user releases |
33
+
34
+ ## CSS Custom Properties
35
+
36
+ | Property | Description |
37
+ |-----------------------|--------------------------------|
38
+ | `--slider_fill-color` | Fill track color (default: `--bds-color_interactive`) |
39
+ | `--slider_track-color`| Unfilled track color |
40
+ | `--slider_thumb-color`| Thumb color |
41
+
42
+ ## Stories
43
+
44
+ <Canvas of={Stories.Default} />
45
+ <Canvas of={Stories.AllVariants} />
46
+
47
+ ## Controls
48
+
49
+ <ArgTypes of={Stories} />
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../../index';
4
+
5
+ function BdsSlider({
6
+ value,
7
+ min,
8
+ max,
9
+ step,
10
+ disabled,
11
+ }: {
12
+ value?: number;
13
+ min?: number;
14
+ max?: number;
15
+ step?: number;
16
+ disabled?: boolean;
17
+ }) {
18
+ return React.createElement('bds-slider', {
19
+ value,
20
+ min,
21
+ max,
22
+ step,
23
+ disabled: disabled || undefined,
24
+ style: { display: 'block', maxInlineSize: '320px' },
25
+ });
26
+ }
27
+
28
+ const meta = {
29
+ title: 'Web Components/Interaction/Form/Slider',
30
+ component: BdsSlider,
31
+ tags: ['!stable', 'experimental'],
32
+ parameters: { layout: 'padded' },
33
+ argTypes: {
34
+ value: { control: 'number' },
35
+ min: { control: 'number' },
36
+ max: { control: 'number' },
37
+ step: { control: 'number' },
38
+ disabled: { control: 'boolean' },
39
+ },
40
+ } satisfies Meta<typeof BdsSlider>;
41
+
42
+ export default meta;
43
+ type Story = StoryObj<typeof meta>;
44
+
45
+ export const Default: Story = { args: { value: 50 } };
46
+ export const WithStep: Story = { args: { value: 25, min: 0, max: 100, step: 25 } };
47
+ export const Disabled: Story = { args: { value: 60, disabled: true } };
48
+
49
+ export const AllVariants: Story = {
50
+ render: () => (
51
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '24px', maxInlineSize: '320px' }}>
52
+ <div>
53
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Default (0%)</p>
54
+ {React.createElement('bds-slider', { value: 0, style: { display: 'block' } })}
55
+ </div>
56
+ <div>
57
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Mid (50%)</p>
58
+ {React.createElement('bds-slider', { value: 50, style: { display: 'block' } })}
59
+ </div>
60
+ <div>
61
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Full (100%)</p>
62
+ {React.createElement('bds-slider', { value: 100, style: { display: 'block' } })}
63
+ </div>
64
+ <div>
65
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Disabled</p>
66
+ {React.createElement('bds-slider', { value: 40, disabled: true, style: { display: 'block' } })}
67
+ </div>
68
+ </div>
69
+ ),
70
+ };
71
+
72
+ export const Interactive: Story = {
73
+ render: () => {
74
+ const [volume, setVolume] = React.useState(50);
75
+ return (
76
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', maxInlineSize: '320px' }}>
77
+ <p style={{ margin: '0 0 4px', fontSize: '0.875rem' }}>Volume: {volume}%</p>
78
+ {React.createElement('bds-slider', {
79
+ value: volume,
80
+ min: 0,
81
+ max: 100,
82
+ step: 1,
83
+ style: { display: 'block' },
84
+ onInput: (e: Event) => setVolume(parseFloat((e.target as HTMLInputElement).value)),
85
+ })}
86
+ </div>
87
+ );
88
+ },
89
+ };
@@ -0,0 +1,39 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsSwitch.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # Switch
7
+
8
+ `<bds-switch>` is a visually styled toggle switch. Semantically equivalent to a checkbox (`role="switch"`), it participates in HTML forms via the Form-Associated Custom Elements API.
9
+
10
+ ## Usage
11
+
12
+ ```html
13
+ <bds-switch name="notifications" value="enabled">Enable notifications</bds-switch>
14
+ ```
15
+
16
+ ## Attributes
17
+
18
+ | Attribute | Type | Default | Description |
19
+ |------------|-----------|---------|-------------------------------------|
20
+ | `name` | `string` | `""` | Form field name |
21
+ | `value` | `string` | `"on"` | Submitted value when on |
22
+ | `checked` | `boolean` | `false` | Whether the switch is on |
23
+ | `required` | `boolean` | `false` | Marks the field as required |
24
+ | `disabled` | `boolean` | `false` | Disables interaction |
25
+
26
+ ## Slots
27
+
28
+ | Slot | Description |
29
+ |-----------|---------------|
30
+ | (default) | Label text |
31
+
32
+ ## Stories
33
+
34
+ <Canvas of={Stories.Default} />
35
+ <Canvas of={Stories.AllVariants} />
36
+
37
+ ## Controls
38
+
39
+ <ArgTypes of={Stories} />
@@ -0,0 +1,73 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../../index';
4
+
5
+ function BdsSwitch({
6
+ label = 'Enable feature',
7
+ checked,
8
+ disabled,
9
+ }: {
10
+ label?: string;
11
+ checked?: boolean;
12
+ disabled?: boolean;
13
+ }) {
14
+ return React.createElement(
15
+ 'bds-switch',
16
+ {
17
+ checked: checked || undefined,
18
+ disabled: disabled || undefined,
19
+ },
20
+ label,
21
+ );
22
+ }
23
+
24
+ const meta = {
25
+ title: 'Web Components/Interaction/Form/Switch',
26
+ component: BdsSwitch,
27
+ tags: ['!stable', 'experimental'],
28
+ parameters: { layout: 'padded' },
29
+ argTypes: {
30
+ checked: { control: 'boolean' },
31
+ disabled: { control: 'boolean' },
32
+ },
33
+ } satisfies Meta<typeof BdsSwitch>;
34
+
35
+ export default meta;
36
+ type Story = StoryObj<typeof meta>;
37
+
38
+ export const Default: Story = { args: { label: 'Enable notifications' } };
39
+ export const On: Story = { args: { label: 'Notifications enabled', checked: true } };
40
+ export const Disabled: Story = { args: { label: 'Managed by admin', disabled: true } };
41
+ export const DisabledOn: Story = { args: { label: 'Always on (managed)', checked: true, disabled: true } };
42
+
43
+ export const AllVariants: Story = {
44
+ render: () => (
45
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
46
+ {React.createElement('bds-switch', null, 'Off (default)')}
47
+ {React.createElement('bds-switch', { checked: true }, 'On')}
48
+ {React.createElement('bds-switch', { disabled: true }, 'Disabled off')}
49
+ {React.createElement('bds-switch', { checked: true, disabled: true }, 'Disabled on')}
50
+ </div>
51
+ ),
52
+ };
53
+
54
+ export const Interactive: Story = {
55
+ render: () => {
56
+ const [enabled, setEnabled] = React.useState(false);
57
+ return (
58
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
59
+ <p style={{ margin: '0 0 8px', fontSize: '0.875rem' }}>
60
+ Dark mode: {enabled ? 'enabled' : 'disabled'}
61
+ </p>
62
+ {React.createElement(
63
+ 'bds-switch',
64
+ {
65
+ checked: enabled || undefined,
66
+ onChange: (e: Event) => setEnabled((e.target as HTMLInputElement).checked),
67
+ },
68
+ 'Dark mode',
69
+ )}
70
+ </div>
71
+ );
72
+ },
73
+ };
@@ -0,0 +1,41 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsTextarea.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # Textarea
7
+
8
+ `<bds-textarea>` wraps a native `<textarea>` for consistent styling while participating in HTML forms via the Form-Associated Custom Elements API.
9
+
10
+ ## Usage
11
+
12
+ ```html
13
+ <bds-textarea name="message" placeholder="Enter your message…" rows="6"></bds-textarea>
14
+ ```
15
+
16
+ ## Attributes
17
+
18
+ | Attribute | Type | Default | Description |
19
+ |---------------|-----------|---------|------------------------------|
20
+ | `name` | `string` | `""` | Form field name |
21
+ | `value` | `string` | `""` | Current text value |
22
+ | `placeholder` | `string` | `""` | Placeholder text |
23
+ | `rows` | `number` | `4` | Number of visible rows |
24
+ | `required` | `boolean` | `false` | Marks the field as required |
25
+ | `disabled` | `boolean` | `false` | Disables the textarea |
26
+
27
+ ## Events
28
+
29
+ | Event | Description |
30
+ |----------|------------------------------------|
31
+ | `input` | Fired as the user types |
32
+ | `change` | Fired when value is committed |
33
+
34
+ ## Stories
35
+
36
+ <Canvas of={Stories.Default} />
37
+ <Canvas of={Stories.AllVariants} />
38
+
39
+ ## Controls
40
+
41
+ <ArgTypes of={Stories} />
@@ -0,0 +1,79 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../../index';
4
+
5
+ function BdsTextarea({
6
+ placeholder = 'Enter text…',
7
+ rows,
8
+ disabled,
9
+ required,
10
+ }: {
11
+ placeholder?: string;
12
+ rows?: number;
13
+ disabled?: boolean;
14
+ required?: boolean;
15
+ }) {
16
+ return React.createElement('bds-textarea', {
17
+ placeholder,
18
+ rows,
19
+ disabled: disabled || undefined,
20
+ required: required || undefined,
21
+ style: { display: 'block', maxInlineSize: '400px' },
22
+ });
23
+ }
24
+
25
+ const meta = {
26
+ title: 'Web Components/Interaction/Form/Textarea',
27
+ component: BdsTextarea,
28
+ tags: ['!stable', 'experimental'],
29
+ parameters: { layout: 'padded' },
30
+ argTypes: {
31
+ rows: { control: 'number' },
32
+ disabled: { control: 'boolean' },
33
+ required: { control: 'boolean' },
34
+ },
35
+ } satisfies Meta<typeof BdsTextarea>;
36
+
37
+ export default meta;
38
+ type Story = StoryObj<typeof meta>;
39
+
40
+ export const Default: Story = { args: { placeholder: 'Enter your message…' } };
41
+ export const WithRows: Story = { args: { placeholder: 'Extended text area…', rows: 8 } };
42
+ export const Disabled: Story = { args: { placeholder: 'Not editable', disabled: true } };
43
+
44
+ export const AllVariants: Story = {
45
+ render: () => (
46
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxInlineSize: '400px' }}>
47
+ <div>
48
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Default (4 rows)</p>
49
+ {React.createElement('bds-textarea', { placeholder: 'Write something…' })}
50
+ </div>
51
+ <div>
52
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Tall (8 rows)</p>
53
+ {React.createElement('bds-textarea', { placeholder: 'More space to write…', rows: 8 })}
54
+ </div>
55
+ <div>
56
+ <p style={{ margin: '0 0 4px', fontSize: '0.75rem', color: '#888' }}>Disabled</p>
57
+ {React.createElement('bds-textarea', { placeholder: 'Read-only area', disabled: true })}
58
+ </div>
59
+ </div>
60
+ ),
61
+ };
62
+
63
+ export const Interactive: Story = {
64
+ render: () => {
65
+ const [value, setValue] = React.useState('');
66
+ return (
67
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', maxInlineSize: '400px' }}>
68
+ <p style={{ margin: '0 0 4px', fontSize: '0.875rem' }}>
69
+ Characters: {value.length}
70
+ </p>
71
+ {React.createElement('bds-textarea', {
72
+ placeholder: 'Start typing…',
73
+ value,
74
+ onInput: (e: Event) => setValue((e.target as HTMLTextAreaElement).value),
75
+ })}
76
+ </div>
77
+ );
78
+ },
79
+ };
@@ -52,10 +52,8 @@ export class BdsCheckbox extends LitElement {
52
52
  --bdc_color: currentcolor;
53
53
  --bdc-outline_radius: var(--bds-border_radius--xs);
54
54
 
55
- outline: var(--bdc-outline_width) solid var(--bdc_color);
56
- outline-offset: var(--bdc-outline_offset);
57
55
  border-radius: var(--checkbox_radius, var(--bdc-outline_radius));
58
- box-shadow: var(--checkbox_shadow, var(--bdc-outline_shadow));
56
+ box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--checkbox_shadow, var(--bdc-outline_shadow));
59
57
  border: none;
60
58
  appearance: none;
61
59
  background-color: var(--checkbox_color_bg, var(--bds-color_bg));
@@ -57,10 +57,8 @@ export class BdsCombobox extends LitElement {
57
57
  --bdc_color: currentcolor;
58
58
  --bdc-outline_radius: var(--bds-border_radius--xs);
59
59
 
60
- outline: var(--bdc-outline_width) solid var(--bdc_color);
61
- outline-offset: var(--bdc-outline_offset);
62
60
  border-radius: var(--combobox_radius, var(--bdc-outline_radius));
63
- box-shadow: var(--combobox_shadow, var(--bdc-outline_shadow));
61
+ box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--combobox_shadow, var(--bdc-outline_shadow));
64
62
  background-color: var(--combobox_color_bg, var(--bds-color_bg));
65
63
  color: var(--combobox_color, var(--bds-color_on-bg));
66
64
  box-sizing: border-box;
@@ -45,10 +45,8 @@ export class BdsNumberInput extends LitElement {
45
45
  --bdc_color: currentcolor;
46
46
  --bdc-outline_radius: var(--bds-border_radius--xs);
47
47
 
48
- outline: var(--bdc-outline_width) solid var(--bdc_color);
49
- outline-offset: var(--bdc-outline_offset);
50
48
  border-radius: var(--number-input_radius, var(--bdc-outline_radius));
51
- box-shadow: var(--number-input_shadow, var(--bdc-outline_shadow));
49
+ box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--number-input_shadow, var(--bdc-outline_shadow));
52
50
  background-color: var(--number-input_color_bg, var(--bds-color_bg));
53
51
  color: var(--number-input_color, var(--bds-color_on-bg));
54
52
  text-align: center;
@@ -76,12 +74,13 @@ export class BdsNumberInput extends LitElement {
76
74
  display: flex;
77
75
  align-items: center;
78
76
  justify-content: center;
77
+ margin: 1px;
79
78
  inline-size: 2rem;
80
79
  block-size: 2rem;
81
80
  border-radius: var(--bds-border_radius--xs);
82
81
  cursor: pointer;
83
82
  flex-shrink: 0;
84
- color: var(--bds-color_on-bg);
83
+ color: var(--bds-color_interactive);
85
84
  transition: var(--bds-animation_transition);
86
85
  }
87
86
 
@@ -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-color: var(--radio_color-active, var(--bdc-color_active));
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);