@robr0/design-system 0.1.0 → 0.3.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/README.md +13 -9
- package/components/Accordion/Accordion.js +0 -1
- package/components/Avatar/Avatar.js +1 -0
- package/components/Breadcrumb/Breadcrumb.css +9 -1
- package/components/Breadcrumb/Breadcrumb.d.ts +7 -1
- package/components/Breadcrumb/Breadcrumb.js +3 -2
- package/components/Button/Button.css +18 -0
- package/components/Button/Button.d.ts +38 -16
- package/components/Button/Button.js +76 -58
- package/components/Card/Card.css +6 -0
- package/components/Card/Card.d.ts +17 -5
- package/components/Card/Card.js +101 -80
- package/components/Checkbox/Checkbox.d.ts +24 -12
- package/components/Checkbox/Checkbox.js +99 -85
- package/components/CircularButton/CircularButton.css +11 -0
- package/components/CircularButton/CircularButton.d.ts +7 -1
- package/components/CircularButton/CircularButton.js +15 -4
- package/components/CodeBlock/CodeBlock.js +10 -1
- package/components/ColorPicker/ColorPicker.css +278 -0
- package/components/ColorPicker/ColorPicker.d.ts +50 -0
- package/components/ColorPicker/ColorPicker.js +338 -0
- package/components/Combobox/Combobox.css +0 -36
- package/components/Combobox/Combobox.d.ts +19 -7
- package/components/Combobox/Combobox.js +106 -89
- package/components/CommandPalette/CommandPalette.css +1 -15
- package/components/CommandPalette/CommandPalette.js +6 -5
- package/components/ContextMenu/ContextMenu.css +262 -0
- package/components/ContextMenu/ContextMenu.d.ts +26 -0
- package/components/ContextMenu/ContextMenu.js +350 -0
- package/components/DateInput/DateInput.css +0 -36
- package/components/DateInput/DateInput.d.ts +18 -21
- package/components/DateInput/DateInput.js +76 -64
- package/components/DatePicker/DatePicker.d.ts +9 -2
- package/components/DatePicker/DatePicker.js +137 -128
- package/components/Dialog/Dialog.d.ts +15 -4
- package/components/Dialog/Dialog.js +136 -118
- package/components/Drawer/Drawer.d.ts +15 -4
- package/components/Drawer/Drawer.js +138 -119
- package/components/Dropdown/Dropdown.css +0 -36
- package/components/Dropdown/Dropdown.d.ts +24 -8
- package/components/Dropdown/Dropdown.js +219 -169
- package/components/DropdownMenu/DropdownMenu.js +10 -7
- package/components/Field/Field.css +80 -0
- package/components/Field/Field.d.ts +50 -0
- package/components/Field/Field.js +58 -0
- package/components/Field/FieldContext.d.ts +42 -0
- package/components/Field/FieldContext.js +7 -0
- package/components/FileInput/FileInput.css +0 -36
- package/components/FileInput/FileInput.d.ts +13 -17
- package/components/FileInput/FileInput.js +168 -141
- package/components/Input/Input.css +0 -43
- package/components/Input/Input.d.ts +23 -22
- package/components/Input/Input.js +93 -66
- package/components/Kbd/Kbd.css +28 -0
- package/components/Kbd/Kbd.d.ts +19 -0
- package/components/Kbd/Kbd.js +14 -0
- package/components/Popover/Popover.d.ts +0 -6
- package/components/Popover/Popover.js +22 -16
- package/components/ProgressBar/ProgressBar.js +1 -1
- package/components/RadioButton/RadioButton.d.ts +26 -13
- package/components/RadioButton/RadioButton.js +95 -70
- package/components/SelectionCard/SelectionCard.css +6 -2
- package/components/SelectionCard/SelectionCard.d.ts +10 -4
- package/components/SelectionCard/SelectionCard.js +72 -56
- package/components/Skeleton/Skeleton.css +2 -0
- package/components/Slider/Slider.d.ts +19 -10
- package/components/Slider/Slider.js +50 -40
- package/components/Spinner/Spinner.css +11 -0
- package/components/Spinner/Spinner.d.ts +2 -2
- package/components/Swatch/Swatch.css +52 -0
- package/components/Swatch/Swatch.d.ts +34 -0
- package/components/Swatch/Swatch.js +44 -0
- package/components/Table/Table.css +19 -0
- package/components/Table/Table.d.ts +10 -2
- package/components/Table/Table.js +58 -58
- package/components/Textarea/Textarea.css +0 -43
- package/components/Textarea/Textarea.d.ts +21 -22
- package/components/Textarea/Textarea.js +78 -67
- package/components/ToggleGroup/ToggleGroup.d.ts +18 -8
- package/components/ToggleGroup/ToggleGroup.js +61 -44
- package/components/ToggleSwitch/ToggleSwitch.css +7 -2
- package/components/ToggleSwitch/ToggleSwitch.d.ts +17 -9
- package/components/ToggleSwitch/ToggleSwitch.js +57 -44
- package/components/registry.d.ts +47 -10
- package/components/registry.js +5 -1
- package/components/registry.json +498 -56
- package/components/registry.json.d.ts +498 -56
- package/components/registry.json.js +4 -1
- package/index.d.ts +8 -1
- package/index.js +16 -1
- package/package.json +1 -1
|
@@ -14,19 +14,6 @@
|
|
|
14
14
|
LABEL
|
|
15
15
|
============================================ */
|
|
16
16
|
|
|
17
|
-
.ds-textarea__label {
|
|
18
|
-
font-family: var(--font-paragraph-em-family);
|
|
19
|
-
font-size: var(--font-paragraph-em-size);
|
|
20
|
-
font-weight: var(--font-paragraph-em-weight);
|
|
21
|
-
line-height: var(--font-paragraph-em-line-height);
|
|
22
|
-
letter-spacing: var(--font-paragraph-em-letter-spacing);
|
|
23
|
-
color: var(--color-text-primary);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.ds-textarea__required {
|
|
27
|
-
color: var(--color-core-accent-coral);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
17
|
/* ============================================
|
|
31
18
|
FIELD
|
|
32
19
|
============================================ */
|
|
@@ -69,24 +56,6 @@
|
|
|
69
56
|
FOOTER (helper + counter)
|
|
70
57
|
============================================ */
|
|
71
58
|
|
|
72
|
-
.ds-textarea__footer {
|
|
73
|
-
display: flex;
|
|
74
|
-
align-items: flex-start;
|
|
75
|
-
justify-content: space-between;
|
|
76
|
-
gap: var(--gap-sm);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.ds-textarea__helper {
|
|
80
|
-
font-family: var(--font-paragraph-sm-family);
|
|
81
|
-
font-size: var(--font-paragraph-sm-size);
|
|
82
|
-
font-weight: var(--font-paragraph-sm-weight);
|
|
83
|
-
line-height: var(--font-paragraph-sm-line-height);
|
|
84
|
-
letter-spacing: var(--font-paragraph-sm-letter-spacing);
|
|
85
|
-
color: var(--color-text-tertiary);
|
|
86
|
-
margin: 0;
|
|
87
|
-
flex: 1;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
59
|
.ds-textarea__counter {
|
|
91
60
|
font-family: var(--font-paragraph-sm-family);
|
|
92
61
|
font-size: var(--font-paragraph-sm-size);
|
|
@@ -108,10 +77,6 @@
|
|
|
108
77
|
border-color: var(--color-status-error-border);
|
|
109
78
|
}
|
|
110
79
|
|
|
111
|
-
.ds-textarea--error .ds-textarea__helper {
|
|
112
|
-
color: var(--color-status-error-border);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
80
|
.ds-textarea--error .ds-textarea__counter {
|
|
116
81
|
color: var(--color-status-error-border);
|
|
117
82
|
}
|
|
@@ -120,10 +85,6 @@
|
|
|
120
85
|
DISABLED STATE
|
|
121
86
|
============================================ */
|
|
122
87
|
|
|
123
|
-
.ds-textarea--disabled .ds-textarea__label {
|
|
124
|
-
color: var(--color-input-text-disabled);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
88
|
.ds-textarea--disabled .ds-textarea__field {
|
|
128
89
|
background-color: var(--color-input-bg-disabled);
|
|
129
90
|
border-color: var(--color-input-border-disabled);
|
|
@@ -146,7 +107,3 @@
|
|
|
146
107
|
letter-spacing: var(--font-paragraph-sm-letter-spacing);
|
|
147
108
|
}
|
|
148
109
|
|
|
149
|
-
.ds-textarea--compact .ds-textarea__label {
|
|
150
|
-
font-size: var(--font-paragraph-sm-size);
|
|
151
|
-
line-height: var(--font-paragraph-sm-line-height);
|
|
152
|
-
}
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
|
|
2
|
+
/** Props owned by Textarea itself — everything else falls through to the <textarea>. */
|
|
3
|
+
type TextareaOwnProps = {
|
|
3
4
|
/** Textarea label text */
|
|
4
5
|
label?: string;
|
|
5
|
-
/** Placeholder text */
|
|
6
|
-
placeholder?: string;
|
|
7
6
|
/** Current value */
|
|
8
7
|
value?: string;
|
|
9
|
-
/** Number of visible rows */
|
|
10
|
-
rows?: number;
|
|
11
8
|
/** Component size */
|
|
12
9
|
size?: 'default' | 'compact';
|
|
13
|
-
/** Whether the textarea is disabled */
|
|
14
|
-
disabled?: boolean;
|
|
15
|
-
/** Whether the textarea is required */
|
|
16
|
-
required?: boolean;
|
|
17
10
|
/** Error state — shows error styling and message */
|
|
18
11
|
error?: boolean;
|
|
19
12
|
/** Helper or error message displayed below */
|
|
@@ -22,19 +15,25 @@ export interface TextareaProps {
|
|
|
22
15
|
resize?: 'none' | 'vertical' | 'horizontal' | 'both';
|
|
23
16
|
/** Max character count — shows counter when set */
|
|
24
17
|
maxLength?: number;
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
/** Additional CSS classes */
|
|
18
|
+
/**
|
|
19
|
+
* Convenience callback receiving the value directly.
|
|
20
|
+
* Fires alongside `onChange`, which keeps the standard React event signature
|
|
21
|
+
* so form libraries work unmodified.
|
|
22
|
+
*/
|
|
23
|
+
onValueChange?: (value: string) => void;
|
|
24
|
+
/** Additional CSS classes — applied to the wrapper, not the <textarea> */
|
|
32
25
|
className?: string;
|
|
33
|
-
/**
|
|
26
|
+
/** @deprecated Pass the native `aria-label` attribute instead. */
|
|
34
27
|
ariaLabel?: string;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/** HTML id attribute */
|
|
38
|
-
id?: string;
|
|
28
|
+
};
|
|
29
|
+
export interface TextareaProps extends TextareaOwnProps, Omit<React.ComponentPropsWithoutRef<'textarea'>, keyof TextareaOwnProps> {
|
|
39
30
|
}
|
|
40
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Multi-line text input with optional label, helper text, character counter
|
|
33
|
+
* and error state.
|
|
34
|
+
*
|
|
35
|
+
* Forwards a ref to the underlying `<textarea>` and spreads unrecognised props
|
|
36
|
+
* onto it.
|
|
37
|
+
*/
|
|
38
|
+
export declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
39
|
+
export {};
|
|
@@ -1,74 +1,85 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "react";
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Field } from "../Field/Field.js";
|
|
3
4
|
import "./Textarea.css";
|
|
4
|
-
const Textarea = (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"textarea",
|
|
5
|
+
const Textarea = React.forwardRef(
|
|
6
|
+
({
|
|
7
|
+
label,
|
|
8
|
+
placeholder = "",
|
|
9
|
+
value = "",
|
|
10
|
+
rows = 4,
|
|
11
|
+
size = "default",
|
|
12
|
+
disabled = false,
|
|
13
|
+
required = false,
|
|
14
|
+
error = false,
|
|
15
|
+
helperText,
|
|
16
|
+
resize = "vertical",
|
|
17
|
+
maxLength,
|
|
18
|
+
onChange,
|
|
19
|
+
onValueChange,
|
|
20
|
+
className = "",
|
|
21
|
+
ariaLabel,
|
|
22
|
+
name,
|
|
23
|
+
id,
|
|
24
|
+
style,
|
|
25
|
+
...rest
|
|
26
|
+
}, ref) => {
|
|
27
|
+
const baseClass = "ds-textarea";
|
|
28
|
+
const classes = [
|
|
29
|
+
baseClass,
|
|
30
|
+
size === "compact" ? `${baseClass}--compact` : "",
|
|
31
|
+
error ? `${baseClass}--error` : "",
|
|
32
|
+
disabled ? `${baseClass}--disabled` : "",
|
|
33
|
+
className
|
|
34
|
+
].filter(Boolean).join(" ");
|
|
35
|
+
const handleChange = (e) => {
|
|
36
|
+
onChange?.(e);
|
|
37
|
+
onValueChange?.(e.target.value);
|
|
38
|
+
};
|
|
39
|
+
const inputId = id || name || label?.toLowerCase().replace(/\s+/g, "-");
|
|
40
|
+
const charCount = value?.length || 0;
|
|
41
|
+
return /* @__PURE__ */ jsx(
|
|
42
|
+
Field,
|
|
43
43
|
{
|
|
44
|
-
className:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
placeholder,
|
|
49
|
-
rows,
|
|
50
|
-
disabled,
|
|
44
|
+
className: classes,
|
|
45
|
+
label,
|
|
46
|
+
helperText,
|
|
47
|
+
error,
|
|
51
48
|
required,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
disabled,
|
|
50
|
+
size,
|
|
51
|
+
id: inputId,
|
|
52
|
+
aside: maxLength ? /* @__PURE__ */ jsxs("span", { className: `${baseClass}__counter`, "aria-live": "polite", "aria-atomic": "true", children: [
|
|
53
|
+
charCount,
|
|
54
|
+
"/",
|
|
55
|
+
maxLength
|
|
56
|
+
] }) : void 0,
|
|
57
|
+
children: /* @__PURE__ */ jsx(
|
|
58
|
+
"textarea",
|
|
59
|
+
{
|
|
60
|
+
...rest,
|
|
61
|
+
ref,
|
|
62
|
+
className: `${baseClass}__field`,
|
|
63
|
+
id: inputId,
|
|
64
|
+
name,
|
|
65
|
+
value,
|
|
66
|
+
placeholder,
|
|
67
|
+
rows,
|
|
68
|
+
disabled,
|
|
69
|
+
required,
|
|
70
|
+
maxLength,
|
|
71
|
+
"aria-label": ariaLabel || rest["aria-label"] || label,
|
|
72
|
+
"aria-invalid": error,
|
|
73
|
+
"aria-describedby": helperText ? `${inputId}-helper` : rest["aria-describedby"],
|
|
74
|
+
onChange: handleChange,
|
|
75
|
+
style: { resize, ...style }
|
|
76
|
+
}
|
|
77
|
+
)
|
|
60
78
|
}
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
charCount,
|
|
66
|
-
"/",
|
|
67
|
-
maxLength
|
|
68
|
-
] })
|
|
69
|
-
] })
|
|
70
|
-
] });
|
|
71
|
-
};
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
Textarea.displayName = "Textarea";
|
|
72
83
|
export {
|
|
73
84
|
Textarea
|
|
74
85
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
1
2
|
export interface ToggleGroupItem {
|
|
2
3
|
/** Unique value */
|
|
3
4
|
value: string;
|
|
@@ -6,25 +7,34 @@ export interface ToggleGroupItem {
|
|
|
6
7
|
/** Use Material Symbol icon instead of text */
|
|
7
8
|
icon?: boolean;
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
+
/** Props owned by ToggleGroup itself — everything else falls through to the wrapper. */
|
|
11
|
+
type ToggleGroupOwnProps = {
|
|
10
12
|
/** Available items */
|
|
11
13
|
items: ToggleGroupItem[];
|
|
12
14
|
/** Currently active value(s) */
|
|
13
15
|
value?: string | string[];
|
|
14
16
|
/** Allow multiple selection */
|
|
15
17
|
multiple?: boolean;
|
|
16
|
-
/**
|
|
18
|
+
/** Component size */
|
|
17
19
|
size?: 'default' | 'compact';
|
|
18
|
-
/**
|
|
20
|
+
/** Whether the whole group is disabled */
|
|
19
21
|
disabled?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
/** Accessible label for the group */
|
|
23
|
-
ariaLabel?: string;
|
|
22
|
+
/** Called with the next selection — a string when single, an array when `multiple` */
|
|
23
|
+
onValueChange?: (value: string | string[]) => void;
|
|
24
24
|
/** Additional CSS classes */
|
|
25
25
|
className?: string;
|
|
26
|
+
/** @deprecated Use `onValueChange` instead. */
|
|
27
|
+
onChange?: (value: string | string[]) => void;
|
|
28
|
+
/** @deprecated Pass the native `aria-label` attribute instead. */
|
|
29
|
+
ariaLabel?: string;
|
|
30
|
+
};
|
|
31
|
+
export interface ToggleGroupProps extends ToggleGroupOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof ToggleGroupOwnProps> {
|
|
26
32
|
}
|
|
27
33
|
/**
|
|
28
34
|
* ToggleGroup is a set of two-state buttons that can be toggled on or off.
|
|
35
|
+
*
|
|
36
|
+
* Forwards a ref to the wrapping group element and spreads unrecognised props
|
|
37
|
+
* onto it.
|
|
29
38
|
*/
|
|
30
|
-
export declare const ToggleGroup:
|
|
39
|
+
export declare const ToggleGroup: React.ForwardRefExoticComponent<ToggleGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
40
|
+
export {};
|
|
@@ -1,53 +1,70 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
2
3
|
import "./ToggleGroup.css";
|
|
3
|
-
const ToggleGroup = (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (disabled) return;
|
|
23
|
-
if (multiple) {
|
|
24
|
-
const next = activeValues.includes(itemValue) ? activeValues.filter((v) => v !== itemValue) : [...activeValues, itemValue];
|
|
25
|
-
onChange?.(next);
|
|
26
|
-
} else {
|
|
27
|
-
onChange?.(itemValue);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
return /* @__PURE__ */ jsx("div", { className: classes, role: "group", "aria-label": ariaLabel, children: items.map((item) => {
|
|
31
|
-
const isActive = activeValues.includes(item.value);
|
|
32
|
-
const btnClass = [
|
|
33
|
-
`${baseClass}__item`,
|
|
34
|
-
isActive ? `${baseClass}__item--active` : ""
|
|
4
|
+
const ToggleGroup = React.forwardRef(
|
|
5
|
+
({
|
|
6
|
+
items,
|
|
7
|
+
value = [],
|
|
8
|
+
multiple = false,
|
|
9
|
+
size = "default",
|
|
10
|
+
disabled = false,
|
|
11
|
+
onValueChange,
|
|
12
|
+
onChange,
|
|
13
|
+
ariaLabel,
|
|
14
|
+
className = "",
|
|
15
|
+
...rest
|
|
16
|
+
}, ref) => {
|
|
17
|
+
const baseClass = "ds-toggle-group";
|
|
18
|
+
const classes = [
|
|
19
|
+
baseClass,
|
|
20
|
+
`${baseClass}--${size}`,
|
|
21
|
+
disabled ? `${baseClass}--disabled` : "",
|
|
22
|
+
className
|
|
35
23
|
].filter(Boolean).join(" ");
|
|
24
|
+
const activeValues = Array.isArray(value) ? value : [value];
|
|
25
|
+
const emit = (next) => {
|
|
26
|
+
onValueChange?.(next);
|
|
27
|
+
onChange?.(next);
|
|
28
|
+
};
|
|
29
|
+
const handleClick = (itemValue) => {
|
|
30
|
+
if (disabled) return;
|
|
31
|
+
if (multiple) {
|
|
32
|
+
const next = activeValues.includes(itemValue) ? activeValues.filter((v) => v !== itemValue) : [...activeValues, itemValue];
|
|
33
|
+
emit(next);
|
|
34
|
+
} else {
|
|
35
|
+
emit(itemValue);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
36
38
|
return /* @__PURE__ */ jsx(
|
|
37
|
-
"
|
|
39
|
+
"div",
|
|
38
40
|
{
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
...rest,
|
|
42
|
+
ref,
|
|
43
|
+
className: classes,
|
|
44
|
+
role: "group",
|
|
45
|
+
"aria-label": ariaLabel || rest["aria-label"],
|
|
46
|
+
children: items.map((item) => {
|
|
47
|
+
const isActive = activeValues.includes(item.value);
|
|
48
|
+
const btnClass = [`${baseClass}__item`, isActive ? `${baseClass}__item--active` : ""].filter(Boolean).join(" ");
|
|
49
|
+
return /* @__PURE__ */ jsx(
|
|
50
|
+
"button",
|
|
51
|
+
{
|
|
52
|
+
className: btnClass,
|
|
53
|
+
onClick: () => handleClick(item.value),
|
|
54
|
+
"aria-pressed": isActive,
|
|
55
|
+
"aria-label": item.icon ? item.label : void 0,
|
|
56
|
+
disabled,
|
|
57
|
+
type: "button",
|
|
58
|
+
children: item.icon ? /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded", "aria-hidden": "true", children: item.label }) : item.label
|
|
59
|
+
},
|
|
60
|
+
item.value
|
|
61
|
+
);
|
|
62
|
+
})
|
|
63
|
+
}
|
|
48
64
|
);
|
|
49
|
-
}
|
|
50
|
-
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
ToggleGroup.displayName = "ToggleGroup";
|
|
51
68
|
export {
|
|
52
69
|
ToggleGroup
|
|
53
70
|
};
|
|
@@ -59,7 +59,10 @@
|
|
|
59
59
|
Set via --icon-size (not font-size): .material-symbols-rounded derives
|
|
60
60
|
font-size, width, and height from it together. Overriding font-size
|
|
61
61
|
alone leaves the box at the 24px default, so the glyph hangs off-centre
|
|
62
|
-
inside the thumb.
|
|
62
|
+
inside the thumb.
|
|
63
|
+
|
|
64
|
+
ds-allow(icon-size): 14px glyph inside the 20px thumb — the smallest
|
|
65
|
+
scale step would fill it edge to edge. */
|
|
63
66
|
--icon-size: 14px;
|
|
64
67
|
color: var(--color-action-primary-bg);
|
|
65
68
|
}
|
|
@@ -123,7 +126,9 @@
|
|
|
123
126
|
|
|
124
127
|
.ds-toggle-switch--compact .ds-toggle-switch__thumb-icon {
|
|
125
128
|
/* Off-scale for the same reason as the default size — the compact thumb
|
|
126
|
-
is only 16x16.
|
|
129
|
+
is only 16x16.
|
|
130
|
+
|
|
131
|
+
ds-allow(icon-size): 12px glyph inside the 16px compact thumb. */
|
|
127
132
|
--icon-size: 12px;
|
|
128
133
|
}
|
|
129
134
|
|
|
@@ -1,23 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
/** Props owned by ToggleSwitch itself — everything else falls through to the <button>. */
|
|
3
|
+
type ToggleSwitchOwnProps = {
|
|
2
4
|
/** Whether the toggle is on (checked) */
|
|
3
5
|
checked?: boolean;
|
|
4
6
|
/** Label text displayed next to the toggle */
|
|
5
7
|
label?: string;
|
|
6
8
|
/** Whether to show the label */
|
|
7
9
|
showLabel?: boolean;
|
|
8
|
-
/** Whether the toggle is disabled */
|
|
9
|
-
disabled?: boolean;
|
|
10
10
|
/** Component size */
|
|
11
11
|
size?: 'default' | 'compact';
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/** Called with the next checked state when toggled */
|
|
13
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
14
14
|
/** Additional CSS classes */
|
|
15
15
|
className?: string;
|
|
16
|
-
/**
|
|
16
|
+
/** @deprecated Use `onCheckedChange` instead. */
|
|
17
|
+
onChange?: (checked: boolean) => void;
|
|
18
|
+
/** @deprecated Pass the native `aria-label` attribute instead. */
|
|
17
19
|
ariaLabel?: string;
|
|
20
|
+
};
|
|
21
|
+
export interface ToggleSwitchProps extends ToggleSwitchOwnProps, Omit<React.ComponentPropsWithoutRef<'button'>, keyof ToggleSwitchOwnProps | 'type'> {
|
|
18
22
|
}
|
|
19
23
|
/**
|
|
20
|
-
* ToggleSwitch component from Figma design system
|
|
21
|
-
* Used for binary on/off settings like theme switching
|
|
24
|
+
* ToggleSwitch component from Figma design system.
|
|
25
|
+
* Used for binary on/off settings like theme switching.
|
|
26
|
+
*
|
|
27
|
+
* Renders a `<button role="switch">`, forwards a ref to it, and spreads
|
|
28
|
+
* unrecognised props onto it.
|
|
22
29
|
*/
|
|
23
|
-
export declare const ToggleSwitch:
|
|
30
|
+
export declare const ToggleSwitch: React.ForwardRefExoticComponent<ToggleSwitchProps & React.RefAttributes<HTMLButtonElement>>;
|
|
31
|
+
export {};
|
|
@@ -1,50 +1,63 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
2
3
|
import "./ToggleSwitch.css";
|
|
3
4
|
import "../../fonts/material-symbols.css";
|
|
4
|
-
const ToggleSwitch = (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
5
|
+
const ToggleSwitch = React.forwardRef(
|
|
6
|
+
({
|
|
7
|
+
checked = true,
|
|
8
|
+
label = "Toggle",
|
|
9
|
+
showLabel = true,
|
|
10
|
+
disabled = false,
|
|
11
|
+
size = "default",
|
|
12
|
+
onCheckedChange,
|
|
13
|
+
onChange,
|
|
14
|
+
onClick,
|
|
15
|
+
className = "",
|
|
16
|
+
ariaLabel,
|
|
17
|
+
...rest
|
|
18
|
+
}, ref) => {
|
|
19
|
+
const baseClass = "ds-toggle-switch";
|
|
20
|
+
const classes = [
|
|
21
|
+
baseClass,
|
|
22
|
+
size === "compact" ? `${baseClass}--compact` : "",
|
|
23
|
+
checked ? "" : `${baseClass}--off`,
|
|
24
|
+
disabled ? `${baseClass}--disabled` : "",
|
|
25
|
+
className
|
|
26
|
+
].filter(Boolean).join(" ");
|
|
27
|
+
const handleClick = (e) => {
|
|
28
|
+
onClick?.(e);
|
|
29
|
+
if (disabled) return;
|
|
30
|
+
onCheckedChange?.(!checked);
|
|
31
|
+
onChange?.(!checked);
|
|
32
|
+
};
|
|
33
|
+
return /* @__PURE__ */ jsxs(
|
|
34
|
+
"button",
|
|
35
|
+
{
|
|
36
|
+
...rest,
|
|
37
|
+
ref,
|
|
38
|
+
type: "button",
|
|
39
|
+
className: classes,
|
|
40
|
+
onClick: handleClick,
|
|
41
|
+
disabled,
|
|
42
|
+
role: "switch",
|
|
43
|
+
"aria-checked": checked,
|
|
44
|
+
"aria-label": ariaLabel || rest["aria-label"] || label,
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ jsx("div", { className: `${baseClass}__track`, children: /* @__PURE__ */ jsx("div", { className: `${baseClass}__thumb`, children: /* @__PURE__ */ jsx(
|
|
47
|
+
"span",
|
|
48
|
+
{
|
|
49
|
+
className: `${baseClass}__thumb-icon material-symbols-rounded`,
|
|
50
|
+
"aria-hidden": "true",
|
|
51
|
+
children: "check"
|
|
52
|
+
}
|
|
53
|
+
) }) }),
|
|
54
|
+
showLabel && /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label })
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
ToggleSwitch.displayName = "ToggleSwitch";
|
|
48
61
|
export {
|
|
49
62
|
ToggleSwitch
|
|
50
63
|
};
|