@boostdev/design-system-components 1.2.0 → 1.2.2
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 +46 -4
- package/README.md +15 -15
- package/dist/client.cjs +149 -124
- package/dist/client.css +503 -525
- package/dist/client.d.cts +71 -96
- package/dist/client.d.ts +71 -96
- package/dist/client.js +149 -124
- package/dist/index.cjs +149 -124
- package/dist/index.css +503 -525
- package/dist/index.d.cts +71 -96
- package/dist/index.d.ts +71 -96
- package/dist/index.js +149 -124
- package/dist/web-components/{chunk-6MH5UWUD.js → chunk-2FGATTGT.js} +5 -0
- package/dist/web-components/{chunk-5IPHEONG.js → chunk-6I2DBFQ7.js} +1 -0
- package/dist/web-components/{chunk-DI46Q2EA.js → chunk-OCODKRVZ.js} +57 -82
- package/dist/web-components/index.d.ts +571 -1
- package/dist/web-components/index.js +1501 -4
- package/dist/web-components/interaction/bds-collapsible.js +1 -1
- package/dist/web-components/interaction/bds-drawer.js +1 -1
- package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
- package/package.json +1 -1
- package/src/components/interaction/Command/Command.tsx +4 -3
- package/src/components/interaction/Dialog/Dialog.tsx +4 -5
- package/src/components/interaction/Drawer/Drawer.module.css +37 -62
- package/src/components/interaction/Drawer/Drawer.spec.tsx +3 -3
- package/src/components/interaction/Drawer/Drawer.tsx +25 -24
- 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.tsx +4 -2
- package/src/components/interaction/form/FileInput/FileInput.tsx +4 -3
- 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.mdx +8 -4
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +13 -6
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +4 -6
- 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.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.tsx +4 -3
- package/src/components/ui/Avatar/Avatar.tsx +5 -3
- package/src/components/ui/Badge/Badge.tsx +4 -5
- package/src/components/ui/Breadcrumb/Breadcrumb.tsx +4 -3
- package/src/components/ui/Calendar/Calendar.tsx +4 -4
- package/src/components/ui/Carousel/Carousel.tsx +4 -4
- package/src/components/ui/DescriptionList/DescriptionList.tsx +4 -4
- package/src/components/ui/Loading/Loading.tsx +4 -3
- package/src/components/ui/NotificationBanner/NotificationBanner.tsx +4 -2
- package/src/components/ui/Pagination/Pagination.tsx +4 -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.tsx +4 -2
- package/src/components/ui/Typography/Typography.tsx +4 -5
- package/src/stories/DesignSystem/Grid.mdx +2 -0
- package/src/stories/Introduction.mdx +2 -1
- package/src/web-components/index.ts +12 -0
- package/src/web-components/interaction/BdsAccordion.mdx +80 -28
- package/src/web-components/interaction/BdsAccordion.stories.tsx +67 -58
- package/src/web-components/interaction/BdsCollapsible.mdx +93 -23
- package/src/web-components/interaction/BdsCollapsible.stories.tsx +29 -48
- package/src/web-components/interaction/BdsDialog.mdx +88 -27
- package/src/web-components/interaction/BdsDialog.stories.tsx +129 -47
- package/src/web-components/interaction/BdsDrawer.mdx +85 -27
- package/src/web-components/interaction/BdsDrawer.stories.tsx +161 -31
- package/src/web-components/interaction/BdsDropdownMenu.mdx +108 -0
- package/src/web-components/interaction/BdsDropdownMenu.stories.tsx +91 -0
- package/src/web-components/interaction/BdsSkipLink.mdx +72 -16
- package/src/web-components/interaction/BdsSkipLink.stories.tsx +47 -34
- package/src/web-components/interaction/BdsTabs.mdx +97 -27
- package/src/web-components/interaction/BdsTabs.stories.tsx +69 -55
- package/src/web-components/interaction/BdsTooltip.mdx +84 -18
- package/src/web-components/interaction/BdsTooltip.stories.tsx +49 -30
- package/src/web-components/interaction/bds-collapsible.ts +1 -0
- package/src/web-components/interaction/bds-drawer.ts +59 -82
- package/src/web-components/interaction/bds-dropdown-menu-item.ts +124 -0
- package/src/web-components/interaction/bds-dropdown-menu.spec.ts +102 -0
- package/src/web-components/interaction/bds-dropdown-menu.ts +200 -0
- package/src/web-components/interaction/form/BdsCheckbox.mdx +57 -20
- package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +35 -36
- package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +70 -0
- package/src/web-components/interaction/form/BdsCheckboxGroup.stories.tsx +81 -0
- package/src/web-components/interaction/form/BdsCombobox.mdx +52 -33
- package/src/web-components/interaction/form/BdsCombobox.stories.tsx +55 -53
- package/src/web-components/interaction/form/BdsFileInput.mdx +59 -24
- package/src/web-components/interaction/form/BdsFileInput.stories.tsx +38 -53
- package/src/web-components/interaction/form/BdsFormInput.mdx +98 -0
- package/src/web-components/interaction/form/BdsFormInput.stories.tsx +139 -0
- package/src/web-components/interaction/form/BdsNumberInput.mdx +51 -22
- package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +24 -46
- package/src/web-components/interaction/form/BdsRadio.mdx +53 -22
- package/src/web-components/interaction/form/BdsRadio.stories.tsx +19 -51
- package/src/web-components/interaction/form/BdsRadioGroup.mdx +73 -0
- package/src/web-components/interaction/form/BdsRadioGroup.stories.tsx +88 -0
- package/src/web-components/interaction/form/BdsSegmentedControl.mdx +76 -23
- package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +64 -54
- package/src/web-components/interaction/form/BdsSelect.mdx +59 -21
- package/src/web-components/interaction/form/BdsSelect.stories.tsx +47 -56
- package/src/web-components/interaction/form/BdsSlider.mdx +55 -27
- package/src/web-components/interaction/form/BdsSlider.stories.tsx +23 -44
- package/src/web-components/interaction/form/BdsSwitch.mdx +53 -20
- package/src/web-components/interaction/form/BdsSwitch.stories.tsx +22 -37
- package/src/web-components/interaction/form/BdsTextarea.mdx +54 -22
- package/src/web-components/interaction/form/BdsTextarea.stories.tsx +35 -44
- package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +55 -0
- package/src/web-components/interaction/form/bds-checkbox-group.ts +117 -0
- package/src/web-components/interaction/form/bds-form-input.spec.ts +83 -0
- package/src/web-components/interaction/form/bds-form-input.ts +268 -0
- package/src/web-components/interaction/form/bds-radio-group.spec.ts +62 -0
- package/src/web-components/interaction/form/bds-radio-group.ts +142 -0
- package/src/web-components/interaction/form/bds-segmented-control.ts +5 -0
- package/src/web-components/ui/BdsAvatar.mdx +29 -20
- package/src/web-components/ui/BdsAvatar.stories.tsx +14 -28
- package/src/web-components/ui/BdsBreadcrumb.mdx +22 -19
- package/src/web-components/ui/BdsBreadcrumb.stories.tsx +11 -21
- package/src/web-components/ui/BdsButtonGroup.mdx +69 -0
- package/src/web-components/ui/BdsButtonGroup.stories.tsx +66 -0
- package/src/web-components/ui/BdsCalendar.mdx +93 -0
- package/src/web-components/ui/BdsCalendar.stories.tsx +63 -0
- package/src/web-components/ui/BdsCard.mdx +30 -25
- package/src/web-components/ui/BdsCard.stories.tsx +19 -42
- package/src/web-components/ui/BdsCarousel.mdx +83 -0
- package/src/web-components/ui/BdsCarousel.stories.tsx +96 -0
- package/src/web-components/ui/BdsDescriptionList.mdx +13 -16
- package/src/web-components/ui/BdsDescriptionList.stories.tsx +34 -49
- package/src/web-components/ui/BdsIconWrapper.mdx +20 -20
- package/src/web-components/ui/BdsIconWrapper.stories.tsx +46 -41
- package/src/web-components/ui/BdsLink.mdx +21 -17
- package/src/web-components/ui/BdsLink.stories.tsx +19 -20
- package/src/web-components/ui/BdsLoading.mdx +9 -13
- package/src/web-components/ui/BdsLoading.stories.tsx +8 -10
- package/src/web-components/ui/BdsNotificationBanner.mdx +32 -37
- package/src/web-components/ui/BdsNotificationBanner.stories.tsx +38 -47
- package/src/web-components/ui/BdsPagination.mdx +74 -0
- package/src/web-components/ui/BdsPagination.stories.tsx +36 -0
- package/src/web-components/ui/BdsProgress.mdx +24 -17
- package/src/web-components/ui/BdsProgress.stories.tsx +55 -29
- package/src/web-components/ui/BdsProgressCircle.mdx +24 -18
- package/src/web-components/ui/BdsProgressCircle.stories.tsx +17 -29
- package/src/web-components/ui/BdsRating.mdx +22 -22
- package/src/web-components/ui/BdsRating.stories.tsx +19 -13
- package/src/web-components/ui/BdsSectionHeader.mdx +31 -28
- package/src/web-components/ui/BdsSectionHeader.stories.tsx +21 -23
- package/src/web-components/ui/BdsSeparator.mdx +22 -8
- package/src/web-components/ui/BdsSeparator.stories.tsx +27 -19
- package/src/web-components/ui/BdsSkeleton.mdx +20 -26
- package/src/web-components/ui/BdsSkeleton.stories.tsx +23 -23
- package/src/web-components/ui/BdsTable.mdx +81 -0
- package/src/web-components/ui/BdsTable.stories.tsx +83 -0
- package/src/web-components/ui/BdsTypography.mdx +20 -29
- package/src/web-components/ui/BdsTypography.stories.tsx +19 -18
- package/src/web-components/ui/bds-button-group.spec.ts +40 -0
- package/src/web-components/ui/bds-button-group.ts +78 -0
- package/src/web-components/ui/bds-calendar.spec.ts +91 -0
- package/src/web-components/ui/bds-calendar.ts +427 -0
- package/src/web-components/ui/bds-carousel.spec.ts +64 -0
- package/src/web-components/ui/bds-carousel.ts +296 -0
- package/src/web-components/ui/bds-pagination.spec.ts +67 -0
- package/src/web-components/ui/bds-pagination.ts +197 -0
- package/src/web-components/ui/bds-table.spec.ts +45 -0
- package/src/web-components/ui/bds-table.ts +96 -0
|
@@ -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(--bds-border_radius--m);
|
|
9
|
+
border-radius: var(--control_radius, var(--bds-border_radius--m));
|
|
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(--bds-border_radius--s);
|
|
19
|
+
border-radius: var(--control_thumb-radius, var(--bds-border_radius--s));
|
|
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(--bds-border_radius--s);
|
|
33
|
+
border-radius: var(--control_thumb-radius, var(--bds-border_radius--s));
|
|
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(--bds-border_radius--s);
|
|
49
|
+
border-radius: var(--control_thumb-radius, var(--bds-border_radius--s));
|
|
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(--bds-border_radius--s);
|
|
69
|
+
border-radius: var(--control_thumb-radius, var(--bds-border_radius--s));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
.item.--active {
|
|
@@ -92,7 +92,6 @@
|
|
|
92
92
|
|
|
93
93
|
/* Outline variant — no thumb, sliding inset-border indicator, interactive active color */
|
|
94
94
|
.control.--variant_outline {
|
|
95
|
-
background-color: var(--control_track-bg, transparent);
|
|
96
95
|
--control_label-color--active: var(--bds-color_interactive);
|
|
97
96
|
}
|
|
98
97
|
|
|
@@ -100,6 +99,14 @@
|
|
|
100
99
|
display: none;
|
|
101
100
|
}
|
|
102
101
|
|
|
102
|
+
.control.--variant_outline .item {
|
|
103
|
+
background-color: var(--control_item-bg, transparent);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.control.--variant_outline .item.--active {
|
|
107
|
+
background-color: var(--control_item-bg--active, var(--bds-color_bg));
|
|
108
|
+
}
|
|
109
|
+
|
|
103
110
|
.control.--variant_outline .indicator {
|
|
104
111
|
display: block;
|
|
105
112
|
box-shadow: inset 0 0 0 2px var(--bds-color_interactive);
|
|
@@ -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,
|
|
@@ -5,6 +5,6 @@ import type { WithClassName } from '../../../../types';
|
|
|
5
5
|
|
|
6
6
|
type ContainerProps = WithClassName & HTMLAttributes<HTMLDivElement>;
|
|
7
7
|
|
|
8
|
-
export const InputContainer = ({ children, className }: ContainerProps) => {
|
|
9
|
-
return <div className={cn(css.container, className)}>{children}</div>;
|
|
8
|
+
export const InputContainer = ({ children, className, ...rest }: ContainerProps) => {
|
|
9
|
+
return <div {...rest} className={cn(css.container, className)}>{children}</div>;
|
|
10
10
|
};
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
2
|
import css from './ButtonGroup.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
|
-
export interface ButtonGroupProps extends WithClassName {
|
|
7
|
-
children: ReactNode;
|
|
6
|
+
export interface ButtonGroupProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
8
7
|
variant?: 'flow' | 'card' | 'modal' | 'content';
|
|
9
|
-
'aria-label'?: string;
|
|
10
8
|
}
|
|
11
9
|
|
|
12
|
-
export function ButtonGroup({ children, className, variant,
|
|
10
|
+
export function ButtonGroup({ children, className, variant, ...rest }: ButtonGroupProps) {
|
|
13
11
|
return (
|
|
14
12
|
<div
|
|
13
|
+
{...rest}
|
|
15
14
|
role="group"
|
|
16
|
-
aria-label={ariaLabel}
|
|
17
15
|
className={cn(css.buttonGroup, className, variant && css[`--variant_${variant}`])}
|
|
18
16
|
>
|
|
19
17
|
<div className={css.container}>{children}</div>
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
2
|
import css from './Card.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
|
-
interface CardProps extends WithClassName {
|
|
7
|
-
children: ReactNode;
|
|
6
|
+
interface CardProps extends WithClassName, HTMLAttributes<HTMLElement> {
|
|
8
7
|
variant?: 'default' | 'elevated' | 'outlined';
|
|
9
8
|
padding?: 'none' | 'small' | 'medium' | 'large';
|
|
10
9
|
textAlign?: 'start' | 'center' | 'end';
|
|
11
|
-
style?: CSSProperties;
|
|
12
|
-
onClick?: () => void;
|
|
13
|
-
'aria-label'?: string;
|
|
14
10
|
}
|
|
15
11
|
|
|
16
12
|
export function Card({
|
|
@@ -19,9 +15,8 @@ export function Card({
|
|
|
19
15
|
variant = 'default',
|
|
20
16
|
padding = 'medium',
|
|
21
17
|
textAlign = 'start',
|
|
22
|
-
style,
|
|
23
18
|
onClick,
|
|
24
|
-
|
|
19
|
+
...rest
|
|
25
20
|
}: CardProps) {
|
|
26
21
|
const classNames = cn(
|
|
27
22
|
css.card,
|
|
@@ -36,10 +31,9 @@ export function Card({
|
|
|
36
31
|
|
|
37
32
|
return (
|
|
38
33
|
<Component
|
|
34
|
+
{...rest}
|
|
39
35
|
className={classNames}
|
|
40
36
|
onClick={onClick}
|
|
41
|
-
style={style}
|
|
42
|
-
aria-label={ariaLabel}
|
|
43
37
|
{...(onClick && { type: 'button' as const })}
|
|
44
38
|
>
|
|
45
39
|
{children}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
import css from './IconWrapper.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
|
-
export interface IconWrapperProps extends WithClassName {
|
|
6
|
+
export interface IconWrapperProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
7
7
|
children: ReactNode;
|
|
8
|
-
'aria-hidden'?: boolean | 'true' | 'false';
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
export function IconWrapper({ children, className,
|
|
10
|
+
export function IconWrapper({ children, className, ...rest }: IconWrapperProps) {
|
|
12
11
|
return (
|
|
13
|
-
<div className={cn(className, css.wrapper)}
|
|
12
|
+
<div {...rest} className={cn(className, css.wrapper)}>{children}</div>
|
|
14
13
|
);
|
|
15
14
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { JSX } from 'react';
|
|
1
|
+
import type { HTMLAttributes, JSX } from 'react';
|
|
2
2
|
import css from './SectionHeader.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
6
|
type IntrinsicElement = keyof JSX.IntrinsicElements;
|
|
7
7
|
|
|
8
|
-
type SectionHeaderProps = WithClassName & {
|
|
8
|
+
type SectionHeaderProps = WithClassName & Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {
|
|
9
9
|
title: string;
|
|
10
10
|
subtitle?: string;
|
|
11
11
|
alignment?: 'start' | 'center' | 'end';
|
|
@@ -19,11 +19,12 @@ export function SectionHeader({
|
|
|
19
19
|
className,
|
|
20
20
|
alignment = 'start',
|
|
21
21
|
size = 'medium',
|
|
22
|
-
titleAs = 'h2'
|
|
22
|
+
titleAs = 'h2',
|
|
23
|
+
...rest
|
|
23
24
|
}: Readonly<SectionHeaderProps>) {
|
|
24
25
|
const Title = titleAs;
|
|
25
26
|
return (
|
|
26
|
-
<div className={cn(css.sectionHeader, css[`--${alignment}`], css[`--${size}`], className)}>
|
|
27
|
+
<div {...rest} className={cn(css.sectionHeader, css[`--${alignment}`], css[`--${size}`], className)}>
|
|
27
28
|
<Title className={css.title}>{title}</Title>
|
|
28
29
|
{subtitle && <p className={css.subtitle}>{subtitle}</p>}
|
|
29
30
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode, useId, useState } from 'react';
|
|
1
|
+
import { HTMLAttributes, ReactNode, useId, useState } from 'react';
|
|
2
2
|
import css from './Accordion.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
@@ -10,7 +10,7 @@ export interface AccordionItem {
|
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
interface AccordionProps extends WithClassName {
|
|
13
|
+
interface AccordionProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
14
14
|
items: AccordionItem[];
|
|
15
15
|
allowMultiple?: boolean;
|
|
16
16
|
defaultOpen?: string[];
|
|
@@ -21,6 +21,7 @@ export function Accordion({
|
|
|
21
21
|
allowMultiple = false,
|
|
22
22
|
defaultOpen = [],
|
|
23
23
|
className,
|
|
24
|
+
...rest
|
|
24
25
|
}: Readonly<AccordionProps>) {
|
|
25
26
|
const baseId = useId();
|
|
26
27
|
const [openIds, setOpenIds] = useState<string[]>(defaultOpen);
|
|
@@ -34,7 +35,7 @@ export function Accordion({
|
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
return (
|
|
37
|
-
<div className={cn(css.accordion, className)}>
|
|
38
|
+
<div {...rest} className={cn(css.accordion, className)}>
|
|
38
39
|
{items.map(item => {
|
|
39
40
|
const isOpen = openIds.includes(item.id);
|
|
40
41
|
const triggerId = `${baseId}-trigger-${item.id}`;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
import css from './Alert.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
|
-
interface AlertProps extends WithClassName {
|
|
6
|
+
interface AlertProps extends WithClassName, Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
7
7
|
variant?: 'info' | 'success' | 'warning' | 'error';
|
|
8
8
|
icon?: ReactNode;
|
|
9
9
|
title?: string;
|
|
10
|
-
children: ReactNode;
|
|
11
10
|
onDismiss?: () => void;
|
|
12
11
|
}
|
|
13
12
|
|
|
@@ -18,11 +17,13 @@ export function Alert({
|
|
|
18
17
|
children,
|
|
19
18
|
onDismiss,
|
|
20
19
|
className,
|
|
20
|
+
...rest
|
|
21
21
|
}: Readonly<AlertProps>) {
|
|
22
22
|
const isUrgent = variant === 'error' || variant === 'warning';
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
25
|
<div
|
|
26
|
+
{...rest}
|
|
26
27
|
role={isUrgent ? 'alert' : 'status'}
|
|
27
28
|
aria-live={isUrgent ? 'assertive' : 'polite'}
|
|
28
29
|
aria-atomic="true"
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import css from './Avatar.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
interface AvatarProps extends WithClassName {
|
|
6
|
+
interface AvatarProps extends WithClassName, HTMLAttributes<HTMLSpanElement> {
|
|
6
7
|
src?: string;
|
|
7
8
|
alt?: string;
|
|
8
9
|
name?: string;
|
|
@@ -18,12 +19,12 @@ function getInitials(name: string): string {
|
|
|
18
19
|
.join('');
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
export function Avatar({ src, alt, name, size = 'medium', className }: Readonly<AvatarProps>) {
|
|
22
|
+
export function Avatar({ src, alt, name, size = 'medium', className, ...rest }: Readonly<AvatarProps>) {
|
|
22
23
|
const sizeClass = css[`--size_${size}`];
|
|
23
24
|
|
|
24
25
|
if (src) {
|
|
25
26
|
return (
|
|
26
|
-
<span className={cn(css.avatar, sizeClass, className)}>
|
|
27
|
+
<span {...rest} className={cn(css.avatar, sizeClass, className)}>
|
|
27
28
|
<img src={src} alt={alt ?? name ?? 'User avatar'} className={css.image} />
|
|
28
29
|
</span>
|
|
29
30
|
);
|
|
@@ -33,6 +34,7 @@ export function Avatar({ src, alt, name, size = 'medium', className }: Readonly<
|
|
|
33
34
|
|
|
34
35
|
return (
|
|
35
36
|
<span
|
|
37
|
+
{...rest}
|
|
36
38
|
role="img"
|
|
37
39
|
aria-label={name ?? 'User avatar'}
|
|
38
40
|
className={cn(css.avatar, css['--fallback'], sizeClass, className)}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
2
|
import css from './Badge.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
|
-
interface BadgeProps extends WithClassName {
|
|
7
|
-
children: ReactNode;
|
|
6
|
+
interface BadgeProps extends WithClassName, HTMLAttributes<HTMLSpanElement> {
|
|
8
7
|
variant?: 'primary' | 'secondary' | 'success' | 'error' | 'warning';
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
export function Badge({ children, variant = 'primary', className }: BadgeProps) {
|
|
12
|
-
return <span className={cn(css.badge, css[`--variant_${variant}`], className)}>{children}</span>;
|
|
10
|
+
export function Badge({ children, variant = 'primary', className, ...rest }: BadgeProps) {
|
|
11
|
+
return <span {...rest} className={cn(css.badge, css[`--variant_${variant}`], className)}>{children}</span>;
|
|
13
12
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import css from './Breadcrumb.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
@@ -7,13 +8,13 @@ export interface BreadcrumbItem {
|
|
|
7
8
|
href?: string;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
interface BreadcrumbProps extends WithClassName {
|
|
11
|
+
interface BreadcrumbProps extends WithClassName, HTMLAttributes<HTMLElement> {
|
|
11
12
|
items: BreadcrumbItem[];
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
export function Breadcrumb({ items, className }: Readonly<BreadcrumbProps>) {
|
|
15
|
+
export function Breadcrumb({ items, className, ...rest }: Readonly<BreadcrumbProps>) {
|
|
15
16
|
return (
|
|
16
|
-
<nav aria-label="Breadcrumb" className={cn(css.breadcrumb, className)}>
|
|
17
|
+
<nav {...rest} aria-label="Breadcrumb" className={cn(css.breadcrumb, className)}>
|
|
17
18
|
<ol className={css.list}>
|
|
18
19
|
{items.map((item, index) => {
|
|
19
20
|
const isLast = index === items.length - 1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useId, KeyboardEvent } from 'react';
|
|
1
|
+
import { HTMLAttributes, useState, useId, KeyboardEvent } from 'react';
|
|
2
2
|
import css from './Calendar.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
@@ -13,7 +13,7 @@ const MONTHS = [
|
|
|
13
13
|
'July', 'August', 'September', 'October', 'November', 'December',
|
|
14
14
|
];
|
|
15
15
|
|
|
16
|
-
interface CalendarProps extends WithClassName {
|
|
16
|
+
interface CalendarProps extends WithClassName, Omit<HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'> {
|
|
17
17
|
value?: Date;
|
|
18
18
|
defaultValue?: Date;
|
|
19
19
|
min?: Date;
|
|
@@ -46,7 +46,7 @@ function getFirstDayOfMonth(year: number, month: number): number {
|
|
|
46
46
|
return new Date(year, month, 1).getDay();
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export function Calendar({ value, defaultValue, min, max, onChange, className }: Readonly<CalendarProps>) {
|
|
49
|
+
export function Calendar({ value, defaultValue, min, max, onChange, className, ...rest }: Readonly<CalendarProps>) {
|
|
50
50
|
const today = new Date();
|
|
51
51
|
const controlled = value !== undefined;
|
|
52
52
|
const [internal, setInternal] = useState<Date | undefined>(defaultValue);
|
|
@@ -107,7 +107,7 @@ export function Calendar({ value, defaultValue, min, max, onChange, className }:
|
|
|
107
107
|
while (cells.length % 7 !== 0) cells.push(null);
|
|
108
108
|
|
|
109
109
|
return (
|
|
110
|
-
<div className={cn(css.calendar, className)} role="group" aria-labelledby={titleId}>
|
|
110
|
+
<div {...rest} className={cn(css.calendar, className)} role="group" aria-labelledby={titleId}>
|
|
111
111
|
<div className={css.header}>
|
|
112
112
|
<button
|
|
113
113
|
type="button"
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { ReactNode, useRef, useId } from 'react';
|
|
1
|
+
import { HTMLAttributes, ReactNode, useRef, useId } from 'react';
|
|
2
2
|
import css from './Carousel.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
|
-
interface CarouselProps extends WithClassName {
|
|
6
|
+
interface CarouselProps extends WithClassName, HTMLAttributes<HTMLElement> {
|
|
7
7
|
items: ReactNode[];
|
|
8
8
|
label: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export function Carousel({ items, label, className }: Readonly<CarouselProps>) {
|
|
11
|
+
export function Carousel({ items, label, className, ...rest }: Readonly<CarouselProps>) {
|
|
12
12
|
const trackRef = useRef<HTMLDivElement>(null);
|
|
13
13
|
const listId = useId();
|
|
14
14
|
|
|
@@ -22,7 +22,7 @@ export function Carousel({ items, label, className }: Readonly<CarouselProps>) {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
|
-
<section aria-label={label} className={cn(css.carousel, className)}>
|
|
25
|
+
<section {...rest} aria-label={label} className={cn(css.carousel, className)}>
|
|
26
26
|
<button
|
|
27
27
|
type="button"
|
|
28
28
|
className={cn(css.navBtn, css['--prev'])}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
import css from './DescriptionList.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
@@ -8,14 +8,14 @@ export interface DescriptionItem {
|
|
|
8
8
|
details: ReactNode | ReactNode[];
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
interface DescriptionListProps extends WithClassName {
|
|
11
|
+
interface DescriptionListProps extends WithClassName, HTMLAttributes<HTMLDListElement> {
|
|
12
12
|
items: DescriptionItem[];
|
|
13
13
|
layout?: 'stacked' | 'inline';
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export function DescriptionList({ items, layout = 'stacked', className }: Readonly<DescriptionListProps>) {
|
|
16
|
+
export function DescriptionList({ items, layout = 'stacked', className, ...rest }: Readonly<DescriptionListProps>) {
|
|
17
17
|
return (
|
|
18
|
-
<dl className={cn(css.list, css[`--layout_${layout}`], className)}>
|
|
18
|
+
<dl {...rest} className={cn(css.list, css[`--layout_${layout}`], className)}>
|
|
19
19
|
{items.map((item, i) => (
|
|
20
20
|
<div key={i} className={css.group}>
|
|
21
21
|
<dt className={css.term}>{item.term}</dt>
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import css from './Loading.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
interface LoadingProps extends WithClassName {
|
|
6
|
+
interface LoadingProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
6
7
|
size?: 'small' | 'medium' | 'large';
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
export function Loading({ size = 'medium', className }: LoadingProps) {
|
|
10
|
+
export function Loading({ size = 'medium', className, ...rest }: LoadingProps) {
|
|
10
11
|
return (
|
|
11
|
-
<div className={cn(css.loading, css[`--size_${size}`], className)}>
|
|
12
|
+
<div {...rest} className={cn(css.loading, css[`--size_${size}`], className)}>
|
|
12
13
|
<div className={css.spinner} role="status" aria-label="Loading" />
|
|
13
14
|
</div>
|
|
14
15
|
);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
import css from './NotificationBanner.module.css';
|
|
3
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
4
4
|
import type { WithClassName } from '../../../types';
|
|
5
5
|
|
|
6
|
-
interface NotificationBannerProps extends WithClassName {
|
|
6
|
+
interface NotificationBannerProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
7
7
|
variant?: 'info' | 'success' | 'warning' | 'error';
|
|
8
8
|
children: ReactNode;
|
|
9
9
|
action?: ReactNode;
|
|
@@ -16,11 +16,13 @@ export function NotificationBanner({
|
|
|
16
16
|
action,
|
|
17
17
|
onDismiss,
|
|
18
18
|
className,
|
|
19
|
+
...rest
|
|
19
20
|
}: Readonly<NotificationBannerProps>) {
|
|
20
21
|
const isUrgent = variant === 'error' || variant === 'warning';
|
|
21
22
|
|
|
22
23
|
return (
|
|
23
24
|
<div
|
|
25
|
+
{...rest}
|
|
24
26
|
role={isUrgent ? 'alert' : 'status'}
|
|
25
27
|
aria-live={isUrgent ? 'assertive' : 'polite'}
|
|
26
28
|
aria-atomic="true"
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import css from './Pagination.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
interface PaginationProps extends WithClassName {
|
|
6
|
+
interface PaginationProps extends WithClassName, HTMLAttributes<HTMLElement> {
|
|
6
7
|
currentPage: number;
|
|
7
8
|
totalPages: number;
|
|
8
9
|
onPageChange: (page: number) => void;
|
|
@@ -28,11 +29,12 @@ export function Pagination({
|
|
|
28
29
|
totalPages,
|
|
29
30
|
onPageChange,
|
|
30
31
|
className,
|
|
32
|
+
...rest
|
|
31
33
|
}: Readonly<PaginationProps>) {
|
|
32
34
|
const pages = getPageRange(currentPage, totalPages);
|
|
33
35
|
|
|
34
36
|
return (
|
|
35
|
-
<nav aria-label="Pagination" className={cn(css.pagination, className)}>
|
|
37
|
+
<nav {...rest} aria-label="Pagination" className={cn(css.pagination, className)}>
|
|
36
38
|
<ul className={css.list}>
|
|
37
39
|
<li>
|
|
38
40
|
<button
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import css from './Progress.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
interface ProgressProps extends WithClassName {
|
|
6
|
+
interface ProgressProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
6
7
|
value: number;
|
|
7
8
|
max?: number;
|
|
8
9
|
label: string;
|
|
@@ -17,11 +18,12 @@ export function Progress({
|
|
|
17
18
|
showLabel = false,
|
|
18
19
|
size = 'medium',
|
|
19
20
|
className,
|
|
21
|
+
...rest
|
|
20
22
|
}: Readonly<ProgressProps>) {
|
|
21
23
|
const percentage = Math.min(100, Math.max(0, (value / max) * 100));
|
|
22
24
|
|
|
23
25
|
return (
|
|
24
|
-
<div className={cn(css.container, className)}>
|
|
26
|
+
<div {...rest} className={cn(css.container, className)}>
|
|
25
27
|
{showLabel && (
|
|
26
28
|
<div className={css.labelRow}>
|
|
27
29
|
<span className={css.label}>{label}</span>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import css from './ProgressCircle.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
interface ProgressCircleProps extends WithClassName {
|
|
6
|
+
interface ProgressCircleProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
|
|
6
7
|
value: number;
|
|
7
8
|
max?: number;
|
|
8
9
|
label: string;
|
|
@@ -20,6 +21,7 @@ export function ProgressCircle({
|
|
|
20
21
|
showValue = false,
|
|
21
22
|
size = 'medium',
|
|
22
23
|
className,
|
|
24
|
+
...rest
|
|
23
25
|
}: Readonly<ProgressCircleProps>) {
|
|
24
26
|
const percentage = Math.min(100, Math.max(0, (value / max) * 100));
|
|
25
27
|
const px = SIZE_PX[size];
|
|
@@ -30,6 +32,7 @@ export function ProgressCircle({
|
|
|
30
32
|
|
|
31
33
|
return (
|
|
32
34
|
<div
|
|
35
|
+
{...rest}
|
|
33
36
|
role="progressbar"
|
|
34
37
|
aria-label={label}
|
|
35
38
|
aria-valuenow={value}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import css from './Separator.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
interface SeparatorProps extends WithClassName {
|
|
6
|
+
interface SeparatorProps extends WithClassName, HTMLAttributes<HTMLElement> {
|
|
6
7
|
orientation?: 'horizontal' | 'vertical';
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
export function Separator({ orientation = 'horizontal', className }: Readonly<SeparatorProps>) {
|
|
10
|
+
export function Separator({ orientation = 'horizontal', className, ...rest }: Readonly<SeparatorProps>) {
|
|
10
11
|
if (orientation === 'vertical') {
|
|
11
12
|
return (
|
|
12
13
|
<div
|
|
14
|
+
{...rest}
|
|
13
15
|
role="separator"
|
|
14
16
|
aria-orientation="vertical"
|
|
15
17
|
className={cn(css.separator, css['--vertical'], className)}
|
|
@@ -17,5 +19,5 @@ export function Separator({ orientation = 'horizontal', className }: Readonly<Se
|
|
|
17
19
|
);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
return <hr aria-orientation="horizontal" className={cn(css.separator, css['--horizontal'], className)} />;
|
|
22
|
+
return <hr {...rest} aria-orientation="horizontal" className={cn(css.separator, css['--horizontal'], className)} />;
|
|
21
23
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
1
2
|
import { cn } from '@boostdev/design-system-foundation';
|
|
2
3
|
import css from './Skeleton.module.css';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
type SkeletonProps = WithClassName
|
|
6
|
+
type SkeletonProps = WithClassName & HTMLAttributes<HTMLDivElement>;
|
|
6
7
|
|
|
7
|
-
export function Skeleton({ className }: SkeletonProps) {
|
|
8
|
+
export function Skeleton({ className, ...rest }: SkeletonProps) {
|
|
8
9
|
return (
|
|
9
|
-
<div aria-hidden="true" className={cn(css.skeleton, className)} />
|
|
10
|
+
<div {...rest} aria-hidden="true" className={cn(css.skeleton, className)} />
|
|
10
11
|
);
|
|
11
12
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
+
import { AnchorHTMLAttributes } from 'react';
|
|
1
2
|
import css from './SkipLink.module.css';
|
|
2
3
|
import { cn } from '@boostdev/design-system-foundation';
|
|
3
4
|
import type { WithClassName } from '../../../types';
|
|
4
5
|
|
|
5
|
-
interface SkipLinkProps extends WithClassName {
|
|
6
|
-
href?: string;
|
|
7
|
-
children?: string;
|
|
6
|
+
interface SkipLinkProps extends WithClassName, AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
8
7
|
}
|
|
9
8
|
|
|
10
|
-
export function SkipLink({ href = '#main', children = 'Skip to main content', className }: SkipLinkProps) {
|
|
9
|
+
export function SkipLink({ href = '#main', children = 'Skip to main content', className, ...rest }: SkipLinkProps) {
|
|
11
10
|
return (
|
|
12
|
-
<a href={href} className={cn(css.skipLink, className)}>
|
|
11
|
+
<a {...rest} href={href} className={cn(css.skipLink, className)}>
|
|
13
12
|
{children}
|
|
14
13
|
</a>
|
|
15
14
|
);
|