@boostdev/design-system-components 1.0.3 → 1.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.
- package/AGENTS.md +5 -5
- package/dist/client.cjs +236 -153
- package/dist/client.css +547 -483
- package/dist/client.d.cts +53 -94
- package/dist/client.d.ts +53 -94
- package/dist/client.js +237 -163
- package/dist/index.cjs +236 -153
- package/dist/index.css +547 -483
- package/dist/index.d.cts +53 -94
- package/dist/index.d.ts +53 -94
- package/dist/index.js +237 -163
- package/dist/native/index.cjs +991 -0
- package/dist/native/index.d.cts +208 -0
- package/dist/native/index.d.ts +208 -0
- package/dist/native/index.js +968 -0
- package/dist/web-components.d.ts +303 -0
- package/dist/web-components.js +1968 -0
- package/package.json +27 -5
- package/src/components/interaction/Button/Button.module.css +10 -7
- package/src/components/interaction/Button/Button.native.spec.tsx +35 -0
- package/src/components/interaction/Button/Button.native.stories.tsx +42 -0
- package/src/components/interaction/Button/Button.native.tsx +95 -0
- package/src/components/interaction/Button/Button.stories.tsx +1 -1
- package/src/components/interaction/Button/Button.tsx +2 -2
- package/src/components/interaction/Command/Command.mdx +16 -0
- package/src/components/interaction/Command/Command.stories.tsx +1 -1
- package/src/components/interaction/Command/Command.tsx +2 -2
- package/src/components/interaction/Dialog/Dialog.stories.tsx +1 -1
- package/src/components/interaction/Dialog/Dialog.tsx +2 -2
- package/src/components/interaction/Drawer/Drawer.mdx +14 -0
- package/src/components/interaction/Drawer/Drawer.stories.tsx +1 -1
- package/src/components/interaction/Drawer/Drawer.tsx +2 -2
- package/src/components/interaction/DropdownMenu/DropdownMenu.stories.tsx +1 -1
- package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +2 -2
- package/src/components/interaction/Popover/Popover.mdx +17 -0
- package/src/components/interaction/Popover/Popover.module.css +70 -13
- package/src/components/interaction/Popover/Popover.spec.tsx +68 -4
- package/src/components/interaction/Popover/Popover.stories.tsx +1 -1
- package/src/components/interaction/Popover/Popover.tsx +76 -20
- package/src/components/interaction/Rating/Rating.stories.tsx +1 -1
- package/src/components/interaction/Rating/Rating.tsx +2 -2
- package/src/components/interaction/Toast/Toast.module.css +6 -1
- package/src/components/interaction/Toast/Toast.spec.tsx +21 -0
- package/src/components/interaction/Toast/Toast.stories.tsx +1 -1
- package/src/components/interaction/Toast/Toast.tsx +22 -2
- package/src/components/interaction/form/Checkbox/Checkbox.mdx +2 -2
- package/src/components/interaction/form/Checkbox/Checkbox.module.css +3 -3
- package/src/components/interaction/form/Checkbox/Checkbox.native.spec.tsx +42 -0
- package/src/components/interaction/form/Checkbox/Checkbox.native.stories.tsx +36 -0
- package/src/components/interaction/form/Checkbox/Checkbox.native.tsx +80 -0
- package/src/components/interaction/form/Checkbox/Checkbox.stories.tsx +1 -1
- package/src/components/interaction/form/Checkbox/Checkbox.tsx +2 -2
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +44 -0
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.stories.tsx +1 -1
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +2 -2
- package/src/components/interaction/form/Combobox/Combobox.mdx +21 -0
- package/src/components/interaction/form/Combobox/Combobox.module.css +1 -1
- package/src/components/interaction/form/Combobox/Combobox.stories.tsx +1 -1
- package/src/components/interaction/form/Combobox/Combobox.tsx +2 -2
- package/src/components/interaction/form/FileInput/FileInput.mdx +14 -0
- package/src/components/interaction/form/FileInput/FileInput.module.css +1 -1
- package/src/components/interaction/form/FileInput/FileInput.stories.tsx +1 -1
- package/src/components/interaction/form/FileInput/FileInput.tsx +2 -2
- package/src/components/interaction/form/FormInput/FormInput.stories.tsx +1 -1
- package/src/components/interaction/form/FormInput/FormInput.tsx +2 -2
- package/src/components/interaction/form/NumberInput/NumberInput.mdx +16 -0
- package/src/components/interaction/form/NumberInput/NumberInput.stories.tsx +1 -1
- package/src/components/interaction/form/NumberInput/NumberInput.tsx +2 -2
- package/src/components/interaction/form/Radio/Radio.mdx +3 -3
- package/src/components/interaction/form/Radio/Radio.module.css +3 -3
- package/src/components/interaction/form/Radio/Radio.native.stories.tsx +46 -0
- package/src/components/interaction/form/Radio/Radio.native.tsx +79 -0
- package/src/components/interaction/form/Radio/Radio.stories.tsx +1 -1
- package/src/components/interaction/form/Radio/Radio.tsx +2 -2
- package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +45 -0
- package/src/components/interaction/form/RadioGroup/RadioGroup.stories.tsx +1 -1
- package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +2 -2
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.stories.tsx +1 -1
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +2 -2
- package/src/components/interaction/form/Select/Select.stories.tsx +1 -1
- package/src/components/interaction/form/Select/Select.tsx +2 -2
- package/src/components/interaction/form/Slider/Slider.mdx +1 -1
- package/src/components/interaction/form/Slider/Slider.module.css +4 -4
- package/src/components/interaction/form/Slider/Slider.stories.tsx +1 -1
- package/src/components/interaction/form/Slider/Slider.tsx +2 -2
- package/src/components/interaction/form/Switch/Switch.mdx +4 -4
- package/src/components/interaction/form/Switch/Switch.module.css +3 -3
- package/src/components/interaction/form/Switch/Switch.native.spec.tsx +60 -0
- package/src/components/interaction/form/Switch/Switch.native.stories.tsx +35 -0
- package/src/components/interaction/form/Switch/Switch.native.tsx +59 -0
- package/src/components/interaction/form/Switch/Switch.stories.tsx +1 -1
- package/src/components/interaction/form/Switch/Switch.tsx +2 -2
- package/src/components/interaction/form/Textarea/Textarea.mdx +17 -0
- package/src/components/interaction/form/Textarea/Textarea.stories.tsx +1 -1
- package/src/components/interaction/form/Textarea/Textarea.tsx +2 -2
- package/src/components/interaction/form/atoms/InputContainer.tsx +2 -1
- package/src/components/interaction/form/atoms/Label.native.stories.tsx +18 -0
- package/src/components/interaction/form/atoms/Label.native.tsx +29 -0
- package/src/components/interaction/form/atoms/Label.tsx +5 -3
- package/src/components/interaction/form/atoms/Message.native.spec.tsx +30 -0
- package/src/components/interaction/form/atoms/Message.native.stories.tsx +22 -0
- package/src/components/interaction/form/atoms/Message.native.tsx +34 -0
- package/src/components/interaction/form/atoms/Message.tsx +5 -3
- package/src/components/layout/ButtonGroup/ButtonGroup.native.stories.tsx +50 -0
- package/src/components/layout/ButtonGroup/ButtonGroup.native.tsx +34 -0
- package/src/components/layout/ButtonGroup/ButtonGroup.stories.tsx +1 -1
- package/src/components/layout/ButtonGroup/ButtonGroup.tsx +2 -2
- package/src/components/layout/Card/Card.native.stories.tsx +53 -0
- package/src/components/layout/Card/Card.native.tsx +89 -0
- package/src/components/layout/Card/Card.stories.tsx +1 -1
- package/src/components/layout/Card/Card.tsx +2 -2
- package/src/components/layout/IconWrapper/IconWrapper.mdx +2 -2
- package/src/components/layout/IconWrapper/IconWrapper.native.spec.tsx +39 -0
- package/src/components/layout/IconWrapper/IconWrapper.native.stories.tsx +41 -0
- package/src/components/layout/IconWrapper/IconWrapper.native.tsx +20 -0
- package/src/components/layout/IconWrapper/IconWrapper.stories.tsx +1 -1
- package/src/components/layout/IconWrapper/IconWrapper.tsx +2 -2
- package/src/components/layout/SectionHeader/SectionHeader.mdx +13 -0
- package/src/components/layout/SectionHeader/SectionHeader.native.stories.tsx +38 -0
- package/src/components/layout/SectionHeader/SectionHeader.native.tsx +79 -0
- package/src/components/layout/SectionHeader/SectionHeader.stories.tsx +1 -1
- package/src/components/layout/SectionHeader/SectionHeader.tsx +2 -2
- package/src/components/ui/Accordion/Accordion.mdx +14 -0
- package/src/components/ui/Accordion/Accordion.stories.tsx +1 -1
- package/src/components/ui/Accordion/Accordion.tsx +2 -2
- package/src/components/ui/Alert/Alert.native.stories.tsx +43 -0
- package/src/components/ui/Alert/Alert.native.tsx +94 -0
- package/src/components/ui/Alert/Alert.stories.tsx +1 -1
- package/src/components/ui/Alert/Alert.tsx +2 -2
- package/src/components/ui/Avatar/Avatar.native.spec.tsx +47 -0
- package/src/components/ui/Avatar/Avatar.native.stories.tsx +34 -0
- package/src/components/ui/Avatar/Avatar.native.tsx +85 -0
- package/src/components/ui/Avatar/Avatar.stories.tsx +1 -1
- package/src/components/ui/Avatar/Avatar.tsx +2 -2
- package/src/components/ui/Badge/Badge.mdx +2 -2
- package/src/components/ui/Badge/Badge.native.stories.tsx +36 -0
- package/src/components/ui/Badge/Badge.native.tsx +50 -0
- package/src/components/ui/Badge/Badge.stories.tsx +1 -1
- package/src/components/ui/Badge/Badge.tsx +2 -2
- package/src/components/ui/Breadcrumb/Breadcrumb.stories.tsx +1 -1
- package/src/components/ui/Breadcrumb/Breadcrumb.tsx +2 -2
- package/src/components/ui/Calendar/Calendar.mdx +16 -0
- package/src/components/ui/Calendar/Calendar.stories.tsx +1 -1
- package/src/components/ui/Calendar/Calendar.tsx +2 -2
- package/src/components/ui/Carousel/Carousel.stories.tsx +1 -1
- package/src/components/ui/Carousel/Carousel.tsx +2 -2
- package/src/components/ui/Collapsible/Collapsible.stories.tsx +1 -1
- package/src/components/ui/Collapsible/Collapsible.tsx +2 -2
- package/src/components/ui/DescriptionList/DescriptionList.stories.tsx +1 -1
- package/src/components/ui/DescriptionList/DescriptionList.tsx +2 -2
- package/src/components/ui/Link/Link.mdx +14 -0
- package/src/components/ui/Link/Link.stories.tsx +1 -1
- package/src/components/ui/Link/Link.tsx +2 -2
- package/src/components/ui/Loading/Loading.native.spec.tsx +24 -0
- package/src/components/ui/Loading/Loading.native.stories.tsx +33 -0
- package/src/components/ui/Loading/Loading.native.tsx +29 -0
- package/src/components/ui/Loading/Loading.stories.tsx +1 -1
- package/src/components/ui/Loading/Loading.tsx +2 -2
- package/src/components/ui/NotificationBanner/NotificationBanner.native.stories.tsx +39 -0
- package/src/components/ui/NotificationBanner/NotificationBanner.native.tsx +76 -0
- package/src/components/ui/NotificationBanner/NotificationBanner.stories.tsx +1 -1
- package/src/components/ui/NotificationBanner/NotificationBanner.tsx +2 -2
- package/src/components/ui/Pagination/Pagination.module.css +1 -1
- package/src/components/ui/Pagination/Pagination.stories.tsx +1 -1
- package/src/components/ui/Pagination/Pagination.tsx +2 -2
- package/src/components/ui/Progress/Progress.mdx +1 -1
- package/src/components/ui/Progress/Progress.module.css +1 -1
- package/src/components/ui/Progress/Progress.native.stories.tsx +34 -0
- package/src/components/ui/Progress/Progress.native.tsx +84 -0
- package/src/components/ui/Progress/Progress.stories.tsx +1 -1
- package/src/components/ui/Progress/Progress.tsx +2 -2
- package/src/components/ui/ProgressCircle/ProgressCircle.module.css +1 -1
- package/src/components/ui/ProgressCircle/ProgressCircle.stories.tsx +1 -1
- package/src/components/ui/ProgressCircle/ProgressCircle.tsx +2 -2
- package/src/components/ui/Separator/Separator.mdx +14 -0
- package/src/components/ui/Separator/Separator.native.stories.tsx +42 -0
- package/src/components/ui/Separator/Separator.native.tsx +32 -0
- package/src/components/ui/Separator/Separator.stories.tsx +1 -1
- package/src/components/ui/Separator/Separator.tsx +2 -2
- package/src/components/ui/Skeleton/Skeleton.native.stories.tsx +33 -0
- package/src/components/ui/Skeleton/Skeleton.native.tsx +41 -0
- package/src/components/ui/Skeleton/Skeleton.stories.tsx +1 -1
- package/src/components/ui/Skeleton/Skeleton.tsx +2 -3
- package/src/components/ui/SkipLink/SkipLink.stories.tsx +1 -1
- package/src/components/ui/SkipLink/SkipLink.tsx +5 -3
- package/src/components/ui/Table/Table.mdx +14 -0
- package/src/components/ui/Table/Table.stories.tsx +1 -1
- package/src/components/ui/Table/Table.tsx +2 -2
- package/src/components/ui/Tabs/Tabs.stories.tsx +1 -1
- package/src/components/ui/Tabs/Tabs.tsx +2 -2
- package/src/components/ui/Tooltip/Tooltip.mdx +14 -0
- package/src/components/ui/Tooltip/Tooltip.stories.tsx +1 -1
- package/src/components/ui/Tooltip/Tooltip.tsx +2 -2
- package/src/components/ui/Typography/Typography.mdx +13 -0
- package/src/components/ui/Typography/Typography.native.stories.tsx +38 -0
- package/src/components/ui/Typography/Typography.native.tsx +65 -0
- package/src/components/ui/Typography/Typography.stories.tsx +1 -1
- package/src/components/ui/Typography/Typography.tsx +2 -2
- package/src/css/bdc.css +8 -0
- package/src/index.ts +1 -0
- package/src/native/ThemeContext.tsx +28 -0
- package/src/native/tokens.ts +13 -0
- package/src/native.ts +39 -0
- package/src/react-augment.d.ts +13 -0
- package/src/stories/DesignSystem/DarkMode.mdx +130 -0
- package/src/types.ts +2 -0
- package/src/typings.d.ts +3 -0
- package/src/web-components/globals.ts +61 -0
- package/src/web-components/index.ts +12 -0
- package/src/web-components/interaction/BdsButton.stories.tsx +60 -0
- package/src/web-components/interaction/BdsPopover.stories.tsx +70 -0
- package/src/web-components/interaction/BdsToastProvider.stories.tsx +73 -0
- package/src/web-components/interaction/bds-button.spec.ts +95 -0
- package/src/web-components/interaction/bds-button.ts +293 -0
- package/src/web-components/interaction/bds-popover.spec.ts +126 -0
- package/src/web-components/interaction/bds-popover.ts +217 -0
- package/src/web-components/interaction/bds-toast-provider.spec.ts +122 -0
- package/src/web-components/interaction/bds-toast-provider.ts +211 -0
- package/src/web-components/test/helpers.ts +14 -0
- package/src/web-components/ui/BdsAlert.stories.tsx +60 -0
- package/src/web-components/ui/BdsBadge.stories.tsx +37 -0
- package/src/web-components/ui/bds-alert.spec.ts +109 -0
- package/src/web-components/ui/bds-alert.ts +209 -0
- package/src/web-components/ui/bds-badge.spec.ts +51 -0
- package/src/web-components/ui/bds-badge.ts +88 -0
|
@@ -2,15 +2,15 @@ import { ReactNode, useId } from 'react';
|
|
|
2
2
|
import css from './CheckboxGroup.module.css';
|
|
3
3
|
import { Message } from '../atoms/Message';
|
|
4
4
|
import { cn } from '@boostdev/design-system-foundation';
|
|
5
|
+
import type { WithClassName } from '../../../../types';
|
|
5
6
|
|
|
6
|
-
export interface CheckboxGroupProps {
|
|
7
|
+
export interface CheckboxGroupProps extends WithClassName {
|
|
7
8
|
legend: string;
|
|
8
9
|
children: ReactNode;
|
|
9
10
|
error?: string;
|
|
10
11
|
hint?: string;
|
|
11
12
|
required?: boolean;
|
|
12
13
|
disabled?: boolean;
|
|
13
|
-
className?: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function CheckboxGroup({
|
|
@@ -29,6 +29,27 @@ Searchable select with type-ahead filtering. Combines a text input with a dropdo
|
|
|
29
29
|
|
|
30
30
|
<ArgTypes of={Stories} />
|
|
31
31
|
|
|
32
|
+
## CSS variables
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
<table>
|
|
36
|
+
<thead>
|
|
37
|
+
<tr><th>Variable</th><th>Default</th><th>Description</th></tr>
|
|
38
|
+
</thead>
|
|
39
|
+
<tbody>
|
|
40
|
+
<tr><td>`--combobox_color_bg`</td><td>`var(--bds-color_bg)`</td><td>Input background colour</td></tr>
|
|
41
|
+
<tr><td>`--combobox_color`</td><td>`var(--bds-color_on-bg)`</td><td>Input text colour</td></tr>
|
|
42
|
+
<tr><td>`--combobox_border`</td><td>`none`</td><td>Input border</td></tr>
|
|
43
|
+
<tr><td>`--combobox_radius`</td><td>`var(--bdc-outline_radius)`</td><td>Input corner radius</td></tr>
|
|
44
|
+
<tr><td>`--combobox_shadow`</td><td>`var(--bdc-outline_shadow)`</td><td>Input box shadow</td></tr>
|
|
45
|
+
<tr><td>`--combobox_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Dropdown list text colour</td></tr>
|
|
46
|
+
<tr><td>`--combobox_listbox-border`</td><td>`none`</td><td>Dropdown list border</td></tr>
|
|
47
|
+
<tr><td>`--combobox_listbox-radius`</td><td>`var(--bdc-outline_radius)`</td><td>Dropdown list corner radius</td></tr>
|
|
48
|
+
<tr><td>`--combobox_listbox-shadow`</td><td>`var(--bds-shadow_m)`</td><td>Dropdown list box shadow</td></tr>
|
|
49
|
+
</tbody>
|
|
50
|
+
</table>
|
|
51
|
+
|
|
52
|
+
|
|
32
53
|
## Accessibility
|
|
33
54
|
|
|
34
55
|
- Input uses `role="combobox"` with `aria-autocomplete="list"` and `aria-controls`
|
|
@@ -13,6 +13,7 @@ import { cn } from '@boostdev/design-system-foundation';
|
|
|
13
13
|
import { InputContainer } from '../atoms/InputContainer';
|
|
14
14
|
import { Label } from '../atoms/Label';
|
|
15
15
|
import { Message } from '../atoms/Message';
|
|
16
|
+
import type { WithClassName } from '../../../../types';
|
|
16
17
|
|
|
17
18
|
export interface ComboboxOption {
|
|
18
19
|
value: string;
|
|
@@ -20,7 +21,7 @@ export interface ComboboxOption {
|
|
|
20
21
|
disabled?: boolean;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
interface ComboboxProps {
|
|
24
|
+
interface ComboboxProps extends WithClassName {
|
|
24
25
|
label: ReactNode;
|
|
25
26
|
name: string;
|
|
26
27
|
options: ComboboxOption[];
|
|
@@ -30,7 +31,6 @@ interface ComboboxProps {
|
|
|
30
31
|
disabled?: boolean;
|
|
31
32
|
error?: string;
|
|
32
33
|
hint?: string;
|
|
33
|
-
className?: string;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export function Combobox({
|
|
@@ -31,6 +31,20 @@ File upload input with styled trigger button, hint, and error support.
|
|
|
31
31
|
|
|
32
32
|
<ArgTypes of={Stories} />
|
|
33
33
|
|
|
34
|
+
## CSS variables
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
<table>
|
|
38
|
+
<thead>
|
|
39
|
+
<tr><th>Variable</th><th>Default</th><th>Description</th></tr>
|
|
40
|
+
</thead>
|
|
41
|
+
<tbody>
|
|
42
|
+
<tr><td>`--fileInput_color`</td><td>`var(--bds-color_on-bg)`</td><td>Text colour</td></tr>
|
|
43
|
+
<tr><td>`--fileInput_border-color`</td><td>`currentcolor`</td><td>Drop zone border colour</td></tr>
|
|
44
|
+
</tbody>
|
|
45
|
+
</table>
|
|
46
|
+
|
|
47
|
+
|
|
34
48
|
## Accessibility
|
|
35
49
|
|
|
36
50
|
- Native `<input type="file">` — opens the OS file picker
|
|
@@ -3,8 +3,9 @@ import css from './FileInput.module.css';
|
|
|
3
3
|
import { Message } from '../atoms/Message';
|
|
4
4
|
import { InputContainer } from '../atoms/InputContainer';
|
|
5
5
|
import { cn } from '@boostdev/design-system-foundation';
|
|
6
|
+
import type { WithClassName } from '../../../../types';
|
|
6
7
|
|
|
7
|
-
interface FileInputProps {
|
|
8
|
+
interface FileInputProps extends WithClassName {
|
|
8
9
|
label: string;
|
|
9
10
|
name: string;
|
|
10
11
|
accept?: string;
|
|
@@ -14,7 +15,6 @@ interface FileInputProps {
|
|
|
14
15
|
error?: string;
|
|
15
16
|
hint?: string;
|
|
16
17
|
onChange?: (files: FileList | null) => void;
|
|
17
|
-
className?: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export function FileInput({
|
|
@@ -4,15 +4,15 @@ import { Label } from '../atoms/Label';
|
|
|
4
4
|
import { Message } from '../atoms/Message';
|
|
5
5
|
import { cn } from '@boostdev/design-system-foundation';
|
|
6
6
|
import { InputContainer } from '../atoms/InputContainer';
|
|
7
|
+
import type { WithClassName } from '../../../../types';
|
|
7
8
|
|
|
8
|
-
interface FormInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
9
|
+
interface FormInputProps extends WithClassName, Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
9
10
|
label: ReactNode;
|
|
10
11
|
name: string;
|
|
11
12
|
type?: Exclude<HTMLInputTypeAttribute, 'checkbox' | 'radio' | 'file'>;
|
|
12
13
|
ariaLabel?: string;
|
|
13
14
|
error?: string;
|
|
14
15
|
hint?: string;
|
|
15
|
-
className?: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export function FormInput({
|
|
@@ -31,6 +31,22 @@ Numeric text input with increment/decrement stepper buttons. Enforces `min`, `ma
|
|
|
31
31
|
|
|
32
32
|
<ArgTypes of={Stories} />
|
|
33
33
|
|
|
34
|
+
## CSS variables
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
<table>
|
|
38
|
+
<thead>
|
|
39
|
+
<tr><th>Variable</th><th>Default</th><th>Description</th></tr>
|
|
40
|
+
</thead>
|
|
41
|
+
<tbody>
|
|
42
|
+
<tr><td>`--numberInput_color`</td><td>`var(--bds-color_on-bg)`</td><td>Text colour</td></tr>
|
|
43
|
+
<tr><td>`--numberInput_border`</td><td>`none`</td><td>Border</td></tr>
|
|
44
|
+
<tr><td>`--numberInput_radius`</td><td>`var(--bdc-outline_radius)`</td><td>Corner radius</td></tr>
|
|
45
|
+
<tr><td>`--numberInput_shadow`</td><td>`var(--bdc-outline_shadow)`</td><td>Box shadow</td></tr>
|
|
46
|
+
</tbody>
|
|
47
|
+
</table>
|
|
48
|
+
|
|
49
|
+
|
|
34
50
|
## Accessibility
|
|
35
51
|
|
|
36
52
|
- Renders `<input type="number">` — browser-native spinner support
|
|
@@ -4,8 +4,9 @@ import {Label} from '../atoms/Label';
|
|
|
4
4
|
import {Message} from '../atoms/Message';
|
|
5
5
|
import {InputContainer} from '../atoms/InputContainer';
|
|
6
6
|
import {cn} from '@boostdev/design-system-foundation';
|
|
7
|
+
import type { WithClassName } from '../../../../types';
|
|
7
8
|
|
|
8
|
-
interface NumberInputProps {
|
|
9
|
+
interface NumberInputProps extends WithClassName {
|
|
9
10
|
label: string;
|
|
10
11
|
name: string;
|
|
11
12
|
value?: number;
|
|
@@ -17,7 +18,6 @@ interface NumberInputProps {
|
|
|
17
18
|
error?: string;
|
|
18
19
|
hint?: string;
|
|
19
20
|
onChange?: (value: number) => void;
|
|
20
|
-
className?: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function NumberInput({
|
|
@@ -46,9 +46,9 @@ Single-select option within a group. Renders a styled native `<input type="radio
|
|
|
46
46
|
<tr><th>Variable</th><th>Default</th><th>Description</th></tr>
|
|
47
47
|
</thead>
|
|
48
48
|
<tbody>
|
|
49
|
-
<tr><td>`--radio_color-active`</td><td>`var(--
|
|
50
|
-
<tr><td>`--radio_color-on-active`</td><td>`var(--
|
|
51
|
-
<tr><td>`--radio_description-color`</td><td>`var(--bds-
|
|
49
|
+
<tr><td>`--radio_color-active`</td><td>`var(--bdc-color_active)`</td><td>Selected fill and border colour</td></tr>
|
|
50
|
+
<tr><td>`--radio_color-on-active`</td><td>`var(--bdc-color_on-active)`</td><td>Inner dot colour</td></tr>
|
|
51
|
+
<tr><td>`--radio_description-color`</td><td>`var(--bds-color_on-bg--subtle)`</td><td>Description text colour</td></tr>
|
|
52
52
|
</tbody>
|
|
53
53
|
</table>
|
|
54
54
|
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
.radio:checked {
|
|
51
|
-
background-color: var(--radio_color-active, var(--
|
|
52
|
-
--bdc_color: var(--radio_color-active, var(--
|
|
51
|
+
background-color: var(--radio_color-active, var(--bdc-color_active));
|
|
52
|
+
--bdc_color: var(--radio_color-active, var(--bdc-color_active));
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
.radio:checked::after {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
width: 0.4em;
|
|
62
62
|
height: 0.4em;
|
|
63
63
|
border-radius: 50%;
|
|
64
|
-
background-color: var(--radio_color-on-active, var(--
|
|
64
|
+
background-color: var(--radio_color-on-active, var(--bdc-color_on-active));
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
.radio:focus {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { ThemeProvider } from '../../../../native/ThemeContext';
|
|
4
|
+
import { Radio } from './Radio.native';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
tags: ['!stable', 'alpha'],
|
|
8
|
+
title: 'React Native/Form/Radio',
|
|
9
|
+
component: Radio,
|
|
10
|
+
decorators: [(Story) => <ThemeProvider><Story /></ThemeProvider>],
|
|
11
|
+
parameters: { layout: 'padded' },
|
|
12
|
+
} satisfies Meta<typeof Radio>;
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof meta>;
|
|
16
|
+
|
|
17
|
+
export const Unchecked: Story = { args: { label: 'Option A', name: 'option', checked: false } };
|
|
18
|
+
export const Checked: Story = { args: { label: 'Option A', name: 'option', checked: true } };
|
|
19
|
+
export const Disabled: Story = { args: { label: 'Option A', name: 'option', disabled: true } };
|
|
20
|
+
export const WithError: Story = {
|
|
21
|
+
args: { label: 'Option A', name: 'option', error: 'Please select an option.' },
|
|
22
|
+
};
|
|
23
|
+
export const WithHint: Story = {
|
|
24
|
+
args: { label: 'Option A', name: 'option', hint: 'This is the recommended option.' },
|
|
25
|
+
};
|
|
26
|
+
export const Group: Story = {
|
|
27
|
+
render: () => {
|
|
28
|
+
const [selected, setSelected] = useState<string | null>(null);
|
|
29
|
+
const options = ['Option A', 'Option B', 'Option C'];
|
|
30
|
+
return (
|
|
31
|
+
<ThemeProvider>
|
|
32
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
|
|
33
|
+
{options.map(o => (
|
|
34
|
+
<Radio
|
|
35
|
+
key={o}
|
|
36
|
+
label={o}
|
|
37
|
+
name="group"
|
|
38
|
+
checked={selected === o}
|
|
39
|
+
onChange={() => setSelected(o)}
|
|
40
|
+
/>
|
|
41
|
+
))}
|
|
42
|
+
</div>
|
|
43
|
+
</ThemeProvider>
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StyleSheet, View, Pressable, StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
import { spacing } from '../../../../native/tokens';
|
|
4
|
+
import { useTheme } from '../../../../native/ThemeContext';
|
|
5
|
+
import { Label } from '../atoms/Label.native';
|
|
6
|
+
import { Message } from '../atoms/Message.native';
|
|
7
|
+
|
|
8
|
+
interface RadioProps {
|
|
9
|
+
label: ReactNode;
|
|
10
|
+
name: string;
|
|
11
|
+
checked?: boolean;
|
|
12
|
+
onChange?: () => void;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
error?: string;
|
|
15
|
+
hint?: string;
|
|
16
|
+
style?: StyleProp<ViewStyle>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const DOT = 22;
|
|
20
|
+
const INNER = 10;
|
|
21
|
+
|
|
22
|
+
const styles = StyleSheet.create({
|
|
23
|
+
container: {
|
|
24
|
+
gap: spacing.xxs,
|
|
25
|
+
},
|
|
26
|
+
row: {
|
|
27
|
+
flexDirection: 'row',
|
|
28
|
+
alignItems: 'center',
|
|
29
|
+
gap: spacing.xs,
|
|
30
|
+
minHeight: 44,
|
|
31
|
+
},
|
|
32
|
+
outer: {
|
|
33
|
+
width: DOT,
|
|
34
|
+
height: DOT,
|
|
35
|
+
borderRadius: DOT / 2,
|
|
36
|
+
borderWidth: 2,
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
justifyContent: 'center',
|
|
39
|
+
},
|
|
40
|
+
inner: {
|
|
41
|
+
width: INNER,
|
|
42
|
+
height: INNER,
|
|
43
|
+
borderRadius: INNER / 2,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export function Radio({
|
|
48
|
+
label,
|
|
49
|
+
name,
|
|
50
|
+
checked = false,
|
|
51
|
+
onChange,
|
|
52
|
+
disabled = false,
|
|
53
|
+
error,
|
|
54
|
+
hint,
|
|
55
|
+
style,
|
|
56
|
+
}: RadioProps) {
|
|
57
|
+
const { colors } = useTheme();
|
|
58
|
+
const borderColor = error ? colors.colorError : checked ? colors.colorInteractive : colors.colorBgSubtle;
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<View style={[styles.container, style]}>
|
|
62
|
+
<Pressable
|
|
63
|
+
onPress={() => !disabled && onChange?.()}
|
|
64
|
+
accessibilityRole="radio"
|
|
65
|
+
accessibilityLabel={typeof label === 'string' ? label : name}
|
|
66
|
+
accessibilityState={{ checked, disabled }}
|
|
67
|
+
disabled={disabled}
|
|
68
|
+
style={({ pressed }) => [styles.row, pressed && { opacity: 0.7 }, disabled && { opacity: 0.4 }]}
|
|
69
|
+
>
|
|
70
|
+
<View style={[styles.outer, { borderColor }]}>
|
|
71
|
+
{checked && <View style={[styles.inner, { backgroundColor: colors.colorInteractive }]} />}
|
|
72
|
+
</View>
|
|
73
|
+
<Label label={label} />
|
|
74
|
+
</Pressable>
|
|
75
|
+
<Message type="error" message={error} />
|
|
76
|
+
<Message type="hint" message={hint} />
|
|
77
|
+
</View>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -4,14 +4,14 @@ import { Message } from '../atoms/Message';
|
|
|
4
4
|
import { Label } from '../atoms/Label';
|
|
5
5
|
import { InputContainer } from '../atoms/InputContainer';
|
|
6
6
|
import { cn } from '@boostdev/design-system-foundation';
|
|
7
|
+
import type { WithClassName } from '../../../../types';
|
|
7
8
|
|
|
8
|
-
interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
9
|
+
interface RadioProps extends WithClassName, Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
9
10
|
label: ReactNode;
|
|
10
11
|
name: string;
|
|
11
12
|
description?: string;
|
|
12
13
|
error?: string;
|
|
13
14
|
hint?: string;
|
|
14
|
-
className?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function Radio({ label, name, description, error, hint, className, ...props }: RadioProps) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './RadioGroup.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# RadioGroup
|
|
7
|
+
|
|
8
|
+
Groups multiple `Radio` inputs under a shared label. Renders a `<fieldset>` with a `<legend>` for accessible grouping.
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
- Mutually exclusive choices where exactly one option must be selected
|
|
12
|
+
- Any time two or more radio buttons share a common question or label
|
|
13
|
+
|
|
14
|
+
## When not to use
|
|
15
|
+
- More than 6 options — use `Select` or `Combobox` to avoid overwhelming the user
|
|
16
|
+
- Independent on/off choices — use `CheckboxGroup`
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### Default
|
|
21
|
+
<Canvas of={Stories.Default} />
|
|
22
|
+
|
|
23
|
+
### With error
|
|
24
|
+
<Canvas of={Stories.WithError} />
|
|
25
|
+
|
|
26
|
+
### With hint
|
|
27
|
+
<Canvas of={Stories.WithHint} />
|
|
28
|
+
|
|
29
|
+
### Required
|
|
30
|
+
<Canvas of={Stories.Required} />
|
|
31
|
+
|
|
32
|
+
### Disabled
|
|
33
|
+
<Canvas of={Stories.Disabled} />
|
|
34
|
+
|
|
35
|
+
## Props
|
|
36
|
+
|
|
37
|
+
<ArgTypes of={Stories} />
|
|
38
|
+
|
|
39
|
+
## Accessibility
|
|
40
|
+
|
|
41
|
+
- Wraps radio buttons in a `<fieldset>` with a `<legend>` — screen readers announce the group label before each option
|
|
42
|
+
- `disabled` on the group sets the HTML `disabled` attribute on the `<fieldset>`, which disables all child inputs
|
|
43
|
+
- `aria-required` is set on the `<fieldset>` when `required` is true
|
|
44
|
+
- Error and hint messages are linked via `aria-describedby`
|
|
45
|
+
- Arrow keys move between options within the group; `Tab` moves focus out of the group
|
|
@@ -2,15 +2,15 @@ import { ReactNode, useId } from 'react';
|
|
|
2
2
|
import css from './RadioGroup.module.css';
|
|
3
3
|
import { Message } from '../atoms/Message';
|
|
4
4
|
import { cn } from '@boostdev/design-system-foundation';
|
|
5
|
+
import type { WithClassName } from '../../../../types';
|
|
5
6
|
|
|
6
|
-
export interface RadioGroupProps {
|
|
7
|
+
export interface RadioGroupProps extends WithClassName {
|
|
7
8
|
legend: string;
|
|
8
9
|
children: ReactNode;
|
|
9
10
|
error?: string;
|
|
10
11
|
hint?: string;
|
|
11
12
|
required?: boolean;
|
|
12
13
|
disabled?: boolean;
|
|
13
|
-
className?: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function RadioGroup({
|
|
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
|
|
3
3
|
import { SegmentedControl } from './SegmentedControl';
|
|
4
4
|
|
|
5
5
|
const meta = {
|
|
6
|
-
title: 'Form/SegmentedControl',
|
|
6
|
+
title: 'React/Form/SegmentedControl',
|
|
7
7
|
component: SegmentedControl,
|
|
8
8
|
argTypes: {
|
|
9
9
|
size: { control: 'radio', options: ['small', 'medium', 'large'] },
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { InputHTMLAttributes, ReactNode, useId, useState } from 'react';
|
|
2
2
|
import css from './SegmentedControl.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
|
+
import type { WithClassName } from '../../../../types';
|
|
4
5
|
|
|
5
6
|
export interface SegmentedControlOption {
|
|
6
7
|
value: string;
|
|
@@ -9,7 +10,7 @@ export interface SegmentedControlOption {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export interface SegmentedControlProps
|
|
12
|
-
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value' | 'size'> {
|
|
13
|
+
extends WithClassName, Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value' | 'size'> {
|
|
13
14
|
name: string;
|
|
14
15
|
options: SegmentedControlOption[];
|
|
15
16
|
/** Controlled selected value */
|
|
@@ -19,7 +20,6 @@ export interface SegmentedControlProps
|
|
|
19
20
|
onChange?: (value: string) => void;
|
|
20
21
|
disabled?: boolean;
|
|
21
22
|
size?: 'small' | 'medium' | 'large';
|
|
22
|
-
className?: string;
|
|
23
23
|
'aria-label'?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -4,6 +4,7 @@ import { cn } from '@boostdev/design-system-foundation';
|
|
|
4
4
|
import { InputContainer } from '../atoms/InputContainer';
|
|
5
5
|
import { Label } from '../atoms/Label';
|
|
6
6
|
import { Message } from '../atoms/Message';
|
|
7
|
+
import type { WithClassName } from '../../../../types';
|
|
7
8
|
|
|
8
9
|
export interface SelectOption {
|
|
9
10
|
value: string;
|
|
@@ -11,14 +12,13 @@ export interface SelectOption {
|
|
|
11
12
|
disabled?: boolean;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'children'> {
|
|
15
|
+
interface SelectProps extends WithClassName, Omit<SelectHTMLAttributes<HTMLSelectElement>, 'children'> {
|
|
15
16
|
label: ReactNode;
|
|
16
17
|
name: string;
|
|
17
18
|
options: SelectOption[];
|
|
18
19
|
placeholder?: string;
|
|
19
20
|
error?: string;
|
|
20
21
|
hint?: string;
|
|
21
|
-
className?: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function Select({
|
|
@@ -46,7 +46,7 @@ Range input for selecting a numeric value within a bounded range.
|
|
|
46
46
|
<tr><th>Variable</th><th>Default</th><th>Description</th></tr>
|
|
47
47
|
</thead>
|
|
48
48
|
<tbody>
|
|
49
|
-
<tr><td>`--slider_color-active`</td><td>`var(--
|
|
49
|
+
<tr><td>`--slider_color-active`</td><td>`var(--bdc-color_active)`</td><td>Filled track and thumb colour</td></tr>
|
|
50
50
|
</tbody>
|
|
51
51
|
</table>
|
|
52
52
|
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
border-radius: 999px;
|
|
30
30
|
background: linear-gradient(
|
|
31
31
|
to right,
|
|
32
|
-
var(--slider_color-active, var(--
|
|
33
|
-
var(--slider_color-active, var(--
|
|
32
|
+
var(--slider_color-active, var(--bdc-color_active)) 0%,
|
|
33
|
+
var(--slider_color-active, var(--bdc-color_active)) var(--slider_fill),
|
|
34
34
|
var(--bds-color_bg--subtle) var(--slider_fill),
|
|
35
35
|
var(--bds-color_bg--subtle) 100%
|
|
36
36
|
);
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
width: var(--slider_thumb-size);
|
|
56
56
|
height: var(--slider_thumb-size);
|
|
57
57
|
border-radius: 50%;
|
|
58
|
-
background-color: var(--slider_color-active, var(--
|
|
58
|
+
background-color: var(--slider_color-active, var(--bdc-color_active));
|
|
59
59
|
box-shadow: var(--bds-shadow_s);
|
|
60
60
|
transition: var(--bds-animation_transition);
|
|
61
61
|
cursor: pointer;
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
height: var(--slider_thumb-size);
|
|
68
68
|
border: none;
|
|
69
69
|
border-radius: 50%;
|
|
70
|
-
background-color: var(--slider_color-active, var(--
|
|
70
|
+
background-color: var(--slider_color-active, var(--bdc-color_active));
|
|
71
71
|
box-shadow: var(--bds-shadow_s);
|
|
72
72
|
cursor: pointer;
|
|
73
73
|
}
|
|
@@ -4,8 +4,9 @@ import { cn } from '@boostdev/design-system-foundation';
|
|
|
4
4
|
import { InputContainer } from '../atoms/InputContainer';
|
|
5
5
|
import { Label } from '../atoms/Label';
|
|
6
6
|
import { Message } from '../atoms/Message';
|
|
7
|
+
import type { WithClassName } from '../../../../types';
|
|
7
8
|
|
|
8
|
-
interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
9
|
+
interface SliderProps extends WithClassName, Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
9
10
|
label: string;
|
|
10
11
|
name: string;
|
|
11
12
|
min?: number;
|
|
@@ -13,7 +14,6 @@ interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'
|
|
|
13
14
|
showValue?: boolean;
|
|
14
15
|
error?: string;
|
|
15
16
|
hint?: string;
|
|
16
|
-
className?: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function Slider({
|