@boostdev/design-system-components 1.2.8 → 2.1.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 (176) hide show
  1. package/AGENTS.md +5 -3
  2. package/README.md +57 -38
  3. package/dist/client.cjs +52 -50
  4. package/dist/client.css +537 -524
  5. package/dist/client.d.cts +31 -1
  6. package/dist/client.d.ts +31 -1
  7. package/dist/client.js +52 -50
  8. package/dist/index.cjs +52 -50
  9. package/dist/index.css +537 -524
  10. package/dist/index.d.cts +31 -1
  11. package/dist/index.d.ts +31 -1
  12. package/dist/index.js +52 -50
  13. package/dist/native/index.cjs +5 -2
  14. package/dist/native/index.d.cts +3 -1
  15. package/dist/native/index.d.ts +3 -1
  16. package/dist/native/index.js +5 -2
  17. package/dist/web-components/{chunk-DZRSJGPB.js → chunk-3S42DZ7W.js} +1 -1
  18. package/dist/web-components/{chunk-3REOIRDW.js → chunk-N3TN6WCH.js} +26 -1
  19. package/dist/web-components/globals.js +1 -1
  20. package/dist/web-components/index.js +2 -2
  21. package/dist/web-components/interaction/bds-button.d.ts +7 -0
  22. package/dist/web-components/interaction/bds-button.js +1 -1
  23. package/package.json +3 -3
  24. package/src/components/interaction/Button/Button.mdx +84 -29
  25. package/src/components/interaction/Button/Button.module.css +25 -1
  26. package/src/components/interaction/Button/Button.native.mdx +33 -14
  27. package/src/components/interaction/Button/Button.native.spec.tsx +20 -0
  28. package/src/components/interaction/Button/Button.native.stories.tsx +110 -9
  29. package/src/components/interaction/Button/Button.native.tsx +13 -4
  30. package/src/components/interaction/Button/Button.spec.tsx +16 -0
  31. package/src/components/interaction/Button/Button.stories.tsx +134 -16
  32. package/src/components/interaction/Button/Button.tsx +32 -0
  33. package/src/components/interaction/Command/Command.module.css +1 -1
  34. package/src/components/interaction/Dialog/Dialog.module.css +1 -1
  35. package/src/components/interaction/Dialog/Dialog.native.mdx +2 -2
  36. package/src/components/interaction/Drawer/Drawer.module.css +1 -1
  37. package/src/components/interaction/Drawer/Drawer.native.mdx +2 -2
  38. package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +1 -1
  39. package/src/components/interaction/DropdownMenu/DropdownMenu.native.mdx +2 -2
  40. package/src/components/interaction/Popover/Popover.module.css +1 -1
  41. package/src/components/interaction/Popover/Popover.native.mdx +2 -2
  42. package/src/components/interaction/Rating/Rating.module.css +1 -1
  43. package/src/components/interaction/Rating/Rating.native.mdx +1 -1
  44. package/src/components/interaction/Toast/Toast.module.css +1 -1
  45. package/src/components/interaction/Toast/Toast.native.mdx +3 -3
  46. package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -1
  47. package/src/components/interaction/form/Checkbox/Checkbox.native.mdx +1 -1
  48. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +1 -1
  49. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.native.mdx +1 -1
  50. package/src/components/interaction/form/Combobox/Combobox.module.css +1 -1
  51. package/src/components/interaction/form/Combobox/Combobox.native.mdx +1 -1
  52. package/src/components/interaction/form/FileInput/FileInput.module.css +1 -1
  53. package/src/components/interaction/form/FileInput/FileInput.native.mdx +1 -1
  54. package/src/components/interaction/form/FormInput/FormInput.module.css +1 -1
  55. package/src/components/interaction/form/FormInput/FormInput.native.mdx +1 -1
  56. package/src/components/interaction/form/NumberInput/NumberInput.module.css +1 -1
  57. package/src/components/interaction/form/NumberInput/NumberInput.native.mdx +1 -1
  58. package/src/components/interaction/form/Radio/Radio.module.css +1 -1
  59. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +1 -1
  60. package/src/components/interaction/form/RadioGroup/RadioGroup.native.mdx +1 -1
  61. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +1 -1
  62. package/src/components/interaction/form/SegmentedControl/SegmentedControl.native.mdx +1 -1
  63. package/src/components/interaction/form/Select/Select.module.css +1 -1
  64. package/src/components/interaction/form/Select/Select.native.mdx +1 -1
  65. package/src/components/interaction/form/Slider/Slider.module.css +1 -1
  66. package/src/components/interaction/form/Slider/Slider.native.mdx +1 -1
  67. package/src/components/interaction/form/Switch/Switch.module.css +1 -1
  68. package/src/components/interaction/form/Textarea/Textarea.module.css +1 -1
  69. package/src/components/interaction/form/Textarea/Textarea.native.mdx +1 -1
  70. package/src/components/interaction/form/atoms/InputContainer.module.css +1 -1
  71. package/src/components/interaction/form/atoms/Label.module.css +1 -1
  72. package/src/components/interaction/form/atoms/Message.module.css +1 -1
  73. package/src/components/layout/ButtonGroup/ButtonGroup.module.css +1 -1
  74. package/src/components/layout/Card/Card.module.css +1 -1
  75. package/src/components/layout/IconWrapper/IconWrapper.module.css +1 -1
  76. package/src/components/layout/IconWrapper/IconWrapper.stories.tsx +46 -14
  77. package/src/components/layout/SectionHeader/SectionHeader.module.css +1 -1
  78. package/src/components/ui/Accordion/Accordion.module.css +1 -1
  79. package/src/components/ui/Accordion/Accordion.native.mdx +1 -1
  80. package/src/components/ui/Accordion/Accordion.native.stories.tsx +1 -1
  81. package/src/components/ui/Alert/Alert.module.css +1 -1
  82. package/src/components/ui/Alert/Alert.native.mdx +1 -1
  83. package/src/components/ui/Avatar/Avatar.module.css +1 -1
  84. package/src/components/ui/Avatar/Avatar.native.mdx +1 -1
  85. package/src/components/ui/Badge/Badge.module.css +1 -1
  86. package/src/components/ui/Badge/Badge.native.mdx +1 -1
  87. package/src/components/ui/Breadcrumb/Breadcrumb.module.css +1 -1
  88. package/src/components/ui/Breadcrumb/Breadcrumb.native.mdx +1 -1
  89. package/src/components/ui/Calendar/Calendar.module.css +1 -1
  90. package/src/components/ui/Calendar/Calendar.native.mdx +1 -1
  91. package/src/components/ui/Carousel/Carousel.module.css +1 -1
  92. package/src/components/ui/Carousel/Carousel.native.mdx +1 -1
  93. package/src/components/ui/Collapsible/Collapsible.module.css +1 -1
  94. package/src/components/ui/Collapsible/Collapsible.native.mdx +1 -1
  95. package/src/components/ui/DescriptionList/DescriptionList.module.css +1 -1
  96. package/src/components/ui/DescriptionList/DescriptionList.native.mdx +1 -1
  97. package/src/components/ui/Link/Link.module.css +1 -1
  98. package/src/components/ui/Link/Link.native.mdx +1 -1
  99. package/src/components/ui/Loading/Loading.module.css +1 -1
  100. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -1
  101. package/src/components/ui/Pagination/Pagination.module.css +1 -1
  102. package/src/components/ui/Pagination/Pagination.native.mdx +1 -1
  103. package/src/components/ui/Progress/Progress.module.css +1 -1
  104. package/src/components/ui/ProgressCircle/ProgressCircle.module.css +1 -1
  105. package/src/components/ui/ProgressCircle/ProgressCircle.native.mdx +1 -1
  106. package/src/components/ui/Separator/Separator.module.css +1 -1
  107. package/src/components/ui/Skeleton/Skeleton.module.css +1 -1
  108. package/src/components/ui/SkipLink/SkipLink.module.css +1 -1
  109. package/src/components/ui/Table/Table.module.css +1 -1
  110. package/src/components/ui/Table/Table.native.mdx +1 -1
  111. package/src/components/ui/Tabs/Tabs.module.css +1 -1
  112. package/src/components/ui/Tabs/Tabs.native.mdx +1 -1
  113. package/src/components/ui/Tooltip/Tooltip.module.css +1 -1
  114. package/src/components/ui/Tooltip/Tooltip.native.mdx +1 -1
  115. package/src/components/ui/Typography/Typography.module.css +1 -1
  116. package/src/components/ui/Typography/Typography.native.mdx +1 -1
  117. package/src/css/bdc.css +1 -1
  118. package/src/css/index.css +1 -1
  119. package/src/stories/DesignSystem/Borders.mdx +3 -3
  120. package/src/stories/DesignSystem/Colors.mdx +1 -1
  121. package/src/stories/DesignSystem/DarkMode.mdx +3 -3
  122. package/src/stories/DesignSystem/Overview.mdx +16 -5
  123. package/src/stories/DesignSystem/Typography.mdx +1 -1
  124. package/src/stories/Introduction.mdx +4 -4
  125. package/src/stories/ReactNative.mdx +6 -6
  126. package/src/web-components/globals.ts +1 -1
  127. package/src/web-components/interaction/BdsAccordion.mdx +3 -3
  128. package/src/web-components/interaction/BdsAccordion.stories.tsx +1 -1
  129. package/src/web-components/interaction/BdsButton.mdx +48 -16
  130. package/src/web-components/interaction/BdsButton.stories.tsx +171 -19
  131. package/src/web-components/interaction/BdsCollapsible.mdx +2 -2
  132. package/src/web-components/interaction/BdsDialog.mdx +2 -2
  133. package/src/web-components/interaction/BdsDrawer.mdx +2 -2
  134. package/src/web-components/interaction/BdsDropdownMenu.mdx +2 -2
  135. package/src/web-components/interaction/BdsPopover.mdx +1 -1
  136. package/src/web-components/interaction/BdsSkipLink.mdx +2 -2
  137. package/src/web-components/interaction/BdsTabs.mdx +2 -2
  138. package/src/web-components/interaction/BdsToastProvider.mdx +3 -3
  139. package/src/web-components/interaction/BdsTooltip.mdx +2 -2
  140. package/src/web-components/interaction/bds-button.spec.ts +35 -0
  141. package/src/web-components/interaction/bds-button.ts +28 -1
  142. package/src/web-components/interaction/form/BdsCheckbox.mdx +1 -1
  143. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +1 -1
  144. package/src/web-components/interaction/form/BdsCombobox.mdx +1 -1
  145. package/src/web-components/interaction/form/BdsFileInput.mdx +1 -1
  146. package/src/web-components/interaction/form/BdsFormInput.mdx +1 -1
  147. package/src/web-components/interaction/form/BdsNumberInput.mdx +1 -1
  148. package/src/web-components/interaction/form/BdsRadio.mdx +1 -1
  149. package/src/web-components/interaction/form/BdsRadioGroup.mdx +1 -1
  150. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +1 -1
  151. package/src/web-components/interaction/form/BdsSelect.mdx +1 -1
  152. package/src/web-components/interaction/form/BdsSlider.mdx +1 -1
  153. package/src/web-components/interaction/form/BdsSwitch.mdx +1 -1
  154. package/src/web-components/interaction/form/BdsTextarea.mdx +1 -1
  155. package/src/web-components/ui/BdsAlert.mdx +1 -1
  156. package/src/web-components/ui/BdsAvatar.mdx +1 -1
  157. package/src/web-components/ui/BdsBadge.mdx +1 -1
  158. package/src/web-components/ui/BdsBreadcrumb.mdx +1 -1
  159. package/src/web-components/ui/BdsButtonGroup.mdx +1 -1
  160. package/src/web-components/ui/BdsCalendar.mdx +1 -1
  161. package/src/web-components/ui/BdsCard.mdx +1 -1
  162. package/src/web-components/ui/BdsCarousel.mdx +1 -1
  163. package/src/web-components/ui/BdsDescriptionList.mdx +1 -1
  164. package/src/web-components/ui/BdsIconWrapper.mdx +1 -1
  165. package/src/web-components/ui/BdsLink.mdx +1 -1
  166. package/src/web-components/ui/BdsLoading.mdx +1 -1
  167. package/src/web-components/ui/BdsNotificationBanner.mdx +1 -1
  168. package/src/web-components/ui/BdsPagination.mdx +1 -1
  169. package/src/web-components/ui/BdsProgress.mdx +1 -1
  170. package/src/web-components/ui/BdsProgressCircle.mdx +1 -1
  171. package/src/web-components/ui/BdsRating.mdx +1 -1
  172. package/src/web-components/ui/BdsSectionHeader.mdx +1 -1
  173. package/src/web-components/ui/BdsSeparator.mdx +2 -2
  174. package/src/web-components/ui/BdsSkeleton.mdx +1 -1
  175. package/src/web-components/ui/BdsTable.mdx +1 -1
  176. package/src/web-components/ui/BdsTypography.mdx +1 -1
