Amazing Dropdowns
Smooth, intuitive dropdown menus that make navigation and selection effortless.
Amazing Dropdowns Showcase
React Code
1import React, { useState, useRef, useEffect } from "react";
2
3interface DropdownItem {
4 label: string;
5 icon?: React.ReactNode;
6 onClick?: () => void;
7}
8
9interface DropdownProps {
10 label: string;
11 items: DropdownItem[];
12 variant?: "light" | "dark" | "gradient";
13}
14
15const Dropdown: React.FC<DropdownProps> = ({ label, items, variant = "dark" }) => {
16 const [open, setOpen] = useState(false);
17 const ref = useRef<HTMLDivElement>(null);
18
19 useEffect(() => {
20 const handleClickOutside = (e: MouseEvent) => {
21 if (ref.current && !ref.current.contains(e.target as Node)) {
22 setOpen(false);
23 }
24 };
25 document.addEventListener("mousedown", handleClickOutside);
26 return () => document.removeEventListener("mousedown", handleClickOutside);
27 }, []);
28
29 const variantStyles = {
30 light: {
31 button: "bg-white text-black border border-gray-300 hover:bg-gray-100",
32 menu: "bg-white text-gray-900 border border-gray-200 shadow-lg",
33 item: "hover:bg-gray-100",
34 },
35 dark: {
36 button: "bg-gray-800 text-white border border-gray-700 hover:bg-gray-700",
37 menu: "bg-gray-900 text-white border border-gray-800 shadow-lg",
38 item: "hover:bg-gray-800",
39 },
40 gradient: {
41 button: "bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 text-white hover:opacity-90",
42 menu: "bg-gradient-to-b from-gray-900 to-black text-white border border-gray-800 shadow-lg",
43 item: "hover:bg-white/10",
44 },
45 }[variant];
46
47 return (
48 <div ref={ref} className="relative inline-block text-left">
49 <button
50 onClick={() => setOpen(!open)}
51 onKeyDown={(e) => e.key === "Escape" && setOpen(false)}
52 className={`px-5 py-3 rounded-lg font-medium transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 ${variantStyles.button}`}
53 >
54 {label}
55 <span className={`ml-2 inline-block transform transition-transform ${open ? "rotate-180" : "rotate-0"}`}>
56 ▼
57 </span>
58 </button>
59
60 {open && (
61 <div
62 className={`absolute mt-2 w-56 rounded-xl overflow-hidden ${variantStyles.menu} animate-fadeSlide`}
63 role="menu"
64 >
65 {items.map((item, i) => (
66 <button
67 key={i}
68 onClick={() => {
69 item.onClick?.();
70 setOpen(false);
71 }}
72 className={`w-full text-left px-4 py-2.5 text-sm flex items-center gap-3 transition-colors duration-200 ${variantStyles.item}`}
73 >
74 {item.icon && <span>{item.icon}</span>}
75 {item.label}
76 </button>
77 ))}
78 </div>
79 )}
80
81 <style jsx>{`
82 @keyframes fadeSlide {
83 from {
84 opacity: 0;
85 transform: translateY(-10px);
86 }
87 to {
88 opacity: 1;
89 transform: translateY(0);
90 }
91 }
92 .animate-fadeSlide {
93 animation: fadeSlide 0.25s ease-out;
94 }
95 `}</style>
96 </div>
97 );
98};
99
100return function AmazingDropdowns() {
101 return (
102 <section className="min-h-screen flex flex-col items-center justify-center bg-gradient-to-b from-gray-900 to-black text-white px-4">
103 <h2 className="text-3xl md:text-4xl font-bold mb-10">Amazing Dropdowns Showcase</h2>
104
105 <div className="flex flex-wrap justify-center gap-10">
106 <Dropdown
107 label="Dark Dropdown"
108 variant="dark"
109 items={[
110 { label: "Profile", onClick: () => alert("Profile clicked") },
111 { label: "Settings", onClick: () => alert("Settings clicked") },
112 { label: "Logout", onClick: () => alert("Logout clicked") },
113 ]}
114 />
115
116 <Dropdown
117 label="Light Dropdown"
118 variant="light"
119 items={[
120 { label: "Dashboard" },
121 { label: "Projects" },
122 { label: "Reports" },
123 ]}
124 />
125
126 <Dropdown
127 label="Gradient Dropdown"
128 variant="gradient"
129 items={[
130 { label: "Home" },
131 { label: "Features" },
132 { label: "Contact" },
133 ]}
134 />
135 </div>
136 </section>
137 );
138}
139
140