@vectara/vectara-ui 18.2.3 → 18.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/lib/components/formGroup/BlockFormGroup.d.ts +2 -0
- package/lib/components/formGroup/BlockFormGroup.js +9 -0
- package/lib/components/formGroup/FormGroup.d.ts +2 -1
- package/lib/components/formGroup/FormGroup.js +20 -6
- package/lib/components/formGroup/InlineFormGroup.d.ts +2 -0
- package/lib/components/formGroup/InlineFormGroup.js +14 -0
- package/lib/components/formGroup/_index.scss +25 -0
- package/lib/components/formGroup/types.d.ts +11 -0
- package/lib/components/formGroup/types.js +1 -0
- package/lib/components/tooltip/InfoTooltip.d.ts +4 -1
- package/lib/components/tooltip/InfoTooltip.js +13 -1
- package/lib/components/tooltip/Tooltip.d.ts +2 -1
- package/lib/components/tooltip/Tooltip.js +19 -4
- package/lib/styles/index.css +22 -0
- package/package.json +1 -1
- package/src/docs/pages/formGroup/FormGroup.tsx +40 -5
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { VuiLabel } from "../form/label/Label";
|
|
3
|
+
import { VuiSpacer } from "../spacer/Spacer";
|
|
4
|
+
import { VuiText } from "../typography/Text";
|
|
5
|
+
import { VuiTextColor } from "../typography/TextColor";
|
|
6
|
+
import { VuiFlexContainer } from "../flex/FlexContainer";
|
|
7
|
+
export const VuiBlockFormGroup = ({ label, labelRightContent, labelFor, labelSize, isRequired, helpText, ariaDescribedByLabel, errorMessages, content }) => {
|
|
8
|
+
return (_jsxs("div", { children: [(label || labelRightContent) && (_jsxs(_Fragment, { children: [_jsxs(VuiFlexContainer, Object.assign({ justifyContent: "spaceBetween", alignItems: "center", spacing: "s" }, { children: [label ? (_jsxs(VuiLabel, Object.assign({ labelFor: labelFor, size: labelSize }, { children: [label, isRequired && " (required)"] }))) : (_jsx("span", {})), labelRightContent] })), _jsx(VuiSpacer, { size: labelSize === "s" ? "xs" : "xxs" })] })), helpText && (_jsxs(_Fragment, { children: [_jsx(VuiText, Object.assign({ size: "xs", id: ariaDescribedByLabel }, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: "subdued" }, { children: helpText })) }) })), _jsx(VuiSpacer, { size: "xs" })] })), errorMessages && (_jsxs(_Fragment, { children: [errorMessages, _jsx(VuiSpacer, { size: "xs" })] })), content] }));
|
|
9
|
+
};
|
|
@@ -7,6 +7,7 @@ type Props = {
|
|
|
7
7
|
helpText?: React.ReactNode;
|
|
8
8
|
errors?: string[];
|
|
9
9
|
isRequired?: boolean;
|
|
10
|
+
inline?: boolean;
|
|
10
11
|
};
|
|
11
|
-
export declare const VuiFormGroup: ({ children, labelFor, helpText, label, labelSize, labelRightContent, errors, isRequired }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare const VuiFormGroup: ({ children, labelFor, helpText, label, labelSize, labelRightContent, errors, isRequired, inline }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
12
13
|
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cloneElement } from "react";
|
|
3
|
-
import { VuiLabel } from "../form/label/Label";
|
|
4
3
|
import { VuiSpacer } from "../spacer/Spacer";
|
|
5
4
|
import { VuiText } from "../typography/Text";
|
|
6
5
|
import { VuiTextColor } from "../typography/TextColor";
|
|
@@ -9,9 +8,10 @@ import { VuiTextInput } from "../form/input/TextInput";
|
|
|
9
8
|
import { VuiNumberInput } from "../form/input/NumberInput";
|
|
10
9
|
import { VuiTextArea } from "../form/textArea/TextArea";
|
|
11
10
|
import { VuiSelect } from "../form/select/Select";
|
|
12
|
-
import {
|
|
11
|
+
import { VuiInlineFormGroup } from "./InlineFormGroup";
|
|
12
|
+
import { VuiBlockFormGroup } from "./BlockFormGroup";
|
|
13
13
|
const VALIDATION_ALLOWLIST = [VuiTextInput, VuiNumberInput, VuiTextArea, VuiSelect];
|
|
14
|
-
export const VuiFormGroup = ({ children, labelFor, helpText, label, labelSize = "s", labelRightContent, errors, isRequired }) => {
|
|
14
|
+
export const VuiFormGroup = ({ children, labelFor, helpText, label, labelSize = "s", labelRightContent, errors, isRequired, inline }) => {
|
|
15
15
|
const ariaProps = {
|
|
16
16
|
"aria-describedby": ""
|
|
17
17
|
};
|
|
@@ -20,7 +20,7 @@ export const VuiFormGroup = ({ children, labelFor, helpText, label, labelSize =
|
|
|
20
20
|
const errorMessages = errors === null || errors === void 0 ? void 0 : errors.map((error, index) => {
|
|
21
21
|
const id = `error-${createId()}`;
|
|
22
22
|
errorMessageIds.push(id);
|
|
23
|
-
return (_jsxs("div", { children: [index > 0 && _jsx(VuiSpacer, { size: "xs" }), _jsx(VuiText, Object.assign({ size: "xs", id: id }, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: "danger" }, { children: error })) }) }), error)] }, error));
|
|
23
|
+
return (_jsxs("div", { children: [index > 0 && _jsx(VuiSpacer, { size: "xs" }), _jsx(VuiText, Object.assign({ size: "xs", id: id }, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: inline ? "empty" : "danger" }, { children: error })) }) }), error)] }, error));
|
|
24
24
|
});
|
|
25
25
|
if (helpText) {
|
|
26
26
|
ariaProps["aria-describedby"] += ariaDescribedByLabel;
|
|
@@ -34,5 +34,19 @@ export const VuiFormGroup = ({ children, labelFor, helpText, label, labelSize =
|
|
|
34
34
|
cloneProps.isInvalid = errors && errors.length > 0;
|
|
35
35
|
}
|
|
36
36
|
const content = cloneElement(children, cloneProps);
|
|
37
|
-
|
|
37
|
+
const props = {
|
|
38
|
+
label,
|
|
39
|
+
labelRightContent,
|
|
40
|
+
labelFor,
|
|
41
|
+
labelSize,
|
|
42
|
+
isRequired,
|
|
43
|
+
helpText,
|
|
44
|
+
ariaDescribedByLabel,
|
|
45
|
+
errorMessages,
|
|
46
|
+
content
|
|
47
|
+
};
|
|
48
|
+
if (inline) {
|
|
49
|
+
return _jsx(VuiInlineFormGroup, Object.assign({}, props));
|
|
50
|
+
}
|
|
51
|
+
return _jsx(VuiBlockFormGroup, Object.assign({}, props));
|
|
38
52
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { VuiLabel } from "../form/label/Label";
|
|
3
|
+
import { VuiFlexContainer } from "../flex/FlexContainer";
|
|
4
|
+
import { VuiInfoTooltip } from "../tooltip/InfoTooltip";
|
|
5
|
+
import { BiError } from "react-icons/bi";
|
|
6
|
+
import classNames from "classnames";
|
|
7
|
+
import { VuiTextColor } from "../typography/TextColor";
|
|
8
|
+
export const VuiInlineFormGroup = ({ label, labelRightContent, labelFor, labelSize, isRequired, helpText, ariaDescribedByLabel, errorMessages, content }) => {
|
|
9
|
+
const hasErrors = errorMessages && errorMessages.length > 0;
|
|
10
|
+
const classes = classNames("vuiInlineFormGroup", {
|
|
11
|
+
"vuiInlineFormGroup-hasError": hasErrors
|
|
12
|
+
});
|
|
13
|
+
return (_jsxs(VuiFlexContainer, Object.assign({ className: classes, spacing: "none", alignItems: "stretch" }, { children: [(label || labelRightContent) && (_jsxs(VuiFlexContainer, Object.assign({ justifyContent: "spaceBetween", className: "vuiInlineFormGroup__label", alignItems: "center", spacing: "xs" }, { children: [label ? (_jsx(VuiLabel, Object.assign({ labelFor: labelFor, size: labelSize }, { children: _jsxs(VuiTextColor, Object.assign({ color: "subdued" }, { children: [label, isRequired && " (required)"] })) }))) : (_jsx("span", {})), labelRightContent, helpText && _jsx(VuiInfoTooltip, { tip: helpText, id: ariaDescribedByLabel }), hasErrors && _jsx(VuiInfoTooltip, { color: "danger", icon: _jsx(BiError, {}), tip: errorMessages })] }))), content] })));
|
|
14
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.vuiInlineFormGroup {
|
|
2
|
+
select,
|
|
3
|
+
input,
|
|
4
|
+
textarea {
|
|
5
|
+
border-top-left-radius: 0;
|
|
6
|
+
border-bottom-left-radius: 0;
|
|
7
|
+
border-left: none;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.vuiInlineFormGroup__label {
|
|
12
|
+
border-top-left-radius: $sizeXxs;
|
|
13
|
+
border-bottom-left-radius: $sizeXxs;
|
|
14
|
+
background-color: var(--vui-color-light-shade);
|
|
15
|
+
padding: 0 $sizeS;
|
|
16
|
+
border: 1px solid var(--vui-color-medium-shade);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.vuiInlineFormGroup-hasError {
|
|
20
|
+
.vuiInlineFormGroup__label {
|
|
21
|
+
border-top-color: var(--vui-color-danger-shade);
|
|
22
|
+
border-left-color: var(--vui-color-danger-shade);
|
|
23
|
+
border-bottom-color: var(--vui-color-danger-shade);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type FormGroupProps = {
|
|
2
|
+
label?: string;
|
|
3
|
+
labelRightContent: React.ReactNode;
|
|
4
|
+
labelFor?: string;
|
|
5
|
+
labelSize: "s" | "xs";
|
|
6
|
+
isRequired?: boolean;
|
|
7
|
+
helpText: React.ReactNode;
|
|
8
|
+
ariaDescribedByLabel: string;
|
|
9
|
+
errorMessages?: JSX.Element[];
|
|
10
|
+
content: React.ReactElement<any, string | React.JSXElementConstructor<any>>;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Props as TooltipProps } from "./Tooltip";
|
|
2
|
-
type Props = Omit<TooltipProps, "children"
|
|
2
|
+
type Props = Omit<TooltipProps, "children"> & {
|
|
3
|
+
color?: "danger" | "warning" | "success" | "subdued";
|
|
4
|
+
icon?: React.ReactNode;
|
|
5
|
+
};
|
|
3
6
|
export declare const VuiInfoTooltip: (props: Props) => import("react/jsx-runtime").JSX.Element;
|
|
4
7
|
export {};
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
1
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
13
|
import { BiHelpCircle } from "react-icons/bi";
|
|
3
14
|
import { VuiIcon } from "../icon/Icon";
|
|
4
15
|
import { VuiTooltip } from "./Tooltip";
|
|
5
16
|
export const VuiInfoTooltip = (props) => {
|
|
6
|
-
|
|
17
|
+
const { icon, color = "subdued" } = props, rest = __rest(props, ["icon", "color"]);
|
|
18
|
+
return (_jsx(VuiTooltip, Object.assign({}, rest, { children: _jsx(VuiIcon, Object.assign({ color: color, size: "s" }, { children: icon ? icon : _jsx(BiHelpCircle, {}) })) })));
|
|
7
19
|
};
|
|
@@ -5,5 +5,6 @@ export type Props = {
|
|
|
5
5
|
darkTheme?: boolean;
|
|
6
6
|
position?: TooltipRefProps["place"];
|
|
7
7
|
usePortal?: boolean;
|
|
8
|
+
id?: string;
|
|
8
9
|
};
|
|
9
|
-
export declare const VuiTooltip: ({ children, darkTheme, position, tip, usePortal }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export declare const VuiTooltip: ({ children, darkTheme, position, tip, usePortal, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
1
12
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
13
|
import { useState, cloneElement } from "react";
|
|
3
14
|
import { Tooltip } from "react-tooltip";
|
|
4
15
|
import { useVuiContext } from "../context/Context";
|
|
5
16
|
import { VuiPortal } from "../portal/Portal";
|
|
17
|
+
import { VuiText } from "../typography/Text";
|
|
18
|
+
import { VuiTextColor } from "../typography/TextColor";
|
|
6
19
|
const generateTooltipId = () => {
|
|
7
20
|
return `tooltip-${Math.random().toString(36).slice(2, 9)}`;
|
|
8
21
|
};
|
|
@@ -26,15 +39,17 @@ const needsTabIndex = (element) => {
|
|
|
26
39
|
}
|
|
27
40
|
return true;
|
|
28
41
|
};
|
|
29
|
-
export const VuiTooltip = (
|
|
42
|
+
export const VuiTooltip = (_a) => {
|
|
43
|
+
var { children, darkTheme, position, tip, usePortal } = _a, rest = __rest(_a, ["children", "darkTheme", "position", "tip", "usePortal"]);
|
|
30
44
|
const { getThemeStyle } = useVuiContext();
|
|
31
|
-
const [
|
|
32
|
-
const target = cloneElement(children, Object.assign({ "data-tooltip-id":
|
|
45
|
+
const [tooltipId] = useState(generateTooltipId());
|
|
46
|
+
const target = cloneElement(children, Object.assign(Object.assign({ "data-tooltip-id": tooltipId }, (needsTabIndex(children) && { tabIndex: 0 })), rest));
|
|
33
47
|
// Tooltips can be used in a dark-themed component, so we need to explicitly set
|
|
34
48
|
// the light theme class in order to enable having a different theme than the
|
|
35
49
|
// parent.
|
|
36
50
|
const style = getThemeStyle(darkTheme ? "dark" : "light");
|
|
37
|
-
const
|
|
51
|
+
const content = typeof tip === "string" ? (_jsx(VuiText, Object.assign({ size: "xs" }, { children: _jsx("p", { children: _jsx(VuiTextColor, Object.assign({ color: "empty" }, { children: tip })) }) }))) : (tip);
|
|
52
|
+
const tooltip = (_jsx(Tooltip, Object.assign({ id: tooltipId, offset: 10, className: "vuiTooltip", style: style, opacity: 1, place: position }, { children: content })));
|
|
38
53
|
return (_jsxs(_Fragment, { children: [target, usePortal ? _jsx(VuiPortal, { children: tooltip }) : tooltip] }));
|
|
39
54
|
};
|
|
40
55
|
// This is a workaround for the issue with ResizeObserver in ReactTooltip.
|
package/lib/styles/index.css
CHANGED
|
@@ -3051,6 +3051,28 @@ h2.react-datepicker__current-month {
|
|
|
3051
3051
|
max-height: 12rem;
|
|
3052
3052
|
}
|
|
3053
3053
|
|
|
3054
|
+
.vuiInlineFormGroup select,
|
|
3055
|
+
.vuiInlineFormGroup input,
|
|
3056
|
+
.vuiInlineFormGroup textarea {
|
|
3057
|
+
border-top-left-radius: 0;
|
|
3058
|
+
border-bottom-left-radius: 0;
|
|
3059
|
+
border-left: none;
|
|
3060
|
+
}
|
|
3061
|
+
|
|
3062
|
+
.vuiInlineFormGroup__label {
|
|
3063
|
+
border-top-left-radius: 4px;
|
|
3064
|
+
border-bottom-left-radius: 4px;
|
|
3065
|
+
background-color: var(--vui-color-light-shade);
|
|
3066
|
+
padding: 0 12px;
|
|
3067
|
+
border: 1px solid var(--vui-color-medium-shade);
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
.vuiInlineFormGroup-hasError .vuiInlineFormGroup__label {
|
|
3071
|
+
border-top-color: var(--vui-color-danger-shade);
|
|
3072
|
+
border-left-color: var(--vui-color-danger-shade);
|
|
3073
|
+
border-bottom-color: var(--vui-color-danger-shade);
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3054
3076
|
.vuiGridContainer {
|
|
3055
3077
|
container-type: inline-size;
|
|
3056
3078
|
width: 100%;
|
package/package.json
CHANGED
|
@@ -6,13 +6,16 @@ import {
|
|
|
6
6
|
VuiSpacer,
|
|
7
7
|
VuiSuperRadioGroup,
|
|
8
8
|
VuiTextArea,
|
|
9
|
-
VuiTextInput
|
|
9
|
+
VuiTextInput,
|
|
10
|
+
VuiToggle
|
|
10
11
|
} from "../../../lib";
|
|
11
12
|
import { Subsection } from "../../components/Subsection";
|
|
12
13
|
|
|
13
14
|
type Pizza = "pepperoni" | "mushrooms" | "jalapenos";
|
|
14
15
|
|
|
15
16
|
export const FormGroup = () => {
|
|
17
|
+
const [inline, setInline] = useState(false);
|
|
18
|
+
const [showError, setShowError] = useState(false);
|
|
16
19
|
const [group, setGroup] = useState<RadioButtonConfig<Pizza>[]>([
|
|
17
20
|
{
|
|
18
21
|
label: "Pepperoni",
|
|
@@ -45,11 +48,20 @@ export const FormGroup = () => {
|
|
|
45
48
|
|
|
46
49
|
return (
|
|
47
50
|
<>
|
|
51
|
+
<VuiToggle label="Show error message" onChange={(e) => setShowError(e.target.checked)} />
|
|
52
|
+
|
|
53
|
+
<VuiSpacer size="m" />
|
|
54
|
+
<VuiToggle label="Inline" onChange={(event) => setInline(event.target.checked)} checked={inline} />
|
|
55
|
+
|
|
56
|
+
<VuiSpacer size="m" />
|
|
57
|
+
|
|
48
58
|
<Subsection title="With help text">
|
|
49
59
|
<VuiFormGroup
|
|
50
60
|
label="Choose an option"
|
|
51
61
|
labelFor="optionsList1"
|
|
52
62
|
helpText="Some helpful information about this input."
|
|
63
|
+
inline={inline}
|
|
64
|
+
errors={showError ? ["This is an error message."] : []}
|
|
53
65
|
>
|
|
54
66
|
<VuiSelect
|
|
55
67
|
id="optionsList1"
|
|
@@ -61,25 +73,48 @@ export const FormGroup = () => {
|
|
|
61
73
|
|
|
62
74
|
<VuiSpacer size="m" />
|
|
63
75
|
|
|
64
|
-
<VuiFormGroup
|
|
76
|
+
<VuiFormGroup
|
|
77
|
+
label="Enter input"
|
|
78
|
+
labelFor="input1"
|
|
79
|
+
helpText="Some helpful information about this input."
|
|
80
|
+
inline={inline}
|
|
81
|
+
errors={showError ? ["This is an error message."] : []}
|
|
82
|
+
>
|
|
65
83
|
<VuiTextInput id="input1" value="Text input" onChange={(event) => console.log(event.target.value)} />
|
|
66
84
|
</VuiFormGroup>
|
|
67
85
|
|
|
68
86
|
<VuiSpacer size="m" />
|
|
69
87
|
|
|
70
|
-
<VuiFormGroup
|
|
88
|
+
<VuiFormGroup
|
|
89
|
+
label="Select option"
|
|
90
|
+
labelFor="superRadioGroup"
|
|
91
|
+
helpText="Choose wisely."
|
|
92
|
+
inline={inline}
|
|
93
|
+
errors={showError ? ["This is an error message."] : []}
|
|
94
|
+
>
|
|
71
95
|
<VuiSuperRadioGroup groupName="superRadioGroup" group={group} onChange={onChange} />
|
|
72
96
|
</VuiFormGroup>
|
|
73
97
|
|
|
74
98
|
<VuiSpacer size="m" />
|
|
75
99
|
|
|
76
|
-
<VuiFormGroup
|
|
100
|
+
<VuiFormGroup
|
|
101
|
+
label="Enter text"
|
|
102
|
+
labelFor="textArea"
|
|
103
|
+
helpText="Enter some text here."
|
|
104
|
+
inline={inline}
|
|
105
|
+
errors={showError ? ["This is an error message."] : []}
|
|
106
|
+
>
|
|
77
107
|
<VuiTextArea id="textArea" value="Text area" onChange={() => undefined} />
|
|
78
108
|
</VuiFormGroup>
|
|
79
109
|
</Subsection>
|
|
80
110
|
|
|
81
111
|
<Subsection title="Without help text">
|
|
82
|
-
<VuiFormGroup
|
|
112
|
+
<VuiFormGroup
|
|
113
|
+
label="Choose an option"
|
|
114
|
+
labelFor="optionsList2"
|
|
115
|
+
inline={inline}
|
|
116
|
+
errors={showError ? ["This is an error message."] : []}
|
|
117
|
+
>
|
|
83
118
|
<VuiSelect
|
|
84
119
|
id="optionsList2"
|
|
85
120
|
options={[{ text: "Option A", value: "a" }]}
|