Working modals, a filterable ⌘K command palette, slide-over drawers, tooltips and bottom sheets — every overlay opens right inside its preview box.
Command Palette (⌘K)
AI
Navigate
Actions
Type to filter commands live — grouped results, keyboard hints and an AI action pinned on top.
| 1 | function CommandPalette() { |
| 2 | const [query, setQuery] = useState(""); |
| 3 | const commands = [ |
| 4 | { group: "AI", icon: "✦", label: "Generate component from prompt", kbd: "G" }, |
| 5 | { group: "AI", icon: "✦", label: "Explain selected code", kbd: "E" }, |
| 6 | { group: "Navigate", icon: "→", label: "Go to Dashboard", kbd: "D" }, |
| 7 | { group: "Navigate", icon: "→", label: "Go to Settings", kbd: "S" }, |
| 8 | { group: "Actions", icon: "+", label: "New project", kbd: "N" }, |
| 9 | { group: "Actions", icon: "⌫", label: "Delete project…", kbd: "⇧D" }, |
| 10 | ]; |
| 11 | const results = commands.filter((c) => |
| 12 | c.label.toLowerCase().includes(query.toLowerCase()) |
| 13 | ); |
| 14 | |
| 15 | return ( |
| 16 | <div "color:#79c0ff">className="w-full max-w-lg overflow-hidden rounded-2xl border border-white/12 bg-[#0d0d1a]/95 shadow-2xl backdrop-blur-xl"> |
| 17 | {/* search row */} |
| 18 | <div "color:#79c0ff">className="flex items-center gap-3 border-b border-white/8 px-4 py-3.5"> |
| 19 | <SearchIcon "color:#79c0ff">className="h-4 w-4 text-white/30" /> |
| 20 | <input |
| 21 | autoFocus |
| 22 | "color:#79c0ff">value={query} |
| 23 | "color:#79c0ff">onChange={(e) => setQuery(e.target.value)} |
| 24 | "color:#79c0ff">placeholder="Type a command or search…" |
| 25 | "color:#79c0ff">className="flex-1 bg-transparent text-sm text-white placeholder-white/30 outline-none" |
| 26 | /> |
| 27 | <kbd "color:#79c0ff">className="rounded border border-white/12 bg-white/[0.05] px-1.5 py-0.5 text-[10px] text-white/35">ESC</kbd> |
| 28 | </div> |
| 29 | |
| 30 | {/* results */} |
| 31 | <div "color:#79c0ff">className="max-h-64 overflow-y-auto p-2"> |
| 32 | {results.length === 0 && ( |
| 33 | <p "color:#79c0ff">className="px-3 py-8 text-center text-sm text-white/30">No results for “{query}”</p> |
| 34 | )} |
| 35 | {["AI", "Navigate", "Actions"].map((group) => { |
| 36 | const items = results.filter((c) => c.group === group); |
| 37 | if (!items.length) return null; |
| 38 | return ( |
| 39 | <div "color:#79c0ff">key={group}> |
| 40 | <p "color:#79c0ff">className="px-3 pb-1 pt-2 text-[10px] font-bold uppercase tracking-widest text-white/25">{group}</p> |
| 41 | {items.map((c, i) => ( |
| 42 | <button "color:#79c0ff">key={c.label} |
| 43 | "color:#79c0ff">className={"flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left transition-colors " + |
| 44 | (group === "AI" && i === 0 && !query |
| 45 | ? "bg-violet-600 text-white" |
| 46 | : "text-white/60 hover:bg-white/[0.06] hover:text-white")}> |
| 47 | <span "color:#79c0ff">className="flex h-7 w-7 items-center justify-center rounded-lg bg-white/10 text-xs">{c.icon}</span> |
| 48 | <span "color:#79c0ff">className="flex-1 text-sm font-medium">{c.label}</span> |
| 49 | <kbd "color:#79c0ff">className="rounded border border-white/12 bg-white/[0.05] px-1.5 py-0.5 text-[10px]">{c.kbd}</kbd> |
| 50 | </button> |
| 51 | ))} |
| 52 | </div> |
| 53 | ); |
| 54 | })} |
| 55 | </div> |
| 56 | </div> |
| 57 | ); |
| 58 | } |
Modal Dialog
Click the button — a real modal opens over the mock page with backdrop blur and a pop-in animation.
| 1 | function DeleteModal() { |
| 2 | const [open, setOpen] = useState(false); |
| 3 | |
| 4 | return ( |
| 5 | <> |
| 6 | <button "color:#79c0ff">onClick={() => setOpen(true)} |
| 7 | "color:#79c0ff">className="rounded-xl bg-rose-500/90 px-5 py-2.5 text-sm font-bold text-white hover:bg-rose-500"> |
| 8 | Delete project |
| 9 | </button> |
| 10 | |
| 11 | {open && ( |
| 12 | <div |
| 13 | "color:#79c0ff">className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4 backdrop-blur-sm" |
| 14 | "color:#79c0ff">onClick={() => setOpen(false)} |
| 15 | > |
| 16 | <div |
| 17 | "color:#79c0ff">onClick={(e) => e.stopPropagation()} |
| 18 | "color:#79c0ff">className="w-full max-w-sm rounded-3xl border border-white/10 bg-[#10101c] p-6 shadow-2xl" |
| 19 | "color:#79c0ff">style={{ animation: "pop .25s ease both" }} |
| 20 | > |
| 21 | <div "color:#79c0ff">className="flex h-11 w-11 items-center justify-center rounded-2xl bg-rose-500/15 ring-1 ring-inset ring-rose-400/30"> |
| 22 | <TrashIcon "color:#79c0ff">className="h-5 w-5 text-rose-300" /> |
| 23 | </div> |
| 24 | <h3 "color:#79c0ff">className="mt-4 text-lg font-extrabold text-white">Delete “nebula-app”?</h3> |
| 25 | <p "color:#79c0ff">className="mt-1.5 text-sm leading-relaxed text-white/45"> |
| 26 | This permanently removes the project, its deployments and all analytics. This cannot be undone. |
| 27 | </p> |
| 28 | <div "color:#79c0ff">className="mt-6 flex gap-3"> |
| 29 | <button "color:#79c0ff">onClick={() => setOpen(false)} |
| 30 | "color:#79c0ff">className="flex-1 rounded-xl border border-white/12 py-2.5 text-sm font-semibold text-white/70 hover:bg-white/5"> |
| 31 | Cancel |
| 32 | </button> |
| 33 | <button "color:#79c0ff">onClick={() => setOpen(false)} |
| 34 | "color:#79c0ff">className="flex-1 rounded-xl bg-rose-500 py-2.5 text-sm font-bold text-white hover:bg-rose-400"> |
| 35 | Delete forever |
| 36 | </button> |
| 37 | </div> |
| 38 | </div> |
| 39 | </div> |
| 40 | )} |
| 41 | </> |
| 42 | ); |
| 43 | } |
Dropdown Menu
Icon rows, keyboard shortcuts, a separator and a destructive item — click to toggle.
| 1 | function Dropdown() { |
| 2 | const [open, setOpen] = useState(false); |
| 3 | |
| 4 | return ( |
| 5 | <div "color:#79c0ff">className="relative"> |
| 6 | <button "color:#79c0ff">onClick={() => setOpen(!open)} |
| 7 | "color:#79c0ff">className="flex items-center gap-2 rounded-xl border border-white/12 bg-white/[0.05] px-4 py-2.5 text-sm font-semibold text-white/85 hover:bg-white/10"> |
| 8 | Options |
| 9 | <ChevronIcon "color:#79c0ff">className={"h-4 w-4 transition-transform " + (open ? "rotate-180" : "")} /> |
| 10 | </button> |
| 11 | |
| 12 | {open && ( |
| 13 | <div "color:#79c0ff">className="absolute left-0 top-full z-20 mt-2 w-56 rounded-2xl border border-white/10 bg-[#10101c]/95 p-1.5 shadow-2xl backdrop-blur-xl" |
| 14 | "color:#79c0ff">style={{ animation: "pop .18s ease both" }}> |
| 15 | {[ |
| 16 | { icon: "✏️", label: "Rename", kbd: "R" }, |
| 17 | { icon: "📄", label: "Duplicate", kbd: "⌘D" }, |
| 18 | { icon: "🔗", label: "Copy link", kbd: "⌘C" }, |
| 19 | ].map((it) => ( |
| 20 | <button "color:#79c0ff">key={it.label} |
| 21 | "color:#79c0ff">className="flex w-full items-center gap-3 rounded-xl px-3 py-2 text-sm text-white/65 transition hover:bg-white/[0.07] hover:text-white"> |
| 22 | <span "color:#79c0ff">className="text-xs">{it.icon}</span> |
| 23 | <span "color:#79c0ff">className="flex-1 text-left">{it.label}</span> |
| 24 | <kbd "color:#79c0ff">className="text-[10px] text-white/25">{it.kbd}</kbd> |
| 25 | </button> |
| 26 | ))} |
| 27 | <div "color:#79c0ff">className="my-1.5 h-px bg-white/8" /> |
| 28 | <button "color:#79c0ff">className="flex w-full items-center gap-3 rounded-xl px-3 py-2 text-sm text-rose-300 transition hover:bg-rose-500/10"> |
| 29 | <span "color:#79c0ff">className="text-xs">🗑️</span> Delete project |
| 30 | </button> |
| 31 | </div> |
| 32 | )} |
| 33 | </div> |
| 34 | ); |
| 35 | } |
Slide-Over Drawer
A panel that slides in from the right with a scrim — open and close it inside the preview.
| 1 | function Drawer() { |
| 2 | const [open, setOpen] = useState(false); |
| 3 | |
| 4 | return ( |
| 5 | <div "color:#79c0ff">className="relative h-72 overflow-hidden rounded-2xl border border-white/10 bg-[#08080f]"> |
| 6 | {/* page mock */} |
| 7 | <div "color:#79c0ff">className="p-5"> |
| 8 | <button "color:#79c0ff">onClick={() => setOpen(true)} |
| 9 | "color:#79c0ff">className="rounded-xl bg-violet-600 px-4 py-2 text-sm font-bold text-white hover:bg-violet-500"> |
| 10 | Open cart (2) |
| 11 | </button> |
| 12 | </div> |
| 13 | |
| 14 | {/* scrim */} |
| 15 | <div "color:#79c0ff">onClick={() => setOpen(false)} |
| 16 | "color:#79c0ff">className={"absolute inset-0 bg-black/50 backdrop-blur-[2px] transition-opacity duration-300 " + |
| 17 | (open ? "opacity-100" : "pointer-events-none opacity-0")} /> |
| 18 | |
| 19 | {/* panel */} |
| 20 | <aside "color:#79c0ff">className={"absolute inset-y-0 right-0 flex w-64 flex-col border-l border-white/10 bg-[#10101c] shadow-2xl transition-transform duration-300 " + |
| 21 | (open ? "translate-x-0" : "translate-x-full")}> |
| 22 | <div "color:#79c0ff">className="flex items-center justify-between border-b border-white/8 px-4 py-3"> |
| 23 | <p "color:#79c0ff">className="text-sm font-bold text-white">Your cart</p> |
| 24 | <button "color:#79c0ff">onClick={() => setOpen(false)} "color:#79c0ff">className="text-white/40 hover:text-white">×</button> |
| 25 | </div> |
| 26 | {/* items … */} |
| 27 | <button "color:#79c0ff">className="m-4 mt-auto rounded-xl bg-gradient-to-r from-violet-600 to-indigo-600 py-2.5 text-sm font-bold text-white"> |
| 28 | Checkout — $438 |
| 29 | </button> |
| 30 | </aside> |
| 31 | </div> |
| 32 | ); |
| 33 | } |
Tooltips
Pure-CSS hover tooltips in four directions with arrows — hover the buttons.
| 1 | {/* top tooltip */} |
| 2 | <div "color:#79c0ff">className="group relative"> |
| 3 | <button "color:#79c0ff">className="flex h-10 w-10 items-center justify-center rounded-xl bg-white/[0.06] text-white/60 ring-1 ring-inset ring-white/10 hover:text-white"> |
| 4 | <BoldIcon "color:#79c0ff">className="h-4 w-4" /> |
| 5 | </button> |
| 6 | <span "color:#79c0ff">className="pointer-events-none absolute -top-9 left-1/2 -translate-x-1/2 whitespace-nowrap rounded-lg bg-black/85 px-2.5 py-1.5 text-[11px] font-semibold text-white opacity-0 shadow-xl backdrop-blur transition-all duration-150 group-hover:-top-10 group-hover:opacity-100"> |
| 7 | Bold (⌘B) |
| 8 | {/* arrow */} |
| 9 | <span "color:#79c0ff">className="absolute left-1/2 top-full -mt-px h-2 w-2 -translate-x-1/2 rotate-45 bg-black/85" /> |
| 10 | </span> |
| 11 | </div> |
Profile Popover
Built by AKAyush KumarDesign engineerBuilding UIDrops — 120+ open-source components for the AI era.128 posts12.4k followersFollow with Next.js and Tailwind.
A hover-card with profile stats and actions — hover the username to reveal it.
| 1 | <div "color:#79c0ff">className="group relative inline-block"> |
| 2 | <button "color:#79c0ff">className="font-semibold text-violet-300 underline decoration-violet-400/40 underline-offset-4 hover:text-violet-200"> |
| 3 | @ayushbuilds |
| 4 | </button> |
| 5 | |
| 6 | {/* hover card */} |
| 7 | <div "color:#79c0ff">className="pointer-events-none absolute left-1/2 top-full z-20 mt-3 w-64 -translate-x-1/2 rounded-2xl border border-white/10 bg-[#10101c]/95 p-4 opacity-0 shadow-2xl backdrop-blur-xl transition-all duration-200 group-hover:pointer-events-auto group-hover:mt-2 group-hover:opacity-100"> |
| 8 | <div "color:#79c0ff">className="flex items-center gap-3"> |
| 9 | <span "color:#79c0ff">className="flex h-11 w-11 items-center justify-center rounded-full bg-gradient-to-br from-violet-500 to-indigo-600 text-xs font-black text-white">AK</span> |
| 10 | <div> |
| 11 | <p "color:#79c0ff">className="text-sm font-bold text-white">Ayush Kumar</p> |
| 12 | <p "color:#79c0ff">className="text-xs text-white/40">Design engineer</p> |
| 13 | </div> |
| 14 | </div> |
| 15 | <p "color:#79c0ff">className="mt-3 text-xs leading-relaxed text-white/50"> |
| 16 | Building UIDrops — 120+ open-source components for the AI era. |
| 17 | </p> |
| 18 | <div "color:#79c0ff">className="mt-3 flex gap-4 text-xs text-white/40"> |
| 19 | <span><b "color:#79c0ff">className="text-white">128</b> posts</span> |
| 20 | <span><b "color:#79c0ff">className="text-white">12.4k</b> followers</span> |
| 21 | </div> |
| 22 | <button "color:#79c0ff">className="mt-3 w-full rounded-xl bg-white py-2 text-xs font-bold text-slate-900 hover:bg-slate-100"> |
| 23 | Follow |
| 24 | </button> |
| 25 | </div> |
| 26 | </div> |
Mobile Bottom Sheet
NOW PLAYING
Design Systems Podcast
Episode 42 · 38 min
Share via
A phone-frame demo — tap “Share” and the sheet slides up with a grabber and action grid.
| 1 | function BottomSheet() { |
| 2 | const [open, setOpen] = useState(false); |
| 3 | |
| 4 | return ( |
| 5 | <div "color:#79c0ff">className="relative h-96 w-56 overflow-hidden rounded-[2rem] border-4 border-white/10 bg-[#08080f]"> |
| 6 | {/* app content */} |
| 7 | <div "color:#79c0ff">className="p-4 pt-8"> |
| 8 | <button "color:#79c0ff">onClick={() => setOpen(true)} |
| 9 | "color:#79c0ff">className="w-full rounded-xl bg-violet-600 py-2.5 text-xs font-bold text-white"> |
| 10 | Share ↑ |
| 11 | </button> |
| 12 | </div> |
| 13 | |
| 14 | {/* scrim */} |
| 15 | <div "color:#79c0ff">onClick={() => setOpen(false)} |
| 16 | "color:#79c0ff">className={"absolute inset-0 bg-black/50 transition-opacity duration-300 " + |
| 17 | (open ? "opacity-100" : "pointer-events-none opacity-0")} /> |
| 18 | |
| 19 | {/* sheet */} |
| 20 | <div "color:#79c0ff">className={"absolute inset-x-0 bottom-0 rounded-t-3xl border-t border-white/10 bg-[#12121f] p-4 transition-transform duration-300 " + |
| 21 | (open ? "translate-y-0" : "translate-y-full")}> |
| 22 | <div "color:#79c0ff">className="mx-auto h-1 w-10 rounded-full bg-white/20" /> |
| 23 | <p "color:#79c0ff">className="mt-3 text-center text-xs font-bold text-white">Share via</p> |
| 24 | <div "color:#79c0ff">className="mt-3 grid grid-cols-4 gap-2"> |
| 25 | {apps.map((a) => ( |
| 26 | <button "color:#79c0ff">key={a.name} "color:#79c0ff">className="flex flex-col items-center gap-1"> |
| 27 | <span "color:#79c0ff">className="flex h-10 w-10 items-center justify-center rounded-2xl text-base" |
| 28 | "color:#79c0ff">style={{ background: a.bg }}>{a.emoji}</span> |
| 29 | <span "color:#79c0ff">className="text-[8px] text-white/40">{a.name}</span> |
| 30 | </button> |
| 31 | ))} |
| 32 | </div> |
| 33 | </div> |
| 34 | </div> |
| 35 | ); |
| 36 | } |