mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
239 lines
5.9 KiB
TypeScript
239 lines
5.9 KiB
TypeScript
import React from "react";
|
|
import {ComponentStory, ComponentMeta} from "@storybook/react";
|
|
import {checkbox, colors} from "@nextui-org/theme";
|
|
import {CheckIcon, CloseIcon} from "@nextui-org/shared-icons";
|
|
import {User} from "@nextui-org/user";
|
|
import {Link} from "@nextui-org/link";
|
|
import {Chip, ChipProps} from "@nextui-org/chip";
|
|
import {clsx} from "@nextui-org/shared-utils";
|
|
import {VisuallyHidden} from "@react-aria/visually-hidden";
|
|
|
|
import {
|
|
Checkbox,
|
|
CheckboxIconProps,
|
|
CheckboxProps,
|
|
useCheckbox,
|
|
useCheckboxGroupContext,
|
|
} from "../src";
|
|
|
|
export default {
|
|
title: "Inputs/Checkbox",
|
|
component: Checkbox,
|
|
argTypes: {
|
|
color: {
|
|
control: {
|
|
type: "select",
|
|
options: ["neutral", "primary", "secondary", "success", "warning", "danger"],
|
|
},
|
|
},
|
|
radius: {
|
|
control: {
|
|
type: "select",
|
|
options: ["none", "base", "sm", "md", "lg", "xl", "full"],
|
|
},
|
|
},
|
|
size: {
|
|
control: {
|
|
type: "select",
|
|
options: ["xs", "sm", "md", "lg", "xl"],
|
|
},
|
|
},
|
|
lineThrough: {
|
|
control: {
|
|
type: "boolean",
|
|
},
|
|
},
|
|
isDisabled: {
|
|
control: {
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
} as ComponentMeta<typeof Checkbox>;
|
|
|
|
const defaultProps: CheckboxProps = {
|
|
...checkbox.defaultVariants,
|
|
children: "Option",
|
|
};
|
|
|
|
const Template: ComponentStory<typeof Checkbox> = (args: CheckboxProps) => <Checkbox {...args} />;
|
|
|
|
export const Default = Template.bind({});
|
|
Default.args = {
|
|
...defaultProps,
|
|
};
|
|
|
|
export const IsDisabled = Template.bind({});
|
|
IsDisabled.args = {
|
|
...defaultProps,
|
|
isDisabled: true,
|
|
};
|
|
|
|
export const DefaultSelected = Template.bind({});
|
|
DefaultSelected.args = {
|
|
...defaultProps,
|
|
defaultSelected: true,
|
|
};
|
|
|
|
export const CustomIconNode = Template.bind({});
|
|
CustomIconNode.args = {
|
|
...defaultProps,
|
|
icon: <CloseIcon />,
|
|
};
|
|
|
|
export const CustomIconFunction = Template.bind({});
|
|
CustomIconFunction.args = {
|
|
...defaultProps,
|
|
icon: (props: CheckboxIconProps) => <CloseIcon {...props} />,
|
|
};
|
|
|
|
export const AlwaysSelected = Template.bind({});
|
|
AlwaysSelected.args = {
|
|
...defaultProps,
|
|
isSelected: true,
|
|
};
|
|
|
|
export const IsIndeterminate = Template.bind({});
|
|
IsIndeterminate.args = {
|
|
...defaultProps,
|
|
isIndeterminate: true,
|
|
};
|
|
|
|
export const LineThrough = Template.bind({});
|
|
LineThrough.args = {
|
|
...defaultProps,
|
|
lineThrough: true,
|
|
};
|
|
|
|
export const DisableAnimation = Template.bind({});
|
|
DisableAnimation.args = {
|
|
...defaultProps,
|
|
disableAnimation: true,
|
|
};
|
|
|
|
export const Controlled = () => {
|
|
const [selected, setSelected] = React.useState<boolean>(true);
|
|
|
|
React.useEffect(() => {
|
|
// eslint-disable-next-line no-console
|
|
console.log("Checkbox ", selected);
|
|
}, [selected]);
|
|
|
|
return (
|
|
<div className="flex flex-row gap-2">
|
|
<Checkbox isSelected={selected} onChange={setSelected} {...checkbox.defaultVariants}>
|
|
Subscribe (controlled)
|
|
</Checkbox>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
interface CustomCheckboxProps extends CheckboxProps {
|
|
userName?: string;
|
|
userProfile?: {
|
|
username?: string;
|
|
avatar?: string;
|
|
url?: string;
|
|
};
|
|
userRole?: string;
|
|
status?: string;
|
|
statusColor?: ChipProps["color"];
|
|
}
|
|
|
|
export const CustomWithStyles = (props: CustomCheckboxProps) => {
|
|
const {
|
|
value,
|
|
userName = "Junior Garcia",
|
|
userProfile = {
|
|
avatar: "https://avatars.githubusercontent.com/u/30373425?v=4",
|
|
username: "jrgarciadev",
|
|
url: "https://twitter.com/jrgarciadev",
|
|
},
|
|
userRole = "Software Developer",
|
|
status = "Active",
|
|
statusColor = "secondary",
|
|
...otherProps
|
|
} = props;
|
|
|
|
const groupContext = useCheckboxGroupContext();
|
|
const isInGroup = !!groupContext;
|
|
|
|
const [isSelected, setIsSelected] = React.useState<boolean>(false);
|
|
|
|
const checkboxProps = !isInGroup
|
|
? {
|
|
isSelected,
|
|
onChange: setIsSelected,
|
|
}
|
|
: {};
|
|
|
|
const isChecked = isInGroup && value ? groupContext?.groupState.isSelected(value) : isSelected;
|
|
|
|
return (
|
|
<Checkbox
|
|
{...otherProps}
|
|
aria-label={userName}
|
|
styles={{
|
|
base: clsx(
|
|
"inline-flex w-full max-w-md bg-content1 hover:bg-content2 items-center justify-start cursor-pointer rounded-lg gap-2 p-4 border-2 border-transparent",
|
|
{
|
|
"border-primary": isChecked,
|
|
},
|
|
),
|
|
label: "w-full",
|
|
}}
|
|
value={value}
|
|
{...checkboxProps}
|
|
>
|
|
<div className="w-full flex justify-between gap-2">
|
|
<User
|
|
avatarProps={{size: "sm", src: userProfile.avatar}}
|
|
description={
|
|
<Link href={userProfile.url} size="xs">
|
|
@{userProfile.username}
|
|
</Link>
|
|
}
|
|
name={userName}
|
|
/>
|
|
<div className="flex flex-col items-end gap-1">
|
|
<span className="text-xs text-neutral-500">{userRole}</span>
|
|
<Chip color={statusColor} size="xs" variant="flat">
|
|
{status}
|
|
</Chip>
|
|
</div>
|
|
</div>
|
|
</Checkbox>
|
|
);
|
|
};
|
|
|
|
export const CustomWithHooks = (props: CheckboxProps) => {
|
|
const {children, isSelected, getBaseProps, getLabelProps, getInputProps} = useCheckbox({
|
|
"aria-label": props["aria-label"] || "Toggle status",
|
|
...props,
|
|
});
|
|
|
|
return (
|
|
<label {...getBaseProps()}>
|
|
<VisuallyHidden>
|
|
<input {...getInputProps()} />
|
|
</VisuallyHidden>
|
|
<Chip
|
|
color="primary"
|
|
leftContent={isSelected ? <CheckIcon className="ml-1" color={colors.white} /> : null}
|
|
styles={{
|
|
base: clsx("border-neutral hover:bg-neutral-200", {
|
|
"border-primary bg-primary hover:bg-primary-600 hover:border-primary-600": isSelected,
|
|
}),
|
|
content: clsx("text-primary", {
|
|
"text-primary-contrastText pl-1": isSelected,
|
|
}),
|
|
}}
|
|
variant="faded"
|
|
{...getLabelProps()}
|
|
>
|
|
{children ? children : isSelected ? "Enabled" : "Disabled"}
|
|
</Chip>
|
|
</label>
|
|
);
|
|
};
|