@boostdev/design-system-components 1.2.1 → 1.2.3
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 +26 -0
- package/README.md +36 -19
- package/dist/client.cjs +141 -120
- package/dist/client.css +506 -503
- package/dist/client.d.cts +71 -96
- package/dist/client.d.ts +71 -96
- package/dist/client.js +141 -120
- package/dist/index.cjs +141 -120
- package/dist/index.css +506 -503
- package/dist/index.d.cts +71 -96
- package/dist/index.d.ts +71 -96
- package/dist/index.js +141 -120
- package/package.json +3 -3
- package/src/components/interaction/Button/Button.module.css +1 -4
- package/src/components/interaction/Command/Command.tsx +4 -3
- package/src/components/interaction/Dialog/Dialog.module.css +1 -1
- package/src/components/interaction/Dialog/Dialog.tsx +4 -5
- package/src/components/interaction/Drawer/Drawer.module.css +1 -1
- package/src/components/interaction/Drawer/Drawer.spec.tsx +3 -3
- package/src/components/interaction/Drawer/Drawer.tsx +4 -7
- package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +4 -0
- package/src/components/interaction/DropdownMenu/DropdownMenu.stories.tsx +4 -4
- package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +4 -2
- package/src/components/interaction/Popover/Popover.tsx +4 -3
- package/src/components/interaction/Rating/Rating.tsx +4 -2
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +4 -6
- package/src/components/interaction/form/Combobox/Combobox.module.css +1 -1
- package/src/components/interaction/form/Combobox/Combobox.tsx +4 -2
- package/src/components/interaction/form/FileInput/FileInput.tsx +4 -3
- package/src/components/interaction/form/FormInput/FormInput.module.css +1 -1
- package/src/components/interaction/form/NumberInput/NumberInput.module.css +1 -1
- package/src/components/interaction/form/NumberInput/NumberInput.tsx +4 -3
- package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +4 -6
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +5 -5
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +4 -6
- package/src/components/interaction/form/Select/Select.module.css +1 -1
- package/src/components/interaction/form/Slider/Slider.module.css +4 -4
- package/src/components/interaction/form/Switch/Switch.module.css +3 -3
- package/src/components/interaction/form/atoms/InputContainer.tsx +2 -2
- package/src/components/layout/ButtonGroup/ButtonGroup.tsx +4 -6
- package/src/components/layout/Card/Card.tsx +4 -10
- package/src/components/layout/IconWrapper/IconWrapper.module.css +1 -1
- package/src/components/layout/IconWrapper/IconWrapper.tsx +4 -5
- package/src/components/layout/SectionHeader/SectionHeader.tsx +5 -4
- package/src/components/ui/Accordion/Accordion.tsx +4 -3
- package/src/components/ui/Alert/Alert.module.css +1 -1
- package/src/components/ui/Alert/Alert.tsx +4 -3
- package/src/components/ui/Avatar/Avatar.module.css +1 -1
- package/src/components/ui/Avatar/Avatar.tsx +5 -3
- package/src/components/ui/Badge/Badge.module.css +1 -1
- package/src/components/ui/Badge/Badge.tsx +4 -5
- package/src/components/ui/Breadcrumb/Breadcrumb.tsx +4 -3
- package/src/components/ui/Calendar/Calendar.module.css +2 -2
- package/src/components/ui/Calendar/Calendar.tsx +4 -4
- package/src/components/ui/Carousel/Carousel.module.css +1 -1
- package/src/components/ui/Carousel/Carousel.tsx +4 -4
- package/src/components/ui/DescriptionList/DescriptionList.tsx +4 -4
- package/src/components/ui/Loading/Loading.module.css +1 -1
- package/src/components/ui/Loading/Loading.tsx +4 -3
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -1
- package/src/components/ui/NotificationBanner/NotificationBanner.tsx +4 -2
- package/src/components/ui/Pagination/Pagination.module.css +5 -1
- package/src/components/ui/Pagination/Pagination.tsx +4 -2
- package/src/components/ui/Progress/Progress.module.css +2 -2
- package/src/components/ui/Progress/Progress.tsx +4 -2
- package/src/components/ui/ProgressCircle/ProgressCircle.tsx +4 -1
- package/src/components/ui/Separator/Separator.tsx +5 -3
- package/src/components/ui/Skeleton/Skeleton.tsx +4 -3
- package/src/components/ui/SkipLink/SkipLink.tsx +4 -5
- package/src/components/ui/Tabs/Tabs.tsx +4 -4
- package/src/components/ui/Tooltip/Tooltip.module.css +1 -1
- package/src/components/ui/Tooltip/Tooltip.tsx +4 -2
- package/src/components/ui/Typography/Typography.tsx +4 -5
- package/src/stories/DesignSystem/Grid.mdx +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boostdev/design-system-components",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "BoostDev React component library: accessible, token-driven components built on @boostdev/design-system-foundation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"React",
|
|
@@ -271,7 +271,7 @@
|
|
|
271
271
|
"typecheck": "tsc --noEmit",
|
|
272
272
|
"lint": "eslint src",
|
|
273
273
|
"lint:css": "stylelint \"src/**/*.css\"",
|
|
274
|
-
"storybook": "storybook dev -p 6006
|
|
274
|
+
"storybook": "storybook dev -p 6006",
|
|
275
275
|
"build-storybook": "storybook build",
|
|
276
276
|
"test": "vitest run",
|
|
277
277
|
"test:watch": "vitest",
|
|
@@ -279,7 +279,7 @@
|
|
|
279
279
|
"changelog:unreleased": "pnpm exec git-cliff --unreleased"
|
|
280
280
|
},
|
|
281
281
|
"devDependencies": {
|
|
282
|
-
"@boostdev/design-system-foundation": "^1.0.
|
|
282
|
+
"@boostdev/design-system-foundation": "^1.0.5",
|
|
283
283
|
"@modelcontextprotocol/sdk": "^1.27.0",
|
|
284
284
|
"@storybook/addon-docs": "8.6.14",
|
|
285
285
|
"@storybook/addon-essentials": "^8.6.14",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
padding-inline: var(--bds-space_l);
|
|
37
37
|
display: inline-flex;
|
|
38
38
|
gap: var(--bds-space_xs);
|
|
39
|
-
border-radius: var(--
|
|
39
|
+
border-radius: var(--button_radius, var(--bds-border_radius--full));
|
|
40
40
|
align-items: center;
|
|
41
41
|
cursor: pointer;
|
|
42
42
|
scroll-padding-block-end: var(--bds-space_l);
|
|
@@ -76,7 +76,6 @@
|
|
|
76
76
|
.button.--size_small {
|
|
77
77
|
--button_height: 2.25em;
|
|
78
78
|
--button_font-size: var(--bds-font_size--body--s);
|
|
79
|
-
--button_border_radius--s: var(--bds-border_radius--xs);
|
|
80
79
|
|
|
81
80
|
padding-inline: var(--bds-space_m);
|
|
82
81
|
}
|
|
@@ -89,7 +88,6 @@
|
|
|
89
88
|
|
|
90
89
|
.button.--size_large {
|
|
91
90
|
--button_font-size: var(--bds-font_size--heading-3);
|
|
92
|
-
--button_border_radius--s: var(--bds-border_radius--m);
|
|
93
91
|
|
|
94
92
|
padding-inline: var(--bds-space_xl);
|
|
95
93
|
}
|
|
@@ -137,7 +135,6 @@
|
|
|
137
135
|
.button:focus-visible {
|
|
138
136
|
outline: var(--bds-outline_default);
|
|
139
137
|
outline-offset: var(--bds-outline_offset);
|
|
140
|
-
border-radius: var(--bds-border_radius--s);
|
|
141
138
|
}
|
|
142
139
|
|
|
143
140
|
/* Default hover: outline appears, bg becomes page surface */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useRef, useId, KeyboardEvent, useMemo } from 'react';
|
|
1
|
+
import { HTMLAttributes, useState, useEffect, useRef, useId, KeyboardEvent, useMemo } from 'react';
|
|
2
2
|
import { installInvokerCommandsPolyfill } from '../../../polyfill-invoker-commands';
|
|
3
3
|
|
|
4
4
|
// Install once at module load — no-op if native support is present.
|
|
@@ -17,8 +17,7 @@ export interface CommandItem {
|
|
|
17
17
|
onSelect: () => void;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
interface CommandProps extends WithClassName {
|
|
21
|
-
id?: string;
|
|
20
|
+
interface CommandProps extends WithClassName, HTMLAttributes<HTMLDialogElement> {
|
|
22
21
|
isOpen: boolean;
|
|
23
22
|
onOpen?: () => void;
|
|
24
23
|
onClose: () => void;
|
|
@@ -34,6 +33,7 @@ export function Command({
|
|
|
34
33
|
items,
|
|
35
34
|
placeholder = 'Search commands…',
|
|
36
35
|
className,
|
|
36
|
+
...rest
|
|
37
37
|
}: Readonly<CommandProps>) {
|
|
38
38
|
const [query, setQuery] = useState('');
|
|
39
39
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
@@ -139,6 +139,7 @@ export function Command({
|
|
|
139
139
|
|
|
140
140
|
return (
|
|
141
141
|
<dialog
|
|
142
|
+
{...rest}
|
|
142
143
|
ref={dialogRef}
|
|
143
144
|
id={dialogId}
|
|
144
145
|
className={cn(css.dialog, className)}
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
display: flex;
|
|
34
34
|
align-items: center;
|
|
35
35
|
justify-content: center;
|
|
36
|
-
border-radius:
|
|
36
|
+
border-radius: var(--dialog_close-radius, var(--bds-border_radius--circle));
|
|
37
37
|
background-color: var(--bds-color_bg);
|
|
38
38
|
color: currentcolor;
|
|
39
39
|
border: var(--dialog_close-border, none);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HTMLAttributes, useEffect, useId, useRef } from 'react';
|
|
2
2
|
import { installInvokerCommandsPolyfill } from '../../../polyfill-invoker-commands';
|
|
3
3
|
|
|
4
4
|
// Install once at module load — no-op if native support is present.
|
|
@@ -9,15 +9,13 @@ import css from './Dialog.module.css';
|
|
|
9
9
|
import { cn } from '@boostdev/design-system-foundation';
|
|
10
10
|
import type { WithClassName } from '../../../types';
|
|
11
11
|
|
|
12
|
-
interface DialogProps extends WithClassName {
|
|
13
|
-
children: ReactNode;
|
|
14
|
-
id?: string;
|
|
12
|
+
interface DialogProps extends WithClassName, HTMLAttributes<HTMLDialogElement> {
|
|
15
13
|
isOpen?: boolean;
|
|
16
14
|
onOpen?: () => void;
|
|
17
15
|
onClose?: () => void;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
export function Dialog({ children, id: idProp, isOpen = false, className, onOpen, onClose }: DialogProps) {
|
|
18
|
+
export function Dialog({ children, id: idProp, isOpen = false, className, onOpen, onClose, ...rest }: DialogProps) {
|
|
21
19
|
const generatedId = useId();
|
|
22
20
|
const id = idProp ?? generatedId;
|
|
23
21
|
|
|
@@ -92,6 +90,7 @@ export function Dialog({ children, id: idProp, isOpen = false, className, onOpen
|
|
|
92
90
|
|
|
93
91
|
return (
|
|
94
92
|
<dialog
|
|
93
|
+
{...rest}
|
|
95
94
|
ref={dialogRef}
|
|
96
95
|
id={id}
|
|
97
96
|
className={cn(className, css.dialog)}
|
|
@@ -85,13 +85,13 @@ describe('Drawer', () => {
|
|
|
85
85
|
expect(dialog).toHaveAttribute('aria-modal', 'true');
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
-
it('renders aria-label on the dialog when
|
|
89
|
-
render(<Drawer isOpen title="Settings"
|
|
88
|
+
it('renders aria-label on the dialog when aria-label prop is provided', () => {
|
|
89
|
+
render(<Drawer isOpen title="Settings" aria-label="Settings panel" onClose={() => {}}>Content</Drawer>);
|
|
90
90
|
const dialog = document.querySelector('dialog');
|
|
91
91
|
expect(dialog).toHaveAttribute('aria-label', 'Settings panel');
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
it('does not render aria-label when
|
|
94
|
+
it('does not render aria-label when aria-label prop is not provided', () => {
|
|
95
95
|
render(<Drawer isOpen title="Settings" onClose={() => {}}>Content</Drawer>);
|
|
96
96
|
const dialog = document.querySelector('dialog');
|
|
97
97
|
expect(dialog).not.toHaveAttribute('aria-label');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode, useEffect, useId, useRef } from 'react';
|
|
1
|
+
import { HTMLAttributes, ReactNode, useEffect, useId, useRef } from 'react';
|
|
2
2
|
import { installInvokerCommandsPolyfill } from '../../../polyfill-invoker-commands';
|
|
3
3
|
|
|
4
4
|
// Install once at module load — no-op if native support is present.
|
|
@@ -8,15 +8,12 @@ import css from './Drawer.module.css';
|
|
|
8
8
|
import { cn } from '@boostdev/design-system-foundation';
|
|
9
9
|
import type { WithClassName } from '../../../types';
|
|
10
10
|
|
|
11
|
-
interface DrawerProps extends WithClassName {
|
|
12
|
-
id?: string;
|
|
11
|
+
interface DrawerProps extends WithClassName, Omit<HTMLAttributes<HTMLDialogElement>, 'title'> {
|
|
13
12
|
isOpen: boolean;
|
|
14
13
|
onOpen?: () => void;
|
|
15
14
|
onClose: () => void;
|
|
16
15
|
title: ReactNode;
|
|
17
|
-
children: ReactNode;
|
|
18
16
|
side?: 'left' | 'right';
|
|
19
|
-
ariaLabel?: string;
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
export function Drawer({
|
|
@@ -27,8 +24,8 @@ export function Drawer({
|
|
|
27
24
|
title,
|
|
28
25
|
children,
|
|
29
26
|
side = 'right',
|
|
30
|
-
ariaLabel,
|
|
31
27
|
className,
|
|
28
|
+
...rest
|
|
32
29
|
}: Readonly<DrawerProps>) {
|
|
33
30
|
const generatedId = useId();
|
|
34
31
|
const id = idProp ?? generatedId;
|
|
@@ -92,10 +89,10 @@ export function Drawer({
|
|
|
92
89
|
|
|
93
90
|
return (
|
|
94
91
|
<dialog
|
|
92
|
+
{...rest}
|
|
95
93
|
ref={dialogRef}
|
|
96
94
|
id={id}
|
|
97
95
|
className={cn(css.drawer, css[`--side_${side}`], className)}
|
|
98
|
-
aria-label={ariaLabel}
|
|
99
96
|
aria-modal="true"
|
|
100
97
|
onClick={handleClick}
|
|
101
98
|
onCancel={handleCancel}
|
|
@@ -26,14 +26,14 @@ export const Default: Story = {
|
|
|
26
26
|
],
|
|
27
27
|
},
|
|
28
28
|
render: args => (
|
|
29
|
-
<DropdownMenu {...args} trigger={<Button variant="
|
|
29
|
+
<DropdownMenu {...args} trigger={<Button variant="outline">Actions ▾</Button>} />
|
|
30
30
|
),
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export const WithDisabledItem: Story = {
|
|
34
34
|
render: () => (
|
|
35
35
|
<DropdownMenu
|
|
36
|
-
trigger={<Button variant="
|
|
36
|
+
trigger={<Button variant="outline">Options ▾</Button>}
|
|
37
37
|
items={[
|
|
38
38
|
{ id: 'view', label: 'View' },
|
|
39
39
|
{ id: 'edit', label: 'Edit' },
|
|
@@ -46,7 +46,7 @@ export const WithDisabledItem: Story = {
|
|
|
46
46
|
export const WithSeparator: Story = {
|
|
47
47
|
render: () => (
|
|
48
48
|
<DropdownMenu
|
|
49
|
-
trigger={<Button variant="
|
|
49
|
+
trigger={<Button variant="outline">File ▾</Button>}
|
|
50
50
|
items={[
|
|
51
51
|
{ id: 'new', label: 'New' },
|
|
52
52
|
{ id: 'open', label: 'Open' },
|
|
@@ -60,7 +60,7 @@ export const WithSeparator: Story = {
|
|
|
60
60
|
export const AlignedEnd: Story = {
|
|
61
61
|
render: () => (
|
|
62
62
|
<DropdownMenu
|
|
63
|
-
trigger={<Button variant="
|
|
63
|
+
trigger={<Button variant="outline">⋮</Button>}
|
|
64
64
|
items={[{ id: 'copy', label: 'Copy link' }, { id: 'report', label: 'Report' }]}
|
|
65
65
|
placement="bottom-end"
|
|
66
66
|
/>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
HTMLAttributes,
|
|
2
3
|
KeyboardEvent,
|
|
3
4
|
ReactElement,
|
|
4
5
|
cloneElement,
|
|
@@ -21,7 +22,7 @@ export interface DropdownMenuItem {
|
|
|
21
22
|
separator?: boolean;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
interface DropdownMenuProps extends WithClassName {
|
|
25
|
+
interface DropdownMenuProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
25
26
|
trigger: ReactElement;
|
|
26
27
|
items: DropdownMenuItem[];
|
|
27
28
|
placement?: 'bottom-start' | 'bottom-end';
|
|
@@ -32,6 +33,7 @@ export function DropdownMenu({
|
|
|
32
33
|
items,
|
|
33
34
|
placement = 'bottom-start',
|
|
34
35
|
className,
|
|
36
|
+
...rest
|
|
35
37
|
}: Readonly<DropdownMenuProps>) {
|
|
36
38
|
const [isOpen, setIsOpen] = useState(false);
|
|
37
39
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
@@ -105,7 +107,7 @@ export function DropdownMenu({
|
|
|
105
107
|
: trigger;
|
|
106
108
|
|
|
107
109
|
return (
|
|
108
|
-
<div ref={containerRef} className={cn(css.wrapper, className)}>
|
|
110
|
+
<div {...rest} ref={containerRef} className={cn(css.wrapper, className)}>
|
|
109
111
|
{triggerEl}
|
|
110
112
|
{isOpen && (
|
|
111
113
|
<ul
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
HTMLAttributes,
|
|
2
3
|
ReactElement,
|
|
3
4
|
ReactNode,
|
|
4
5
|
cloneElement,
|
|
@@ -25,11 +26,10 @@ if (
|
|
|
25
26
|
import('@oddbird/css-anchor-positioning').catch(() => {});
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
interface PopoverProps extends WithClassName {
|
|
29
|
+
interface PopoverProps extends WithClassName, Omit<HTMLAttributes<HTMLSpanElement>, 'content'> {
|
|
29
30
|
children: ReactElement;
|
|
30
31
|
content: ReactNode;
|
|
31
32
|
placement?: 'top' | 'bottom' | 'left' | 'right';
|
|
32
|
-
'aria-label'?: string;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export function Popover({
|
|
@@ -38,6 +38,7 @@ export function Popover({
|
|
|
38
38
|
placement = 'bottom',
|
|
39
39
|
className,
|
|
40
40
|
'aria-label': ariaLabel,
|
|
41
|
+
...rest
|
|
41
42
|
}: Readonly<PopoverProps>) {
|
|
42
43
|
const [isOpen, setIsOpen] = useState(false);
|
|
43
44
|
const containerRef = useRef<HTMLSpanElement>(null);
|
|
@@ -102,7 +103,7 @@ export function Popover({
|
|
|
102
103
|
: children;
|
|
103
104
|
|
|
104
105
|
return (
|
|
105
|
-
<span ref={containerRef} className={cn(css.wrapper, className)}>
|
|
106
|
+
<span {...rest} ref={containerRef} className={cn(css.wrapper, className)}>
|
|
106
107
|
{trigger}
|
|
107
108
|
<div
|
|
108
109
|
ref={panelRef}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import css from './Rating.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
interface RatingProps extends WithClassName {
|
|
6
|
+
interface RatingProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
6
7
|
value: number;
|
|
7
8
|
max?: number;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
export function Rating({ value, max = 5, className }: RatingProps) {
|
|
11
|
+
export function Rating({ value, max = 5, className, ...rest }: RatingProps) {
|
|
11
12
|
return (
|
|
12
13
|
<div
|
|
14
|
+
{...rest}
|
|
13
15
|
className={cn(css.rating, className)}
|
|
14
16
|
role="img"
|
|
15
17
|
aria-label={`${value} out of ${max} stars`}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FieldsetHTMLAttributes, 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
5
|
import type { WithClassName } from '../../../../types';
|
|
6
6
|
|
|
7
|
-
export interface CheckboxGroupProps extends WithClassName {
|
|
7
|
+
export interface CheckboxGroupProps extends WithClassName, FieldsetHTMLAttributes<HTMLFieldSetElement> {
|
|
8
8
|
legend: string;
|
|
9
|
-
children: ReactNode;
|
|
10
9
|
error?: string;
|
|
11
10
|
hint?: string;
|
|
12
11
|
required?: boolean;
|
|
13
|
-
disabled?: boolean;
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
export function CheckboxGroup({
|
|
@@ -19,8 +17,8 @@ export function CheckboxGroup({
|
|
|
19
17
|
error,
|
|
20
18
|
hint,
|
|
21
19
|
required,
|
|
22
|
-
disabled,
|
|
23
20
|
className,
|
|
21
|
+
...rest
|
|
24
22
|
}: Readonly<CheckboxGroupProps>) {
|
|
25
23
|
const id = useId();
|
|
26
24
|
const hintId = id + 'hint';
|
|
@@ -29,8 +27,8 @@ export function CheckboxGroup({
|
|
|
29
27
|
|
|
30
28
|
return (
|
|
31
29
|
<fieldset
|
|
30
|
+
{...rest}
|
|
32
31
|
className={cn(css.group, className)}
|
|
33
|
-
disabled={disabled}
|
|
34
32
|
aria-required={required || undefined}
|
|
35
33
|
aria-describedby={describedBy}
|
|
36
34
|
>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
padding-inline-end: var(--bds-space_xxl);
|
|
20
20
|
border: var(--combobox_border, none);
|
|
21
21
|
--bdc_color: currentcolor;
|
|
22
|
-
--bdc-outline_radius: var(--bds-border_radius--
|
|
22
|
+
--bdc-outline_radius: var(--bds-border_radius--full);
|
|
23
23
|
|
|
24
24
|
border-radius: var(--combobox_radius, var(--bdc-outline_radius));
|
|
25
25
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--combobox_shadow, var(--bdc-outline_shadow));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ChangeEvent,
|
|
3
|
+
HTMLAttributes,
|
|
3
4
|
KeyboardEvent,
|
|
4
5
|
ReactNode,
|
|
5
6
|
useEffect,
|
|
@@ -21,7 +22,7 @@ export interface ComboboxOption {
|
|
|
21
22
|
disabled?: boolean;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
interface ComboboxProps extends WithClassName {
|
|
25
|
+
interface ComboboxProps extends WithClassName, Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
25
26
|
label: ReactNode;
|
|
26
27
|
name: string;
|
|
27
28
|
options: ComboboxOption[];
|
|
@@ -44,6 +45,7 @@ export function Combobox({
|
|
|
44
45
|
error,
|
|
45
46
|
hint,
|
|
46
47
|
className,
|
|
48
|
+
...rest
|
|
47
49
|
}: Readonly<ComboboxProps>) {
|
|
48
50
|
const id = name + useId();
|
|
49
51
|
const listboxId = id + 'listbox';
|
|
@@ -122,7 +124,7 @@ export function Combobox({
|
|
|
122
124
|
};
|
|
123
125
|
|
|
124
126
|
return (
|
|
125
|
-
<InputContainer className={cn(css.formGroup, className)}>
|
|
127
|
+
<InputContainer {...rest} className={cn(css.formGroup, className)}>
|
|
126
128
|
<Label id={id} label={label} />
|
|
127
129
|
<div ref={containerRef} className={css.inputWrapper}>
|
|
128
130
|
<input
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { useId, useRef, useState, DragEvent, ChangeEvent } from 'react';
|
|
1
|
+
import { HTMLAttributes, useId, useRef, useState, DragEvent, ChangeEvent } from 'react';
|
|
2
2
|
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
6
|
import type { WithClassName } from '../../../../types';
|
|
7
7
|
|
|
8
|
-
interface FileInputProps extends WithClassName {
|
|
8
|
+
interface FileInputProps extends WithClassName, Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
9
9
|
label: string;
|
|
10
10
|
name: string;
|
|
11
11
|
accept?: string;
|
|
@@ -28,6 +28,7 @@ export function FileInput({
|
|
|
28
28
|
hint,
|
|
29
29
|
onChange,
|
|
30
30
|
className,
|
|
31
|
+
...rest
|
|
31
32
|
}: Readonly<FileInputProps>) {
|
|
32
33
|
const uid = name + useId();
|
|
33
34
|
const hintId = uid + 'hint';
|
|
@@ -73,7 +74,7 @@ export function FileInput({
|
|
|
73
74
|
const handleDragLeave = () => setIsDragging(false);
|
|
74
75
|
|
|
75
76
|
return (
|
|
76
|
-
<InputContainer className={cn(css.formGroup, className)}>
|
|
77
|
+
<InputContainer {...rest} className={cn(css.formGroup, className)}>
|
|
77
78
|
<label
|
|
78
79
|
htmlFor={uid}
|
|
79
80
|
className={cn(css.dropZone, isDragging && css.isDragging, error && css.hasError, disabled && css.isDisabled)}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
padding: var(--bds-space_s);
|
|
13
13
|
border: var(--input_border, none);
|
|
14
14
|
--bdc_color: currentcolor;
|
|
15
|
-
--bdc-outline_radius: var(--bds-border_radius--
|
|
15
|
+
--bdc-outline_radius: var(--bds-border_radius--full);
|
|
16
16
|
|
|
17
17
|
border-radius: var(--input_radius, var(--bdc-outline_radius));
|
|
18
18
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--input_shadow, var(--bdc-outline_shadow));
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
align-items: stretch;
|
|
10
10
|
border: var(--numberInput_border, none);
|
|
11
11
|
--bdc_color: currentcolor;
|
|
12
|
-
--bdc-outline_radius: var(--bds-border_radius--
|
|
12
|
+
--bdc-outline_radius: var(--bds-border_radius--full);
|
|
13
13
|
|
|
14
14
|
--_radius: var(--numberInput_radius, var(--bdc-outline_radius));
|
|
15
15
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useId, useRef, useState} from 'react';
|
|
1
|
+
import {HTMLAttributes, useId, useRef, useState} from 'react';
|
|
2
2
|
import css from './NumberInput.module.css';
|
|
3
3
|
import {Label} from '../atoms/Label';
|
|
4
4
|
import {Message} from '../atoms/Message';
|
|
@@ -6,7 +6,7 @@ import {InputContainer} from '../atoms/InputContainer';
|
|
|
6
6
|
import {cn} from '@boostdev/design-system-foundation';
|
|
7
7
|
import type { WithClassName } from '../../../../types';
|
|
8
8
|
|
|
9
|
-
interface NumberInputProps extends WithClassName {
|
|
9
|
+
interface NumberInputProps extends WithClassName, Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
10
10
|
label: string;
|
|
11
11
|
name: string;
|
|
12
12
|
value?: number;
|
|
@@ -33,6 +33,7 @@ export function NumberInput({
|
|
|
33
33
|
hint,
|
|
34
34
|
onChange,
|
|
35
35
|
className,
|
|
36
|
+
...rest
|
|
36
37
|
}: Readonly<NumberInputProps>) {
|
|
37
38
|
const uid = name + useId();
|
|
38
39
|
const hintId = uid + 'hint';
|
|
@@ -62,7 +63,7 @@ export function NumberInput({
|
|
|
62
63
|
};
|
|
63
64
|
|
|
64
65
|
return (
|
|
65
|
-
<InputContainer className={cn(css.formGroup, className)}>
|
|
66
|
+
<InputContainer {...rest} className={cn(css.formGroup, className)}>
|
|
66
67
|
<Label id={uid} label={label} />
|
|
67
68
|
<div className={css.inputRow}>
|
|
68
69
|
<button
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FieldsetHTMLAttributes, 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
5
|
import type { WithClassName } from '../../../../types';
|
|
6
6
|
|
|
7
|
-
export interface RadioGroupProps extends WithClassName {
|
|
7
|
+
export interface RadioGroupProps extends WithClassName, FieldsetHTMLAttributes<HTMLFieldSetElement> {
|
|
8
8
|
legend: string;
|
|
9
|
-
children: ReactNode;
|
|
10
9
|
error?: string;
|
|
11
10
|
hint?: string;
|
|
12
11
|
required?: boolean;
|
|
13
|
-
disabled?: boolean;
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
export function RadioGroup({
|
|
@@ -19,8 +17,8 @@ export function RadioGroup({
|
|
|
19
17
|
error,
|
|
20
18
|
hint,
|
|
21
19
|
required,
|
|
22
|
-
disabled,
|
|
23
20
|
className,
|
|
21
|
+
...rest
|
|
24
22
|
}: Readonly<RadioGroupProps>) {
|
|
25
23
|
const id = useId();
|
|
26
24
|
const hintId = id + 'hint';
|
|
@@ -29,8 +27,8 @@ export function RadioGroup({
|
|
|
29
27
|
|
|
30
28
|
return (
|
|
31
29
|
<fieldset
|
|
30
|
+
{...rest}
|
|
32
31
|
className={cn(css.group, className)}
|
|
33
|
-
disabled={disabled}
|
|
34
32
|
aria-required={required || undefined}
|
|
35
33
|
aria-describedby={describedBy}
|
|
36
34
|
>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
grid-auto-columns: 1fr;
|
|
7
7
|
padding: var(--bds-space_xxxs);
|
|
8
8
|
background-color: var(--control_track-bg, var(--bds-color_bg--subtle));
|
|
9
|
-
border-radius: var(--control_radius, var(--bds-border_radius--
|
|
9
|
+
border-radius: var(--control_radius, var(--bds-border_radius--full));
|
|
10
10
|
gap: 0;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
inset-block: var(--bds-space_xxxs);
|
|
17
17
|
inset-inline-start: var(--bds-space_xxxs);
|
|
18
18
|
inline-size: calc((100% - 2 * var(--bds-space_xxxs)) / var(--control_count, 1));
|
|
19
|
-
border-radius: var(--control_thumb-radius, var(--bds-border_radius--
|
|
19
|
+
border-radius: var(--control_thumb-radius, var(--bds-border_radius--full));
|
|
20
20
|
background-color: var(--control_thumb-bg, var(--bds-color_interactive));
|
|
21
21
|
box-shadow: var(--bds-shadow_s);
|
|
22
22
|
pointer-events: none;
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
inset-block: var(--bds-space_xxxs);
|
|
31
31
|
inset-inline-start: var(--bds-space_xxxs);
|
|
32
32
|
inline-size: calc((100% - 2 * var(--bds-space_xxxs)) / var(--control_count, 1));
|
|
33
|
-
border-radius: var(--control_thumb-radius, var(--bds-border_radius--
|
|
33
|
+
border-radius: var(--control_thumb-radius, var(--bds-border_radius--full));
|
|
34
34
|
pointer-events: none;
|
|
35
35
|
z-index: 2;
|
|
36
36
|
display: none;
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
align-items: center;
|
|
47
47
|
justify-content: center;
|
|
48
48
|
cursor: pointer;
|
|
49
|
-
border-radius: var(--control_thumb-radius, var(--bds-border_radius--
|
|
49
|
+
border-radius: var(--control_thumb-radius, var(--bds-border_radius--full));
|
|
50
50
|
padding: var(--bds-space_xs) var(--bds-space_m);
|
|
51
51
|
font-size: var(--bds-font_size--body);
|
|
52
52
|
font-family: var(--bds-font_family--body);
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
.item:focus-visible {
|
|
67
67
|
outline: var(--bds-outline_default);
|
|
68
68
|
outline-offset: calc(var(--bds-outline_offset) * -1);
|
|
69
|
-
border-radius: var(--control_thumb-radius, var(--bds-border_radius--
|
|
69
|
+
border-radius: var(--control_thumb-radius, var(--bds-border_radius--full));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
.item.--active {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { Children,
|
|
1
|
+
import { Children, HTMLAttributes, ReactElement, cloneElement, isValidElement } from 'react';
|
|
2
2
|
import css from './SegmentedControl.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../../types';
|
|
5
5
|
|
|
6
|
-
export interface SegmentedControlProps extends WithClassName {
|
|
7
|
-
children: ReactNode;
|
|
6
|
+
export interface SegmentedControlProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
8
7
|
/**
|
|
9
8
|
* Zero-based index of the active item.
|
|
10
9
|
* When omitted, auto-detected from the first child that has
|
|
@@ -15,7 +14,6 @@ export interface SegmentedControlProps extends WithClassName {
|
|
|
15
14
|
size?: 'small' | 'medium' | 'large';
|
|
16
15
|
/** "outline" (default) — sliding inset border; "filled" — sliding filled thumb */
|
|
17
16
|
variant?: 'outline' | 'filled';
|
|
18
|
-
'aria-label'?: string;
|
|
19
17
|
}
|
|
20
18
|
|
|
21
19
|
export function SegmentedControl({
|
|
@@ -25,7 +23,7 @@ export function SegmentedControl({
|
|
|
25
23
|
size = 'medium',
|
|
26
24
|
variant = 'outline',
|
|
27
25
|
className,
|
|
28
|
-
|
|
26
|
+
...rest
|
|
29
27
|
}: Readonly<SegmentedControlProps>) {
|
|
30
28
|
const validChildren = Children.toArray(children).filter(isValidElement) as ReactElement<Record<string, unknown>>[];
|
|
31
29
|
|
|
@@ -41,8 +39,8 @@ export function SegmentedControl({
|
|
|
41
39
|
|
|
42
40
|
return (
|
|
43
41
|
<div
|
|
42
|
+
{...rest}
|
|
44
43
|
role="group"
|
|
45
|
-
aria-label={ariaLabel}
|
|
46
44
|
className={cn(css.control, css[`--size_${size}`], css[`--variant_${variant}`], className)}
|
|
47
45
|
style={{
|
|
48
46
|
'--control_count': validChildren.length,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
padding-inline-end: var(--bds-space_xxl);
|
|
20
20
|
border: var(--select_border, none);
|
|
21
21
|
--bdc_color: currentcolor;
|
|
22
|
-
--bdc-outline_radius: var(--bds-border_radius--
|
|
22
|
+
--bdc-outline_radius: var(--bds-border_radius--full);
|
|
23
23
|
|
|
24
24
|
border-radius: var(--select_radius, var(--bdc-outline_radius));
|
|
25
25
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--select_shadow, var(--bdc-outline_shadow));
|