@@ -127,7 +127,7 @@ Override a component's border colour for a specific context by reassigning `--bd
127
127
  }
128
128
 
129
129
  /* Override globally via the token layer */
130
- @layer tokens.override {
130
+ @layer boostdev.tokens.override {
131
131
  :root {
132
132
  --bdc_color: var(--bds-color_green);
133
133
  }
@@ -151,8 +151,8 @@ The `bdc` tokens are included automatically when you import the component styles
151
151
 
152
152
  ```css
153
153
  /* Included automatically with the full component CSS */
154
- @import '@boostdev/components/css';
154
+ @import '@boostdev/design-system-components/css';
155
155
 
156
156
  /* Or load the token layer standalone */
157
- @import '@boostdev/components/css/bdc';
157
+ @import '@boostdev/design-system-components/css/bdc';
158
158
  ```
@@ -184,7 +184,7 @@ These `--bds-BASE__color--*` tokens are the primitive values. **Do not use them
184
184
  Override `--bds-color_green` and `--bds-color_interactive` to change the primary action colour globally:
185
185
 
186
186
  ```css
187
- @layer tokens.override {
187
+ @layer boostdev.tokens.override {
188
188
  :root {
189
189
  --bds-color_green: var(--bds-BASE__color--blue);
190
190
  --bds-color_on-green: var(--bds-BASE__color--white);
@@ -85,20 +85,20 @@ function ThemeToggle() {
85
85
 
86
86
  ## Customising tokens in dark mode
87
87
 
88
- Override any token in `@layer tokens.override` — the rule applies regardless of the active theme unless you scope it:
88
+ Override any token in `@layer boostdev.tokens.override` — the rule applies regardless of the active theme unless you scope it:
89
89
 
90
90
  ```css
91
91
  @import "@boostdev/design-system-foundation/css";
92
92
 
93
93
  /* override for all themes */
94
- @layer tokens.override {
94
+ @layer boostdev.tokens.override {
95
95
  :root {
96
96
  --bds-color_green: oklch(60% 0.15 145);
97
97
  }
98
98
  }
99
99
 
100
100
  /* override for dark mode only */
101
- @layer tokens.override {
101
+ @layer boostdev.tokens.override {
102
102
  [data-theme="dark"],
103
103
  @media (prefers-color-scheme: dark) {
104
104
  :root:not([data-theme="light"]) {
@@ -49,14 +49,25 @@ import '@boostdev/design-system-foundation/css';
49
49
 
50
50
  ## Layer architecture
51
51
 
52
- All tokens live inside `@layer` declarations. The cascade order, from lowest to highest, is:
52
+ All tokens live inside `@layer` declarations, all prefixed with `boostdev.` to prevent collisions
53
+ with consumer layers of the same name. The cascade order, from lowest to highest, is:
53
54
 
54
55
  ```
55
- tokens.base → tokens.semantic → tokens.override → reset → base → utilities → component
56
+ boostdev.tokens.base →
57
+ boostdev.tokens.semantic →
58
+ boostdev.tokens.deprecated →
59
+ boostdev.tokens.override →
60
+ boostdev.reset →
61
+ boostdev.base →
62
+ boostdev.utilities →
63
+ boostdev.components →
64
+ boostdev.component
56
65
  ```
57
66
 
58
- `@layer component` — used by every component in this library — sits above the token layers,
59
- so you can override any component from `@layer my-overrides` without specificity fights.
67
+ `@layer boostdev.component` — used by every component in this library — sits above the token layers,
68
+ so you can override any component from your own layer (e.g. `@layer my-overrides`) without
69
+ specificity fights. Anything written outside of any `@layer` is treated as an unlayered declaration,
70
+ which is the highest-priority in the cascade.
60
71
 
61
72
  ## Theming
62
73
 
@@ -78,7 +89,7 @@ Override any token in your own layer to retheme:
78
89
  ```css
79
90
  @import "@boostdev/design-system-foundation/css";
80
91
 
81
- @layer tokens.override {
92
+ @layer boostdev.tokens.override {
82
93
  :root {
83
94
  --bds-cta: var(--bds-BASE__color--blue);
84
95
  --bds-color_on-green: var(--bds-BASE__color--white);
@@ -49,7 +49,7 @@ export const TrackingSample = ({ token, label, value }) => (
49
49
  Override both tokens to apply a custom typeface globally:
50
50
 
51
51
  ```css
52
- @layer tokens.override {
52
+ @layer boostdev.tokens.override {
53
53
  :root {
54
54
  --bds-font_family--heading: 'Inter', sans-serif;
55
55
  --bds-font_family--body: 'Inter', sans-serif;
@@ -30,20 +30,20 @@ import logo from '../static/logo.svg';
30
30
  ## Installation
31
31
 
32
32
  ```bash
33
- pnpm add @boostdev/components @boostdev/design-system-foundation
33
+ pnpm add @boostdev/design-system-components @boostdev/design-system-foundation
34
34
  ```
35
35
 
36
36
  Import the CSS once at your app root:
37
37
 
38
38
  ```ts
39
39
  import '@boostdev/design-system-foundation/css';
40
- import '@boostdev/components/css';
40
+ import '@boostdev/design-system-components/css';
41
41
  ```
42
42
 
43
43
  For **Next.js / RSC**, use the `/client` subpath:
44
44
 
45
45
  ```ts
46
- import {Button, Card} from '@boostdev/components/client';
46
+ import {Button, Card} from '@boostdev/design-system-components/client';
47
47
  ```
48
48
 
49
49
  ---
@@ -92,7 +92,7 @@ import logo from '../static/logo.svg';
92
92
  everything at once:
93
93
 
94
94
  ```css
95
- @layer tokens.override {
95
+ @layer boostdev.tokens.override {
96
96
  :root {
97
97
  --bds-cta: var(--bds-BASE__color--orange);
98
98
  --bds-on-cta: var(--bds-BASE__color--white);
@@ -6,21 +6,21 @@ import { Meta } from '@storybook/blocks';
6
6
 
7
7
  > **Status: alpha** — components and APIs may change before stable release.
8
8
 
9
- `@boostdev/components` ships native implementations for 47 components — near-complete parity with the React web library. These use React Native primitives (`View`, `Text`, `Pressable`, `StyleSheet`, `Modal`, `Animated`) rather than HTML elements, and consume a dedicated token layer instead of CSS custom properties.
9
+ `@boostdev/design-system-components` ships native implementations for 47 components — near-complete parity with the React web library. These use React Native primitives (`View`, `Text`, `Pressable`, `StyleSheet`, `Modal`, `Animated`) rather than HTML elements, and consume a dedicated token layer instead of CSS custom properties.
10
10
 
11
11
  ## Installation
12
12
 
13
13
  ```bash
14
- npm install @boostdev/components
14
+ npm install @boostdev/design-system-components
15
15
  # or
16
- pnpm add @boostdev/components
16
+ pnpm add @boostdev/design-system-components
17
17
  ```
18
18
 
19
19
  Metro automatically resolves the native entry point via the `"react-native"` export condition in `package.json` — no extra configuration needed.
20
20
 
21
21
  ```ts
22
22
  // Import is identical to the web version:
23
- import { Button, Alert, Badge, Avatar, Typography } from '@boostdev/components';
23
+ import { Button, Alert, Badge, Avatar, Typography } from '@boostdev/design-system-components';
24
24
  ```
25
25
 
26
26
  ## Setup — ThemeProvider
@@ -28,7 +28,7 @@ import { Button, Alert, Badge, Avatar, Typography } from '@boostdev/components';
28
28
  Wrap your app (or the relevant subtree) in `ThemeProvider` to give native components access to the design token context:
29
29
 
30
30
  ```tsx
31
- import { ThemeProvider } from '@boostdev/components/native/ThemeContext';
31
+ import { ThemeProvider } from '@boostdev/design-system-components/native/ThemeContext';
32
32
 
33
33
  export default function App() {
34
34
  return (
@@ -57,7 +57,7 @@ Native components consume tokens from `src/native/tokens.ts` — a JS object mir
57
57
  Tokens are accessed inside components via `useTheme()`:
58
58
 
59
59
  ```tsx
60
- import { useTheme } from '@boostdev/components/native/ThemeContext';
60
+ import { useTheme } from '@boostdev/design-system-components/native/ThemeContext';
61
61
 
62
62
  function MyComponent() {
63
63
  const { tokens } = useTheme();
@@ -36,7 +36,7 @@ const bdcCss = `
36
36
  initial-value: 0 0 0 0 transparent;
37
37
  }
38
38
 
39
- @layer component {
39
+ @layer boostdev.component {
40
40
  :root {
41
41
  --bdc-outline_border: none;
42
42
 
@@ -12,14 +12,14 @@ Framework-agnostic Accordion custom element. Coordinates open/closed state acros
12
12
  ## Installation
13
13
 
14
14
  ```js
15
- import '@boostdev/components/web-components';
15
+ import '@boostdev/design-system-components/web-components';
16
16
  ```
17
17
 
18
18
  Or in HTML without a bundler:
19
19
 
20
20
  ```html
21
21
  <script type="module">
22
- import '@boostdev/components/web-components';
22
+ import '@boostdev/design-system-components/web-components';
23
23
  </script>
24
24
  ```
25
25
 
@@ -85,7 +85,7 @@ Or in HTML without a bundler:
85
85
  </bds-accordion-item>
86
86
  <bds-accordion-item>
87
87
  <span slot="header">How do I install it?</span>
88
- <p>Run npm install @boostdev/components.</p>
88
+ <p>Run npm install @boostdev/design-system-components.</p>
89
89
  </bds-accordion-item>
90
90
  </bds-accordion>
91
91
 
@@ -49,7 +49,7 @@ function BdsAccordionStory({
49
49
  {React.createElement('p', { style: { margin: 0 } }, 'A framework-agnostic component library built on web standards.')}
50
50
  </BdsAccordionItem>
51
51
  <BdsAccordionItem header="How do I install it?">
52
- {React.createElement('p', { style: { margin: 0 } }, 'Run npm install @boostdev/components and import the web components entry point.')}
52
+ {React.createElement('p', { style: { margin: 0 } }, 'Run npm install @boostdev/design-system-components and import the web components entry point.')}
53
53
  </BdsAccordionItem>
54
54
  <BdsAccordionItem header="Does it support dark mode?">
55
55
  {React.createElement('p', { style: { margin: 0 } }, 'Yes — all design tokens respond to [data-theme="dark"] and prefers-color-scheme: dark.')}
@@ -1,4 +1,4 @@
1
- import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
1
+ import { Meta, Canvas, ArgTypes, Controls } from '@storybook/blocks';
2
2
  import * as Stories from './BdsButton.stories';
3
3
 
4
4
  <Meta of={Stories} />
@@ -13,37 +13,65 @@ Framework-agnostic button custom element. Renders as `<button>` or `<a>` dependi
13
13
 
14
14
  ```js
15
15
  // Register all web components at once
16
- import '@boostdev/components/web-components';
16
+ import '@boostdev/design-system-components/web-components';
17
17
  ```
18
18
 
19
19
  Or in HTML without a bundler:
20
20
 
21
21
  ```html
22
22
  <script type="module">
23
- import '@boostdev/components/web-components';
23
+ import '@boostdev/design-system-components/web-components';
24
24
  </script>
25
25
  ```
26
26
 
27
- ## Examples
27
+ ## Playground
28
28
 
29
- ### All variants & sizes
30
- <Canvas of={Stories.AllVariants} />
29
+ <Canvas of={Stories.Playground} />
30
+ <Controls of={Stories.Playground} />
31
+
32
+ ## Variants
31
33
 
32
- ### Default
33
34
  <Canvas of={Stories.Default} />
35
+ <Canvas of={Stories.Outline} />
34
36
 
35
- ### Ghost
36
- <Canvas of={Stories.Ghost} />
37
+ ## Sizes
37
38
 
38
- ### Sizes
39
39
  <Canvas of={Stories.Small} />
40
40
  <Canvas of={Stories.Medium} />
41
41
  <Canvas of={Stories.Large} />
42
42
 
43
- ### Pulse (CTA emphasis)
43
+ ## Icons
44
+
45
+ Slot an SVG (or any element) into `icon-start` or `icon-end`:
46
+
47
+ ```html
48
+ <bds-button>
49
+ <svg slot="icon-start">…</svg>
50
+ Save
51
+ </bds-button>
52
+ ```
53
+
54
+ <Canvas of={Stories.WithIconStart} />
55
+ <Canvas of={Stories.WithIconEnd} />
56
+
57
+ ### Icon-only (1:1 aspect ratio)
58
+
59
+ Set the `is-icon-only` attribute to render a square button with equal `var(--bds-space_xs)` padding on both axes. Composable with any `variant`. Always pair with `aria-label` — there's no visible label text for assistive tech to read.
60
+
61
+ <Canvas of={Stories.IconOnly} />
62
+ <Canvas of={Stories.IconOnlyOutline} />
63
+ <Canvas of={Stories.AllIconOnly} />
64
+
65
+ ## All variants & sizes
66
+
67
+ <Canvas of={Stories.AllVariants} />
68
+
69
+ ## Pulse (CTA emphasis)
70
+
44
71
  <Canvas of={Stories.WithPulse} />
45
72
 
46
- ### Disabled
73
+ ## Disabled
74
+
47
75
  <Canvas of={Stories.Disabled} />
48
76
 
49
77
  ## Props
@@ -54,14 +82,15 @@ Or in HTML without a bundler:
54
82
 
55
83
  | Attribute | Type | Default | Description |
56
84
  |-----------|------|---------|-------------|
57
- | `variant` | `"default" \| "ghost"` | `"default"` | Visual style — filled or transparent outlined |
58
- | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Height and padding scale |
85
+ | `variant` | `"default" \| "outline"` | `"default"` | Visual style — filled or transparent outlined (`"ghost"` is a deprecated alias for `"outline"`) |
86
+ | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Height and horizontal padding |
59
87
  | `disabled` | boolean | `false` | Prevents interaction, sets `aria-disabled` |
60
88
  | `href` | string | — | Renders as `<a>` when set |
61
89
  | `target` | string | — | Forwarded to `<a>` when `href` is set |
62
90
  | `rel` | string | — | Forwarded to `<a>` when `href` is set |
63
91
  | `type` | `"button" \| "submit" \| "reset"` | `"button"` | Native button type |
64
92
  | `has-pulse` | boolean | `false` | Adds animated ring for CTA emphasis |
93
+ | `is-icon-only` | boolean | `false` | 1:1 aspect ratio with equal `xs` padding on both axes. Requires `aria-label`. |
65
94
  | `aria-label` | string | — | Accessible label (required for icon-only buttons) |
66
95
 
67
96
  ## Slots
@@ -76,7 +105,7 @@ Or in HTML without a bundler:
76
105
 
77
106
  | Property | Description |
78
107
  |----------|-------------|
79
- | `--button_color` | Identity colour — fills the default variant, outlines the ghost variant |
108
+ | `--button_color` | Identity colour — fills the default variant, outlines the outline variant |
80
109
  | `--button_on-color` | Text/icon colour on the button surface. Pair with `--button_color` |
81
110
 
82
111
  ## Invoker Commands API
@@ -94,8 +123,11 @@ Or in HTML without a bundler:
94
123
 
95
124
  ```html
96
125
  <bds-button variant="default" size="medium">Save</bds-button>
97
- <bds-button variant="ghost">Cancel</bds-button>
126
+ <bds-button variant="outline">Cancel</bds-button>
98
127
  <bds-button href="/dashboard">Go to dashboard</bds-button>
128
+ <bds-button is-icon-only aria-label="Confirm">
129
+ <svg viewBox="0 0 24 24">…</svg>
130
+ </bds-button>
99
131
  ```
100
132
 
101
133
  ## Accessibility
@@ -1,56 +1,188 @@
1
- import React from 'react';
1
+ import React, { type ReactNode } from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
3
  import type { ButtonVariant, ButtonSize } from './bds-button';
4
4
  import '../index'; // auto-registers all custom elements
5
5
 
6
- // Thin React wrapper so Storybook controls work with the custom element's props
6
+ const CheckIcon = (
7
+ <svg
8
+ slot="icon-start"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ viewBox="0 0 24 24"
11
+ width="1em"
12
+ height="1em"
13
+ aria-hidden
14
+ fill="currentColor"
15
+ >
16
+ <path d="M12 0a12 12 0 1 0 12 12A12 12 0 0 0 12 0Zm6.93 8.2-6.85 9.29a1 1 0 0 1-1.43.19l-4.89-3.91a1 1 0 0 1-.15-1.41A1 1 0 0 1 7 12.21l4.08 3.26L17.32 7a1 1 0 0 1 1.39-.21 1 1 0 0 1 .22 1.41Z" />
17
+ </svg>
18
+ );
19
+
20
+ const ArrowRightStart = <span slot="icon-start" aria-hidden>→</span>;
21
+ const ArrowRightEnd = <span slot="icon-end" aria-hidden>→</span>;
22
+ const ArrowLeftStart = <span slot="icon-start" aria-hidden>←</span>;
23
+
24
+ // Icon for icon-only buttons — goes into the default slot (no slot attribute)
25
+ const CheckIconDefault = (
26
+ <svg
27
+ xmlns="http://www.w3.org/2000/svg"
28
+ viewBox="0 0 24 24"
29
+ width="1em"
30
+ height="1em"
31
+ aria-hidden
32
+ fill="currentColor"
33
+ >
34
+ <path d="M12 0a12 12 0 1 0 12 12A12 12 0 0 0 12 0Zm6.93 8.2-6.85 9.29a1 1 0 0 1-1.43.19l-4.89-3.91a1 1 0 0 1-.15-1.41A1 1 0 0 1 7 12.21l4.08 3.26L17.32 7a1 1 0 0 1 1.39-.21 1 1 0 0 1 .22 1.41Z" />
35
+ </svg>
36
+ );
37
+
38
+ const iconStartMap = {
39
+ none: undefined,
40
+ check: CheckIcon,
41
+ arrowRight: ArrowRightStart,
42
+ arrowLeft: ArrowLeftStart,
43
+ };
44
+
45
+ const iconEndMap = {
46
+ none: undefined,
47
+ arrowRight: ArrowRightEnd,
48
+ };
49
+
50
+ type IconStartKey = keyof typeof iconStartMap;
51
+ type IconEndKey = keyof typeof iconEndMap;
52
+
53
+ // React wrapper translating typed props into the custom element's attributes/slots
54
+ interface BdsButtonProps {
55
+ variant?: ButtonVariant;
56
+ size?: ButtonSize;
57
+ disabled?: boolean;
58
+ href?: string;
59
+ hasPulse?: boolean;
60
+ isIconOnly?: boolean;
61
+ 'aria-label'?: string;
62
+ iconStart?: ReactNode;
63
+ iconEnd?: ReactNode;
64
+ children?: ReactNode;
65
+ }
66
+
7
67
  function BdsButton({
8
68
  variant = 'default',
9
69
  size = 'medium',
10
70
  disabled,
11
71
  href,
12
72
  hasPulse,
73
+ isIconOnly,
74
+ 'aria-label': ariaLabel,
75
+ iconStart,
76
+ iconEnd,
13
77
  children,
14
- }: {
15
- variant?: ButtonVariant;
16
- size?: ButtonSize;
17
- disabled?: boolean;
18
- href?: string;
19
- hasPulse?: boolean;
20
- children?: React.ReactNode;
21
- }) {
78
+ }: BdsButtonProps) {
22
79
  return React.createElement(
23
80
  'bds-button',
24
- { variant, size, disabled: disabled || undefined, href, 'has-pulse': hasPulse || undefined },
81
+ {
82
+ variant,
83
+ size,
84
+ disabled: disabled || undefined,
85
+ href,
86
+ 'has-pulse': hasPulse || undefined,
87
+ 'is-icon-only': isIconOnly || undefined,
88
+ 'aria-label': ariaLabel,
89
+ },
90
+ iconStart,
25
91
  children,
92
+ iconEnd,
26
93
  );
27
94
  }
28
95
 
29
- const meta = {
96
+ type BdsButtonStoryArgs = Omit<BdsButtonProps, 'iconStart' | 'iconEnd'> & {
97
+ iconStart?: IconStartKey;
98
+ iconEnd?: IconEndKey;
99
+ };
100
+
101
+ const meta: Meta<BdsButtonStoryArgs> = {
30
102
  title: 'Web Components/Interaction/Button',
31
103
  component: BdsButton,
32
104
  tags: ['!stable', 'experimental'],
33
105
  parameters: { layout: 'centered' },
34
106
  argTypes: {
35
- variant: { control: 'select', options: ['default', 'ghost'] },
36
- size: { control: 'select', options: ['small', 'medium', 'large'] },
107
+ variant: {
108
+ control: 'select',
109
+ options: ['default', 'outline'],
110
+ description: '`default` is filled; `outline` is transparent with a border.',
111
+ table: { defaultValue: { summary: 'default' } },
112
+ },
113
+ size: {
114
+ control: 'select',
115
+ options: ['small', 'medium', 'large'],
116
+ description: 'Height + horizontal padding.',
117
+ table: { defaultValue: { summary: 'medium' } },
118
+ },
119
+ iconStart: {
120
+ control: 'select',
121
+ options: Object.keys(iconStartMap) as IconStartKey[],
122
+ mapping: iconStartMap,
123
+ description: 'Icon rendered in the `icon-start` slot.',
124
+ },
125
+ iconEnd: {
126
+ control: 'select',
127
+ options: Object.keys(iconEndMap) as IconEndKey[],
128
+ mapping: iconEndMap,
129
+ description: 'Icon rendered in the `icon-end` slot.',
130
+ },
131
+ isIconOnly: {
132
+ control: 'boolean',
133
+ description: 'Forces 1:1 aspect ratio with minimal xs padding. Composable with any `variant`. Requires `aria-label`.',
134
+ table: { defaultValue: { summary: 'false' } },
135
+ },
136
+ hasPulse: {
137
+ control: 'boolean',
138
+ description: 'Adds a pulsing animation for CTA emphasis.',
139
+ table: { defaultValue: { summary: 'false' } },
140
+ },
141
+ disabled: { control: 'boolean' },
142
+ href: { control: 'text', description: 'When set, renders as `<a>` with button styling.' },
143
+ 'aria-label': { control: 'text', description: 'Required for icon-only buttons.' },
37
144
  },
38
- } satisfies Meta<typeof BdsButton>;
145
+ args: { variant: 'default', size: 'medium' },
146
+ };
39
147
 
40
148
  export default meta;
41
- type Story = StoryObj<typeof meta>;
149
+ type Story = StoryObj<BdsButtonStoryArgs>;
42
150
 
43
- export const Default: Story = { args: { children: 'Default', variant: 'default' } };
44
- export const Ghost: Story = { args: { children: 'Ghost', variant: 'ghost' } };
151
+ export const Playground: Story = {
152
+ args: { children: 'Button', iconStart: 'none', iconEnd: 'none' },
153
+ };
154
+
155
+ export const Default: Story = { args: { children: 'Default' } };
156
+ export const Outline: Story = { args: { children: 'Outline', variant: 'outline' } };
45
157
  export const Small: Story = { args: { children: 'Small', size: 'small' } };
46
158
  export const Medium: Story = { args: { children: 'Medium', size: 'medium' } };
47
159
  export const Large: Story = { args: { children: 'Large', size: 'large' } };
48
160
  export const WithPulse: Story = { args: { children: 'Pulsing', hasPulse: true } };
49
161
  export const Disabled: Story = { args: { children: 'Disabled', disabled: true } };
162
+ export const WithIconStart: Story = { args: { children: 'Confirm', iconStart: 'check' } };
163
+ export const WithIconEnd: Story = { args: { children: 'Continue', iconEnd: 'arrowRight' } };
164
+
165
+ export const IconOnly: Story = {
166
+ args: {
167
+ isIconOnly: true,
168
+ 'aria-label': 'Confirm',
169
+ children: CheckIconDefault,
170
+ },
171
+ };
172
+
173
+ export const IconOnlyOutline: Story = {
174
+ args: {
175
+ variant: 'outline',
176
+ isIconOnly: true,
177
+ 'aria-label': 'Confirm',
178
+ children: CheckIconDefault,
179
+ },
180
+ };
181
+
50
182
  export const AllVariants: Story = {
51
183
  render: () => (
52
184
  <div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
53
- {(['default', 'ghost'] as const).flatMap(v =>
185
+ {(['default', 'outline'] as const).flatMap(v =>
54
186
  (['small', 'medium', 'large'] as const).map(s => (
55
187
  <BdsButton key={`${v}-${s}`} variant={v} size={s}>{v} {s}</BdsButton>
56
188
  )),
@@ -58,3 +190,23 @@ export const AllVariants: Story = {
58
190
  </div>
59
191
  ),
60
192
  };
193
+
194
+ export const AllIconOnly: Story = {
195
+ render: () => (
196
+ <div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
197
+ {(['default', 'outline'] as const).flatMap(v =>
198
+ (['small', 'medium', 'large'] as const).map(s => (
199
+ <BdsButton
200
+ key={`${v}-${s}`}
201
+ variant={v}
202
+ size={s}
203
+ isIconOnly
204
+ aria-label={`${v} ${s}`}
205
+ >
206
+ {CheckIconDefault}
207
+ </BdsButton>
208
+ )),
209
+ )}
210
+ </div>
211
+ ),
212
+ };
@@ -12,14 +12,14 @@ Framework-agnostic Collapsible custom element. Wraps a native `<details>`/`<summ
12
12
  ## Installation
13
13
 
14
14
  ```js
15
- import '@boostdev/components/web-components';
15
+ import '@boostdev/design-system-components/web-components';
16
16
  ```
17
17
 
18
18
  Or in HTML without a bundler:
19
19
 
20
20
  ```html
21
21
  <script type="module">
22
- import '@boostdev/components/web-components';
22
+ import '@boostdev/design-system-components/web-components';
23
23
  </script>
24
24
  ```
25
25
 
@@ -12,14 +12,14 @@ Framework-agnostic Dialog custom element. Wraps a native `<dialog>` element with
12
12
  ## Installation
13
13
 
14
14
  ```js
15
- import '@boostdev/components/web-components';
15
+ import '@boostdev/design-system-components/web-components';
16
16
  ```
17
17
 
18
18
  Or in HTML without a bundler:
19
19
 
20
20
  ```html
21
21
  <script type="module">
22
- import '@boostdev/components/web-components';
22
+ import '@boostdev/design-system-components/web-components';
23
23
  </script>
24
24
  ```
25
25
 
@@ -12,14 +12,14 @@ Framework-agnostic Drawer (slide-in panel) custom element. Same modal infrastruc
12
12
  ## Installation
13
13
 
14
14
  ```js
15
- import '@boostdev/components/web-components';
15
+ import '@boostdev/design-system-components/web-components';
16
16
  ```
17
17
 
18
18
  Or in HTML without a bundler:
19
19
 
20
20
  ```html
21
21
  <script type="module">
22
- import '@boostdev/components/web-components';
22
+ import '@boostdev/design-system-components/web-components';
23
23
  </script>
24
24
  ```
25
25
 
@@ -12,14 +12,14 @@ Framework-agnostic Dropdown Menu custom element. A trigger-anchored menu panel w
12
12
  ## Installation
13
13
 
14
14
  ```js
15
- import '@boostdev/components/web-components';
15
+ import '@boostdev/design-system-components/web-components';
16
16
  ```
17
17
 
18
18
  Or in HTML without a bundler:
19
19
 
20
20
  ```html
21
21
  <script type="module">
22
- import '@boostdev/components/web-components';
22
+ import '@boostdev/design-system-components/web-components';
23
23
  </script>
24
24
  ```
25
25
 
@@ -12,7 +12,7 @@ Framework-agnostic popover custom element. A non-modal floating panel anchored t
12
12
  ## Installation
13
13
 
14
14
  ```js
15
- import '@boostdev/components/web-components';
15
+ import '@boostdev/design-system-components/web-components';
16
16
  ```
17
17
 
18
18
  ## Examples