Dropdown
thegridcn/dropdownFreeComponent
thegridcn publishes no description for this item.
Install it
npx shadcn@latest add https://thegridcn.com/r/dropdown.jsonSource
1"use client";23import * as React from "react";4import { cn } from "@/lib/utils";56interface DropdownItem {7 disabled?: boolean;8 icon?: React.ReactNode;9 label: string;10 onSelect?: () => void;11 separator?: boolean;12 shortcut?: string;13 variant?: "default" | "danger";14}1516interface DropdownProps {17 align?: "left" | "right";18 children: React.ReactNode;19 className?: string;20 items: DropdownItem[];21}2223export function Dropdown({24 items,25 align = "left",26 children,27 className,28}: DropdownProps) {29 const [open, setOpen] = React.useState(false);30 const ref = React.useRef<HTMLDivElement>(null);3132 // Close on outside click33 React.useEffect(() => {34 if (!open) {35 return;36 }37 const handler = (e: MouseEvent) => {38 if (ref.current && !ref.current.contains(e.target as Node)) {39 setOpen(false);40 }41 };42 document.addEventListener("mousedown", handler);43 return () => document.removeEventListener("mousedown", handler);44 }, [open]);4546 // Close on Escape47 React.useEffect(() => {48 if (!open) {49 return;50 }51 const handler = (e: KeyboardEvent) => {52 if (e.key === "Escape") {53 setOpen(false);54 }55 };56 window.addEventListener("keydown", handler);57 return () => window.removeEventListener("keydown", handler);58 }, [open]);5960 return (61 <div ref={ref} className={cn("relative inline-block", className)}>62 <div onClick={() => setOpen(!open)} className="cursor-pointer">63 {children}64 </div>6566 {open ? (67 <div68 data-slot="tron-dropdown"69 className={cn(70 "absolute z-50 mt-1 min-w-[180px] overflow-hidden rounded border border-primary/30 bg-card/95 py-1 shadow-[0_0_20px_rgba(var(--primary-rgb,0,180,255),0.08)] backdrop-blur-md",71 align === "left" ? "left-0" : "right-0"72 )}73 >74 {/* Scanline */}75 <div className="pointer-events-none absolute inset-0 bg-[repeating-linear-gradient(0deg,transparent,transparent_2px,rgba(0,0,0,0.03)_2px,rgba(0,0,0,0.03)_4px)]" />7677 {items.map((item, i) =>78 item.separator ? (79 <div key={i} className="my-1 border-primary/15 border-t" />80 ) : (81 <button82 key={i}83 type="button"84 disabled={item.disabled}85 onClick={() => {86 item.onSelect?.();87 setOpen(false);88 }}89 className={cn(90// … truncated
Files it writes
More from thegridcn
All 139 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | thegridcn | Components | Free | 2 deps | |
| Agent Avataragent-avatar | thegridcn | Components | Free | no deps | |
| Alertalert | thegridcn | Components | Free | 1 dep | |
| Alert Dialogalert-dialog | thegridcn | Components | Free | 1 dep | |
| Announcement Barannouncement-bar | thegridcn | Components | Free | no deps | |
| Anomaly Banneranomaly-banner | thegridcn | Components | Free | no deps | |
| Arrival Panelarrival-panel | thegridcn | Components | Free | no deps | |
| Aspect Ratioaspect-ratio | thegridcn | Components | Free | 1 dep |
