Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(docs): checkbox-group dx #4027

Merged
merged 1 commit into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions apps/docs/content/components/checkbox-group/controlled.raw.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {CheckboxGroup, Checkbox} from "@nextui-org/react";

export default function App() {
const [selected, setSelected] = React.useState(["buenos-aires", "sydney"]);

return (
<div className="flex flex-col gap-3">
<CheckboxGroup
color="warning"
label="Select cities"
value={selected}
onValueChange={setSelected}
>
<Checkbox value="buenos-aires">Buenos Aires</Checkbox>
<Checkbox value="sydney">Sydney</Checkbox>
<Checkbox value="san-francisco">San Francisco</Checkbox>
</CheckboxGroup>
<p className="text-default-500 text-small">Selected: {selected.join(", ")}</p>
</div>
);
}
22 changes: 1 addition & 21 deletions apps/docs/content/components/checkbox-group/controlled.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
const App = `import {CheckboxGroup, Checkbox} from "@nextui-org/react";

export default function App() {
const [selected, setSelected] = React.useState(["buenos-aires", "sydney"]);

return (
<div className="flex flex-col gap-3">
<CheckboxGroup
label="Select cities"
color="warning"
value={selected}
onValueChange={setSelected}
>
<Checkbox value="buenos-aires">Buenos Aires</Checkbox>
<Checkbox value="sydney">Sydney</Checkbox>
<Checkbox value="san-francisco">San Francisco</Checkbox>
</CheckboxGroup>
<p className="text-default-500 text-small">Selected: {selected.join(", ")}</p>
</div>
);
}`;
import App from "./controlled.raw.jsx?raw";

const react = {
"/App.jsx": App,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {useCheckbox, CheckboxGroup, Chip, VisuallyHidden, tv} from "@nextui-org/react";

const checkbox = tv({
slots: {
base: "border-default hover:bg-default-200",
content: "text-default-500",
},
variants: {
isSelected: {
true: {
base: "border-primary bg-primary hover:bg-primary-500 hover:border-primary-500",
content: "text-primary-foreground pl-1",
},
},
isFocusVisible: {
true: {
base: "outline-none ring-2 ring-focus ring-offset-2 ring-offset-background",
},
},
},
});

export const CustomCheckbox = (props) => {
const {children, isSelected, isFocusVisible, getBaseProps, getLabelProps, getInputProps} =
useCheckbox({
...props,
});

const styles = checkbox({isSelected, isFocusVisible});

return (
<label {...getBaseProps()}>
<VisuallyHidden>
<input {...getInputProps()} />
</VisuallyHidden>
<Chip
classNames={{
base: styles.base(),
content: styles.content(),
}}
color="primary"
startContent={isSelected ? <CheckIcon className="ml-1" /> : null}
variant="faded"
{...getLabelProps()}
>
{children ? children : isSelected ? "Enabled" : "Disabled"}
</Chip>
</label>
);
};

export const CheckIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
viewBox="0 0 24 24"
width="1em"
{...props}
>
<polyline points="20 6 9 17 4 12" />
</svg>
);

export default function App() {
const [groupSelected, setGroupSelected] = React.useState([]);

return (
<div className="flex flex-col gap-1 w-full">
<CheckboxGroup
className="gap-1"
label="Select amenities"
orientation="horizontal"
value={groupSelected}
onChange={setGroupSelected}
>
<CustomCheckbox value="wifi">Wifi</CustomCheckbox>
<CustomCheckbox value="tv">TV</CustomCheckbox>
<CustomCheckbox value="kitchen">Kitchen</CustomCheckbox>
<CustomCheckbox value="parking">Parking</CustomCheckbox>
<CustomCheckbox value="pool">Pool</CustomCheckbox>
<CustomCheckbox value="gym">Gym</CustomCheckbox>
</CheckboxGroup>
<p className="mt-4 ml-1 text-default-500">Selected: {groupSelected.join(", ")}</p>
</div>
);
}
108 changes: 1 addition & 107 deletions apps/docs/content/components/checkbox-group/custom-implementation.ts
Original file line number Diff line number Diff line change
@@ -1,113 +1,7 @@
const CheckIcon = `export const CheckIcon = (props) =>
(
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
viewBox="0 0 24 24"
width="1em"
{...props}
>
<polyline points="20 6 9 17 4 12" />
</svg>
);`;

