Dock
unlumen-ui/dockFreeComponent
Animated dock with Gaussian magnification, spring physics, separators, and tooltip carets.
Live preview
live · rendered by the registry
Rendered by Unlumen Ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.unlumen.com/r/dock.jsonSource
1"use client";23import * as React from "react";4import {5 motion,6 useMotionValue,7 useSpring,8 useTransform,9 type SpringOptions,10 AnimatePresence,11} from "motion/react";1213import { cn } from "@/lib/utils";1415export interface DockItem {16 icon: React.ReactNode;17 label: string;18 /** if provided, item renders as an `<a>` */19 href?: string;20 onClick?: () => void;21 /** renders a visual separator after this item */22 separator?: boolean;23}2425export interface DockProps {26 items: DockItem[];27 /** @default 1.8 */28 magnification?: number;29 /** cursor radius (px) within which neighbors are magnified — @default 120 */30 distance?: number;31 /** @default 40 */32 iconSize?: number;33 /** @default 4 */34 gap?: number;35 /** @default 16 */36 borderRadius?: number;37 /** show labels permanently instead of on hover — @default false */38 alwaysShowLabels?: boolean;39 springOptions?: SpringOptions;40 className?: string;41}4243const DEFAULT_SPRING: SpringOptions = {44 stiffness: 400,45 damping: 25,46 mass: 0.4,47};4849function DockSeparator() {50 return (51 <div className="mx-1 flex items-center self-stretch">52 <div className="h-6 w-px bg-foreground/10" />53 </div>54 );55}5657function DockIcon({58 item,59 mouseX,60 magnification,61 distance,62 iconSize,63 borderRadius,64 alwaysShowLabels,65 springOptions,66 onHover,67 iconRef: externalIconRef,68}: {69 item: DockItem;70 mouseX: ReturnType<typeof useMotionValue<number>>;71 magnification: number;72 distance: number;73 iconSize: number;74 borderRadius: number;75 alwaysShowLabels: boolean;76 springOptions: SpringOptions;77 onHover: (ref: React.RefObject<HTMLDivElement | null> | null) => void;78 iconRef: React.RefObject<HTMLDivElement | null>;79}) {80 const wrapperRef = React.useRef<HTMLDivElement>(null);8182 const distanceFromMouse = useTransform(mouseX, (val) => {83 const el = wrapperRef.current;84 if (!el) return distance * 100;85 const rect = el.getBoundingClientRect();86 return Math.abs(val - (rect.left + rect.width / 2));87 });8889 const gaussian = (d: number) =>90 (magnification - 1) * Math.exp(-(d * d) / (2 * distance * distance)) + 1;9192 const widthRaw = useTransform(93 distanceFromMouse,94 (d) => iconSize * gaussian(d),95 );96 const heightRaw = useTransform(97 distanceFromMouse,98 (d) => iconSize * gaussian(d),99 );100101 const width = useSpring(widthRaw, springOptions);102 const height = useSpring(heightRaw, springOptions);103104 const Tag = item.href ? "a" : "button";105106 return (107// … truncated
What it pulls in
npm packages
Files it writes
More from Unlumen Ui
All 233 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| AI Chatai-chat | Unlumen Ui | Components | Paid | 2 deps | |
| Vercel Animate Countanimate-count | Unlumen Ui | Components | Free | 1 dep | |
| Animate Digitsanimate-digits | Unlumen Ui | Components | Free | 1 dep | |
| Animated Inputanimate-text-input-typing | Unlumen Ui | Components | Paid | 1 dep | |
| Animated Listanimated-list | Unlumen Ui | Components | Free | 1 dep | |
| Apple Switchapple-switch | Unlumen Ui | Components | Free | 1 dep | |
| Aurora Barsaurora-bars | Unlumen Ui | Components | Free | 1 dep | |
| Aurora Bluraurora-blur | Unlumen Ui | Components | Free | 2 deps |
