Standalone UI pattern labs. React + Vite + Motion + Tailwind.
Dropdowns are the thing everyone thinks they know. You open a menu, you pick an item, done. But try building one that actually feels good and you're suddenly dealing with hover delays, animation timing, diagonal mouse paths, and physics simulations for a fan speed controller that nobody asked for.
Seven sections, each taking one piece apart.
The thing that makes submenus actually work. A triangle drawn from cursor to submenu edges. Move right and the vertex freezes into a stable cone. Move left past the freeze point and it re-attaches. Ray-casting point-in-polygon in a requestAnimationFrame loop. No overlay div, no clip-path. Pure math.
Same six items, four shadow styles. Elevated stacks ring, inner bevel, drop shadow. Layered doubles offset and blur per pass. Glass swaps the fill for backdrop-filter blur. Soft pools diffused light underneath.
Fan speed controller with physical inertia, a live sparkline, and warm-to-cool color shift across RPM. None of this belongs in a dropdown. It ended up there anyway.
Live demo and writeup on ctrlship.dev
| # | Section | What it covers |
|---|---|---|
| 01 | Trigger States | Subtle, bordered, ghost, solid. Hover, press, open |
| 02 | Open Animations | Fade, scale, slide, spring. Exit always faster than enter |
| 03 | Menu Appearance | Four shadow recipes. Ring, bevel, blur, diffused |
| 04 | Item Hovers | Fill, accent bar, slide fill, color coded |
| 05 | Submenu | Flyout (hover) vs drill-down (click). Four presets each |
| 06 | Safe Triangle | rAF loop, point-in-polygon, freeze/unfreeze cone |
| 07 | List Item Types | Audio mixer, color tags, fan speed controller |
npm install
npm run devReact 19, Motion, Tailwind, Lucide. No component library. MIT license.