const CustomCheckbox = `import {useCheckbox, Chip, VisuallyHidden, tv} from "@nextui-org/react";
import {CheckIcon} from './CheckIcon.jsx'

const checkbox = tv({
slots: {
base: "border-default hover:bg-default-200",
content: "text-default-500"
},
variants: {
isSelected: {
true: {
base: "border-primary bg-primary hover:bg-primary-500 hover:border-primary-500",
content: "text-primary-foreground pl-1"
}
},
isFocusVisible: {
true: {
base: "outline-none ring-2 ring-focus ring-offset-2 ring-offset-background",
}
}
}
})

export const CustomCheckbox = (props) => {
const {
children,
isSelected,
isFocusVisible,
getBaseProps,
getLabelProps,
getInputProps,
} = useCheckbox({
...props
})

const styles = checkbox({ isSelected, isFocusVisible })

return (
<label {...getBaseProps()}>
<VisuallyHidden>
<input {...getInputProps()} />
</VisuallyHidden>
<Chip
classNames={{
base: styles.base(),
content: styles.content(),
}}
color="primary"
startContent={isSelected ? <CheckIcon className="ml-1" /> : null}
variant="faded"
{...getLabelProps()}
>
{children ? children : isSelected ? "Enabled" : "Disabled"}
</Chip>
</label>
);
}`;

const App = `import {CheckboxGroup} from "@nextui-org/react";
import {CustomCheckbox} from "./CustomCheckbox";

export default function App() {
const [groupSelected, setGroupSelected] = React.useState([]);

return (
<div className="flex flex-col gap-1 w-full">
<CheckboxGroup
className="gap-1"
label="Select amenities"
orientation="horizontal"
value={groupSelected}
onChange={setGroupSelected}
>
<CustomCheckbox value="wifi">Wifi</CustomCheckbox>
<CustomCheckbox value="tv">TV</CustomCheckbox>
<CustomCheckbox value="kitchen">Kitchen</CustomCheckbox>
<CustomCheckbox value="parking">Parking</CustomCheckbox>
<CustomCheckbox value="pool">Pool</CustomCheckbox>
<CustomCheckbox value="gym">Gym</CustomCheckbox>
</CheckboxGroup>
<p className="mt-4 ml-1 text-default-500">
Selected: {groupSelected.join(", ")}
</p>
</div>
);
}`;
import App from "./custom-implementation.raw.jsx?raw";

const react = {
"/App.jsx": App,
"/CustomCheckbox.jsx": CustomCheckbox,
"/CheckIcon.jsx": CheckIcon,
};

export default {
Expand Down
104 changes: 104 additions & 0 deletions apps/docs/content/components/checkbox-group/custom-styles.raw.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {Checkbox, CheckboxGroup, Link, User, Chip, cn} from "@nextui-org/react";

export const CustomCheckbox = ({user, statusColor, value}) => {
return (
<Checkbox
aria-label={user.name}
classNames={{
base: cn(
"inline-flex max-w-md w-full bg-content1 m-0",
"hover:bg-content2 items-center justify-start",
"cursor-pointer rounded-lg gap-2 p-4 border-2 border-transparent",
"data-[selected=true]:border-primary",
),
label: "w-full",
}}
value={value}
>
<div className="w-full flex justify-between gap-2">
<User
avatarProps={{size: "md", src: user.avatar}}
description={
<Link isExternal href={user.url} size="sm">
@{user.username}
</Link>
}
name={user.name}
/>
<div className="flex flex-col items-end gap-1">
<span className="text-tiny text-default-500">{user.role}</span>
<Chip color={statusColor} size="sm" variant="flat">
{user.status}
</Chip>
</div>
</div>
</Checkbox>
);
};

export default function App() {
const [groupSelected, setGroupSelected] = React.useState([]);

return (
<div className="flex flex-col gap-1 w-full">
<CheckboxGroup
classNames={{
base: "w-full",
}}
label="Select employees"
value={groupSelected}
onChange={setGroupSelected}
>
<CustomCheckbox
statusColor="secondary"
user={{
name: "Junior Garcia",
avatar: "https://avatars.githubusercontent.com/u/30373425?v=4",
username: "jrgarciadev",
url: "https://x.com/jrgarciadev",
role: "Software Developer",
status: "Active",
}}
value="junior"
/>
<CustomCheckbox
statusColor="warning"
user={{
name: "John Doe",
avatar: "https://i.pravatar.cc/300?u=a042581f4e29026707d",
username: "johndoe",
url: "#",
role: "Product Designer",
status: "Vacation",
}}
value="johndoe"
/>
<CustomCheckbox
statusColor="danger"
user={{
name: "Zoey Lang",
avatar: "https://i.pravatar.cc/300?u=a042581f4e29026704d",
username: "zoeylang",
url: "#",
role: "Technical Writer",
status: "Out of office",
}}
value="zoeylang"
/>
<CustomCheckbox
statusColor="secondary"
user={{
name: "William Howard",
avatar: "https://i.pravatar.cc/300?u=a048581f4e29026701d",
username: "william",
url: "#",
role: "Sales Manager",
status: "Active",
}}
value="william"
/>
</CheckboxGroup>
<p className="mt-4 ml-1 text-default-500">Selected: {groupSelected.join(", ")}</p>
</div>
);
}
Loading