Skip to content
Snippets Groups Projects
Commit daa99f66 authored by Alissa Cheng's avatar Alissa Cheng
Browse files

Merge branch 'SDC-1158/form-components-usability' into 'main'

form components

Closes SDC-1158

See merge request !17
parents c8adb4a4 16b951d0
No related branches found
No related tags found
1 merge request!17form components
Pipeline #67118 passed
Showing with 235 additions and 74 deletions
...@@ -2,13 +2,15 @@ import { Button as NextButton } from "@nextui-org/react"; ...@@ -2,13 +2,15 @@ import { Button as NextButton } from "@nextui-org/react";
import Icon, { IconName } from "./Icon.tsx"; import Icon, { IconName } from "./Icon.tsx";
import Typography from "./Typography.tsx"; import Typography from "./Typography.tsx";
import { bgColor, Color } from "./utils/colors.ts"; import { bgColor, Color } from "./utils/colors.ts";
import { disabledCursor } from "./utils/classes.ts";
export type ButtonProps = { export type ButtonProps = {
label?: string | null; label?: string | null;
color?: Color; color?: Color;
disabled?: boolean;
icon?: IconName | null; icon?: IconName | null;
iconClass?: string; iconClass?: string;
isDisabled?: boolean;
type?: "button" | "submit";
onClick?: () => void; onClick?: () => void;
}; };
...@@ -18,14 +20,15 @@ export type ButtonProps = { ...@@ -18,14 +20,15 @@ export type ButtonProps = {
* @param label: string * @param label: string
* @param color: Color string * @param color: Color string
* @param icon: null | IconName * @param icon: null | IconName
* @param enabled: boolean * @param disabled: boolean
*/ */
const Button = ({ const Button = ({
label = null, label = null,
color = "primary", color = "primary",
icon = null, icon = null,
iconClass, iconClass,
disabled = false, isDisabled = false,
type = "button",
onClick = () => {}, onClick = () => {},
}: ButtonProps) => { }: ButtonProps) => {
if (!label && !icon) throw Error("Button cannot be empty"); if (!label && !icon) throw Error("Button cannot be empty");
...@@ -35,15 +38,22 @@ const Button = ({ ...@@ -35,15 +38,22 @@ const Button = ({
else if (icon) return "px-[9px] "; else if (icon) return "px-[9px] ";
else if (label) return "px-[10px] "; else if (label) return "px-[10px] ";
}; };
const bgClass = disabled const bgClass = (isDisabled: boolean) => {
? "bg-lightGrey cursor-not-allowed opacity-100" if (!isDisabled) return bgColor(color) + " ";
: bgColor(color); return "bg-lightGrey ";
};
return ( return (
<NextButton <NextButton
startContent={icon && <Icon name={icon} customClass={iconClass} />} startContent={icon && <Icon name={icon} customClass={iconClass} />}
className={`${px()} ${bgClass} pointer-events-auto h-[32px] min-w-fit py-[5px] text-baseWhite rounded-[4px] flex`} className={
isDisabled={disabled} px() +
bgClass(isDisabled) +
disabledCursor(isDisabled) +
" h-[32px] min-w-fit max-w-fit py-[5px] text-baseWhite rounded-[4px] flex focus:!outline-0"
}
isDisabled={isDisabled}
type={type}
onClick={onClick} onClick={onClick}
> >
{label && ( {label && (
......
import { Checkbox as NextCheckbox } from "@nextui-org/react"; import { Checkbox as NextCheckbox } from "@nextui-org/react";
import { Dispatch, SetStateAction } from "react"; import { Dispatch, SetStateAction } from "react";
import Icon from "./Icon.tsx"; import Icon from "./Icon.tsx";
import { disabledBg, disabledCursor } from "./utils/classes.ts";
type CheckboxProps = { type CheckboxProps = {
isDisabled?: boolean;
isRequired?: boolean;
isSelected: boolean; isSelected: boolean;
setIsSelected: Dispatch<SetStateAction<boolean>>; setIsSelected?: Dispatch<SetStateAction<boolean>>;
label?: string; label?: string;
}; };
const Checkbox = ({ isSelected, setIsSelected, label }: CheckboxProps) => { const Checkbox = ({
isDisabled = false,
isRequired = false,
isSelected,
setIsSelected,
label,
}: CheckboxProps) => {
return ( return (
<NextCheckbox <NextCheckbox
isRequired={isRequired}
isDisabled={isDisabled}
isSelected={isSelected} isSelected={isSelected}
onValueChange={setIsSelected} onValueChange={setIsSelected}
icon={isSelected ? <Icon name="checkmark" color="body" /> : <></>} icon={isSelected ? <Icon name="checkmark" color="body" /> : <></>}
...@@ -19,8 +30,11 @@ const Checkbox = ({ isSelected, setIsSelected, label }: CheckboxProps) => { ...@@ -19,8 +30,11 @@ const Checkbox = ({ isSelected, setIsSelected, label }: CheckboxProps) => {
color="default" color="default"
disableAnimation disableAnimation
classNames={{ classNames={{
base: disabledCursor(isDisabled),
wrapper: wrapper:
"w-[24px] h-[24px] border-[1px] border-grey rounded-[4px] dark:bg-mediumGrey dark:border-mediumGrey", "w-[24px] h-[24px] rounded-[4px] " +
"border-[1px] border-grey dark:border-none " +
disabledBg(isDisabled),
}} }}
> >
{label} {label}
......
...@@ -8,22 +8,33 @@ import Typography from "./Typography.tsx"; ...@@ -8,22 +8,33 @@ import Typography from "./Typography.tsx";
import { textColor } from "./utils/colors.ts"; import { textColor } from "./utils/colors.ts";
type DateInputProps = { type DateInputProps = {
label?: string; isRequired?: boolean;
label: string;
value?: Date; value?: Date;
onValueChange: Dispatch<SetStateAction<Date | undefined>>; onValueChange: Dispatch<SetStateAction<Date | undefined>>;
isInvalid?: boolean;
errorMessage?: string;
}; };
const DateInput = ({ label, value, onValueChange }: DateInputProps) => { const DateInput = ({
isRequired = false,
label,
value,
onValueChange,
isInvalid = false,
errorMessage = "",
}: DateInputProps) => {
const dateFormat = "dd/MM/yyyy"; const dateFormat = "dd/MM/yyyy";
type inputProps = { type inputProps = {
isRequired: boolean;
value?: string; value?: string;
onClick?: () => void; onClick?: () => void;
}; };
const CustomInput = forwardRef( const CustomInput = forwardRef(
( (
{ value, onClick }: inputProps, { isRequired, value, onClick }: inputProps,
// @ts-expect-error the "ref" prop is needed to avoid console errors. // @ts-expect-error the "ref" prop is needed to avoid console errors.
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
ref ref
...@@ -31,6 +42,7 @@ const DateInput = ({ label, value, onValueChange }: DateInputProps) => { ...@@ -31,6 +42,7 @@ const DateInput = ({ label, value, onValueChange }: DateInputProps) => {
return ( return (
<div onClick={onClick}> <div onClick={onClick}>
<BaseInput <BaseInput
isRequired={isRequired}
label={label} label={label}
endContent={ endContent={
<Icon <Icon
...@@ -41,6 +53,8 @@ const DateInput = ({ label, value, onValueChange }: DateInputProps) => { ...@@ -41,6 +53,8 @@ const DateInput = ({ label, value, onValueChange }: DateInputProps) => {
placeholder="DD/MM/YYYY" placeholder="DD/MM/YYYY"
value={value} value={value}
onValueChange={() => {}} onValueChange={() => {}}
isInvalid={isInvalid}
errorMessage={errorMessage}
/> />
</div> </div>
); );
...@@ -77,11 +91,11 @@ const DateInput = ({ label, value, onValueChange }: DateInputProps) => { ...@@ -77,11 +91,11 @@ const DateInput = ({ label, value, onValueChange }: DateInputProps) => {
return ( return (
<DatePicker <DatePicker
dateFormat={dateFormat} dateFormat={dateFormat}
openToDate={new Date()} openToDate={value || new Date()}
selected={value} selected={value}
onSelect={(date) => onValueChange(date)} onSelect={(date) => onValueChange(date)}
onChange={(date) => !!date && onValueChange(date)} onChange={(date) => !!date && onValueChange(date)}
customInput={<CustomInput />} customInput={<CustomInput isRequired={isRequired} />}
showPopperArrow={false} showPopperArrow={false}
calendarStartDay={1} calendarStartDay={1}
formatWeekDay={(day) => <div>{day.charAt(0)}</div>} formatWeekDay={(day) => <div>{day.charAt(0)}</div>}
......
...@@ -4,6 +4,7 @@ import { baseInputClassNames } from "./utils/baseComponents.tsx"; ...@@ -4,6 +4,7 @@ import { baseInputClassNames } from "./utils/baseComponents.tsx";
import Icon from "./Icon.tsx"; import Icon from "./Icon.tsx";
type DropdownProps = { type DropdownProps = {
isRequired?: boolean;
label?: string; label?: string;
valueOptions: { value: string; label: string }[]; valueOptions: { value: string; label: string }[];
value?: string; value?: string;
...@@ -11,6 +12,7 @@ type DropdownProps = { ...@@ -11,6 +12,7 @@ type DropdownProps = {
}; };
const Dropdown = ({ const Dropdown = ({
isRequired = false,
label, label,
valueOptions, valueOptions,
value, value,
...@@ -18,6 +20,7 @@ const Dropdown = ({ ...@@ -18,6 +20,7 @@ const Dropdown = ({
}: DropdownProps) => { }: DropdownProps) => {
return ( return (
<Autocomplete <Autocomplete
isRequired={isRequired}
label={label} label={label}
selectedKey={value} selectedKey={value}
onSelectionChange={(key) => onValueChange(key as string)} onSelectionChange={(key) => onValueChange(key as string)}
...@@ -25,8 +28,11 @@ const Dropdown = ({ ...@@ -25,8 +28,11 @@ const Dropdown = ({
placeholder=" " // so the label stays outside placeholder=" " // so the label stays outside
disableAnimation disableAnimation
disableSelectorIconRotation disableSelectorIconRotation
variant="bordered" inputProps={{
inputProps={{ classNames: baseInputClassNames }} // use the same props as BaseInput classNames: baseInputClassNames(false),
variant: "bordered",
isRequired: isRequired,
}} // use the same props as BaseInput
selectorIcon={<Icon name="dropdown" />} selectorIcon={<Icon name="dropdown" />}
isClearable={false} // so the "cross" button does not show isClearable={false} // so the "cross" button does not show
classNames={{ classNames={{
......
import { RadioGroup, Radio as NextRadio } from "@nextui-org/react"; import { RadioGroup, Radio as NextRadio } from "@nextui-org/react";
import { Dispatch, SetStateAction } from "react"; import { Dispatch, SetStateAction } from "react";
import { disabledBg, disabledCursor } from "./utils/classes.ts";
type RadioProps = { type RadioProps = {
size?: "small" | "big"; isRequired?: boolean;
label?: string; label?: string;
valueOptions: { value: string; label: string }[]; valueOptions: { value: string; label: string; isDisabled?: boolean }[];
value?: string; value?: string;
onValueChange: Dispatch<SetStateAction<string | undefined>>; onValueChange?: Dispatch<SetStateAction<string | undefined>>;
}; };
const Radio = ({ const Radio = ({
size = "small", isRequired = false,
label, label,
valueOptions, valueOptions,
value, value,
onValueChange, onValueChange,
}: RadioProps) => { }: RadioProps) => {
const sizeClass = {
small: { wrapper: "w-[16px] h-[16px]", control: "w-[10px] h-[10px]" },
big: { wrapper: "w-[24px] h-[24px]", control: "w-[14px] h-[14px]" },
};
return ( return (
<RadioGroup label={label} value={value} onValueChange={onValueChange}> <RadioGroup
isRequired={isRequired}
label={label}
value={value}
onValueChange={onValueChange}
>
{valueOptions.map((option) => ( {valueOptions.map((option) => (
<NextRadio <NextRadio
isDisabled={option.isDisabled || false}
key={option.value} key={option.value}
value={option.value} value={option.value}
disableAnimation disableAnimation
classNames={{ classNames={{
wrapper: `${sizeClass[size].wrapper} bg-lightGrey group-data-[selected=true]:border-none`, base: disabledCursor(option.isDisabled || false),
control: sizeClass[size].control, wrapper:
"w-[16px] h-[16px] border-[1px] !border-grey dark:border-none " +
disabledBg(option.isDisabled || false),
control: "w-[10px] h-[10px]",
}} }}
> >
{option.label} {option.label}
......
...@@ -2,16 +2,19 @@ import { Dispatch, ReactNode, SetStateAction } from "react"; ...@@ -2,16 +2,19 @@ import { Dispatch, ReactNode, SetStateAction } from "react";
import { BaseInput } from "./utils/baseComponents.tsx"; import { BaseInput } from "./utils/baseComponents.tsx";
type TextInputProps = { type TextInputProps = {
isRequired?: boolean;
label?: string; label?: string;
endContent?: ReactNode; // such as units (as text element e.g. <span>) endContent?: ReactNode; // such as units (as text element e.g. <span>)
isClearable?: boolean; isClearable?: boolean;
value: string; value: string;
onValueChange: Dispatch<SetStateAction<string>>; onValueChange?: Dispatch<SetStateAction<string>>;
isInvalid?: boolean; isInvalid?: boolean;
errorMessage?: string; errorMessage?: string;
isDisabled?: boolean;
}; };
const TextInput = ({ const TextInput = ({
isRequired = false,
label = "", label = "",
endContent, endContent,
isClearable = false, isClearable = false,
...@@ -19,9 +22,11 @@ const TextInput = ({ ...@@ -19,9 +22,11 @@ const TextInput = ({
onValueChange, onValueChange,
isInvalid = false, isInvalid = false,
errorMessage = "", errorMessage = "",
isDisabled = false,
}: TextInputProps) => { }: TextInputProps) => {
return ( return (
<BaseInput <BaseInput
isRequired={isRequired}
label={label} label={label}
endContent={endContent} endContent={endContent}
placeholder=" " placeholder=" "
...@@ -30,6 +35,7 @@ const TextInput = ({ ...@@ -30,6 +35,7 @@ const TextInput = ({
onValueChange={onValueChange} onValueChange={onValueChange}
isInvalid={isInvalid} isInvalid={isInvalid}
errorMessage={errorMessage} errorMessage={errorMessage}
isDisabled={isDisabled}
/> />
); );
}; };
......
import { Dispatch, SetStateAction } from "react"; import { Dispatch, SetStateAction } from "react";
import { Switch } from "@nextui-org/react"; import { Switch } from "@nextui-org/react";
import { disabledCursor } from "./utils/classes.ts";
type ToggleProps = { type ToggleProps = {
isDisabled?: boolean;
isSelected: boolean; isSelected: boolean;
setIsSelected: Dispatch<SetStateAction<boolean>>; setIsSelected?: Dispatch<SetStateAction<boolean>>;
label?: string; label?: string;
}; };
const Toggle = ({ isSelected, setIsSelected, label }: ToggleProps) => { const Toggle = ({
isDisabled = false,
isSelected,
setIsSelected,
label,
}: ToggleProps) => {
const selectedClass = isSelected const selectedClass = isSelected
? "group-data-[selected=true]:ml-[11px] bg-primary" ? "group-data-[selected=true]:ml-[11px] bg-primary"
: "bg-grey"; : "bg-grey";
return ( return (
<Switch <Switch
isDisabled={isDisabled}
// Does not support "isRequired": https://github.com/nextui-org/nextui/issues/1610
isSelected={isSelected} isSelected={isSelected}
onValueChange={setIsSelected} onValueChange={setIsSelected}
color="secondary" color="secondary"
classNames={{ classNames={{
base: disabledCursor(isDisabled),
thumb: `h-[14px] w-[14px] ${selectedClass}`, thumb: `h-[14px] w-[14px] ${selectedClass}`,
wrapper: wrapper:
"h-[8px] w-[25px] p-0 overflow-visible bg-lightGrey dark:bg-mediumGrey", "h-[8px] w-[25px] p-0 overflow-visible bg-lightGrey dark:bg-mediumGrey",
......
import { Input } from "@nextui-org/react"; import { Input } from "@nextui-org/react";
import { Dispatch, ReactNode, SetStateAction } from "react"; import { Dispatch, ReactNode, SetStateAction } from "react";
import { InputSlots } from "@nextui-org/theme";
import { disabledBg, disabledCursor } from "./classes.ts";
type BaseInputProps = { type BaseInputProps = {
// basic info // basic info
...@@ -7,26 +9,46 @@ type BaseInputProps = { ...@@ -7,26 +9,46 @@ type BaseInputProps = {
endContent: ReactNode; // such as units or icon endContent: ReactNode; // such as units or icon
// value and validation // value and validation
placeholder: string; placeholder: string;
isClearable: boolean; isClearable?: boolean;
value: string; value?: string;
onValueChange: Dispatch<SetStateAction<string>>; onValueChange?: Dispatch<SetStateAction<string>>;
isInvalid: boolean; isInvalid: boolean;
errorMessage: string; errorMessage: string;
// interaction
isRequired?: boolean;
isDisabled?: boolean;
}; };
type baseInputClassNamesObj = { [key in InputSlots]: string };
export const baseInputClassNames = (isDisabled: boolean) => {
// No we cannot do "[&>svg]:" + className because Tailwind does not support dynamic class names // No we cannot do "[&>svg]:" + className because Tailwind does not support dynamic class names
const clearButtonSvgClass = const clearButtonSvgClass =
"[&>svg]:w-[42px] [&>svg]:h-[42px] [&>svg]:mt-[-6px] [&>svg]:ml-[-5px]"; "[&>svg]:w-[42px] [&>svg]:h-[42px] [&>svg]:mt-[-6px] [&>svg]:ml-[-5px]";
export const baseInputClassNames = { const baseClass = {
base: disabledCursor(isDisabled),
label: "!text-foreground-body", label: "!text-foreground-body",
mainWrapper: "text-grey dark:text-mediumGrey",
inputWrapper: "bg-baseWhite dark:bg-mediumGrey rounded-[4px] px-2",
input: "!text-foreground-body bg-default", input: "!text-foreground-body bg-default",
inputWrapper: "px-2 rounded-[4px] " + disabledBg(isDisabled),
};
const defaultClass = {
...baseClass,
mainWrapper:
"text-grey dark:text-mediumGrey hover:text-baseBlack focus-within:!text-primary", // this is the border color (use text-*)
clearButton: clearButton:
clearButtonSvgClass + clearButtonSvgClass +
" " + " " +
"bg-mediumGrey text-baseWhite dark:bg-baseWhite dark:text-mediumGrey w-[30px] h-[30px] p-0 !opacity-100", "bg-mediumGrey text-baseWhite dark:bg-baseWhite dark:text-mediumGrey w-[30px] h-[30px] p-0 !opacity-100",
} as baseInputClassNamesObj;
const disabledClass = {
...baseClass,
mainWrapper: "text-mediumGrey dark:text-darkModeBlue",
} as baseInputClassNamesObj;
return isDisabled ? disabledClass : defaultClass;
}; };
export const BaseInput = ({ export const BaseInput = ({
...@@ -38,6 +60,8 @@ export const BaseInput = ({ ...@@ -38,6 +60,8 @@ export const BaseInput = ({
onValueChange, onValueChange,
isInvalid, isInvalid,
errorMessage, errorMessage,
isRequired = false,
isDisabled = false,
}: BaseInputProps) => { }: BaseInputProps) => {
return ( return (
<Input <Input
...@@ -50,10 +74,12 @@ export const BaseInput = ({ ...@@ -50,10 +74,12 @@ export const BaseInput = ({
onValueChange={onValueChange} onValueChange={onValueChange}
isInvalid={isInvalid} isInvalid={isInvalid}
errorMessage={errorMessage} errorMessage={errorMessage}
isRequired={isRequired}
isDisabled={isDisabled}
// appearance // appearance
labelPlacement="outside" labelPlacement="outside"
variant="bordered" variant="bordered"
classNames={baseInputClassNames} classNames={baseInputClassNames(isDisabled)}
/> />
); );
}; };
export const disabledCursor = (isDisabled: boolean) => {
if (!isDisabled) return "";
return "pointer-events-auto cursor-not-allowed opacity-50";
};
export const disabledBg = (isDisabled: boolean) => {
if (!isDisabled) return "bg-baseWhite dark:bg-mediumGrey";
return "bg-lightGrey dark:bg-darkModeBlue";
};
import { Meta, StoryObj } from "@storybook/react"; import { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
import Button from "src/components/Button.tsx"; import Button from "src/components/Button.tsx";
import { iconNameOptions } from "src/components/Icon.tsx"; import { iconNameOptions } from "src/components/Icon.tsx";
import { colorOptions } from "src/components/utils/colors.ts"; import { colorOptions } from "src/components/utils/colors.ts";
import Typography from "src/components/Typography.tsx";
import TextInput from "src/components/TextInput.tsx";
/** Use buttons as triggers for actions that are used in forms, toolbars, dialog footers and as stand-alone action triggers. Try to avoid the usage of buttons for navigation. The main difference between actions and navigation is that Actions are operations performed on objects, while Navigation refers to elements on the screen or view that take you to another context in the application. */ /** Use buttons as triggers for actions that are used in forms, toolbars, dialog footers and as stand-alone action triggers. Try to avoid the usage of buttons for navigation. The main difference between actions and navigation is that Actions are operations performed on objects, while Navigation refers to elements on the screen or view that take you to another context in the application. */
const meta = { const meta = {
...@@ -36,6 +39,32 @@ export const IconButton: StoryObj = { ...@@ -36,6 +39,32 @@ export const IconButton: StoryObj = {
export const DisabledButton: StoryObj = { export const DisabledButton: StoryObj = {
args: { args: {
label: "You can't click me!", label: "You can't click me!",
disabled: true, isDisabled: true,
}, },
}; };
/** In order for the Button to listen for Enter keypress, mostly used for submitting forms. Provide `type="submit"` to the Button component, and wrap it in a `<form>` element. For the native form element, you might also want to use an `onSubmit` with `preventDefault` and `stopPropagation` so the page does not reload. But there are also form libraries that take care of that. */
export const SubmitButton = () => {
const [value, setValue] = useState("");
const [count, setCount] = useState(0);
return (
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
className="max-w-md flex flex-col gap-2"
>
<TextInput value={value} onValueChange={setValue} />
<Button
label="Submit"
type="submit"
onClick={() => setCount(count + 1)}
/>
<Typography
text={`You have submitted ${count} times!`}
variant="paragraph"
/>
</form>
);
};
...@@ -19,3 +19,20 @@ export const SimpleCheckbox = () => { ...@@ -19,3 +19,20 @@ export const SimpleCheckbox = () => {
/> />
); );
}; };
export const DisabledCheckbox = () => {
return (
<div className="flex flex-col gap-4">
<Checkbox
isDisabled={true}
isSelected={true}
label="I am always right!"
/>
<Checkbox
isDisabled={true}
isSelected={false}
label="I am always wrong :("
/>
</div>
);
};
...@@ -10,21 +10,19 @@ const meta = { ...@@ -10,21 +10,19 @@ const meta = {
export default meta; export default meta;
export const SimpleRadio = () => {
const [value, setValue] = useState<string>();
const valueOptions = [ const valueOptions = [
{ value: "vanilla", label: "Vanilla" }, { value: "vanilla", label: "Vanilla" },
{ value: "mocha", label: "Mocha" }, { value: "mocha", label: "Mocha" },
{ value: "mint", label: "Mint" }, { value: "mint", label: "Mint" },
{ value: "raspberry", label: "Raspberry" }, { value: "raspberry", label: "Raspberry" },
{ value: "apple", label: "Apple" },
]; ];
export const SmallRadio = () => {
const [value, setValue] = useState<string>();
return ( return (
<> <>
<Radio <Radio
size="small"
label="What's your favourite ice cream?" label="What's your favourite ice cream?"
valueOptions={valueOptions} valueOptions={valueOptions}
onValueChange={setValue} onValueChange={setValue}
...@@ -37,20 +35,18 @@ export const SmallRadio = () => { ...@@ -37,20 +35,18 @@ export const SmallRadio = () => {
); );
}; };
export const BigRadio = () => { export const DisabledRadio = () => {
const [value, setValue] = useState<string>(); const valueOptions = [
{ value: "mint", label: "Mint", isDisabled: true },
{ value: "raspberry", label: "Raspberry", isDisabled: true },
];
return ( return (
<> <>
<Radio <Radio
size="big" label="Your favourite ice cream must be raspberry"
label="What's your favourite ice cream?"
valueOptions={valueOptions} valueOptions={valueOptions}
onValueChange={setValue} value="raspberry"
/>
<Typography
text={`You selected: ${value || "nothing"}`}
variant="paragraph"
/> />
</> </>
); );
......
...@@ -43,3 +43,13 @@ export const IsClearable = () => { ...@@ -43,3 +43,13 @@ export const IsClearable = () => {
/> />
); );
}; };
export const Disabled = () => {
return (
<TextInput
label="You can't change this!"
isDisabled={true}
value="*Evil laughter*"
/>
);
};
...@@ -19,3 +19,12 @@ export const SimpleToggle = () => { ...@@ -19,3 +19,12 @@ export const SimpleToggle = () => {
/> />
); );
}; };
export const DisabledToggle = () => {
return (
<div className="flex flex-col gap-4">
<Toggle isDisabled={true} isSelected={true} label="I'm always right!" />
<Toggle isDisabled={true} isSelected={false} label="I'm always left!" />
</div>
);
};
...@@ -61,7 +61,7 @@ export default { ...@@ -61,7 +61,7 @@ export default {
}, },
dark: { dark: {
colors: { colors: {
background: palette.darkModeBlue, background: palette.darkBlue,
foreground: { foreground: {
heading: palette.baseWhite, heading: palette.baseWhite,
heading2: palette.lightBlue, heading2: palette.lightBlue,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment