Skip to content

Instantly share code, notes, and snippets.

@mxkaske
Last active May 4, 2023 19:23
Show Gist options
  • Save mxkaske/fac169134585d5ad619bf23391a3a06a to your computer and use it in GitHub Desktop.
Save mxkaske/fac169134585d5ad619bf23391a3a06a to your computer and use it in GitHub Desktop.
DropdownMenu with CheckboxItems and nested Dialog
"use client";
import * as React from "react";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuTrigger,
DropdownMenuSeparator,
DropdownMenuItem,
} from "@/components/ui/dropdown-menu";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { DialogClose } from "@radix-ui/react-dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Plus } from "lucide-react";
const LABELS = ["Bug", "Documentation", "Duplicate", "Question"]
export default function LabelDropdownMenu() {
const [newLabel, setNewLabel] = React.useState<string>("");
const [labels, setLabels] = React.useState<string[]>(LABELS);
const [values, setValues] = React.useState<string[]>([]);
React.useEffect(() => {
if (labels.includes(newLabel)) {
setValues((prev) => [...prev, newLabel]);
setNewLabel("");
}
}, [newLabel, labels]);
return (
<Dialog>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Labels</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
{labels.map((label) => {
const checked = values.includes(label);
return (
<DropdownMenuCheckboxItem
key={label}
checked={checked}
onCheckedChange={(checked) => {
if (checked) {
setValues((prev) => [...prev, label]);
} else {
setValues((prev) => prev.filter((l) => l !== label));
}
}}
onSelect={(event) => {
event.preventDefault();
}}
>
{label}
</DropdownMenuCheckboxItem>
);
})}
<DropdownMenuSeparator />
<DialogTrigger asChild>
<DropdownMenuItem
onSelect={(event) => {
event.preventDefault();
}}
className="appearance-none"
>
<Plus className="mr-2 h-4 w-4" />
<span>Create Label</span>
</DropdownMenuItem>
</DialogTrigger>
</DropdownMenuContent>
</DropdownMenu>
<DialogContent>
<DialogHeader>
<DialogTitle>Create Label</DialogTitle>
<DialogDescription>
Missing a label? Create one now!
</DialogDescription>
</DialogHeader>
<div>
<Label htmlFor="name" className="sr-only">
Name
</Label>
<Input
id="name"
value={newLabel}
onChange={(e) => setNewLabel(e.target.value)}
className="w-full"
/>
</div>
<DialogFooter>
<DialogClose asChild>
<Button
disabled={newLabel.trim() === ""}
onClick={() => {
setLabels((prev) => [...prev, newLabel]);
}}
>
Save
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
@mxkaske
Copy link
Author

mxkaske commented May 4, 2023

Seen in the Twitter post.

Available through shadcn ui.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment