Dock
Also called macOS dock, magnification dock, or app dock
A row of app icons, like the macOS dock, where icons near the pointer grow smoothly, a label appears on hover, and a dot marks open apps.
import { useRef } from 'react';
import {
motion,
useMotionValue,
useReducedMotion,
useSpring,
useTransform,
type MotionValue
} from 'motion/react';
type App = { name: string; icon: string; open?: boolean };
const BASE = 48; // icon size at rest, in px
const MAX = 80; // icon size right under the pointer
const REACH = 140; // icons farther than this from the pointer stay at rest
export function Dock({ apps }: { apps: App[] }) {
// Infinity means the pointer is off the dock, so nothing grows.
const mouseX = useMotionValue(Infinity);
return (
<nav
aria-label='Apps'
onPointerMove={(event) => mouseX.set(event.clientX)}
onPointerLeave={() => mouseX.set(Infinity)}
className='mx-auto flex h-16 w-fit items-end gap-2 rounded-2xl border border-white/20 bg-white/10 px-2 pb-2 backdrop-blur-xl'
>
{apps.map((app) => (
<DockIcon key={app.name} app={app} mouseX={mouseX} />
))}
</nav>
);
}
function DockIcon({ app, mouseX }: { app: App; mouseX: MotionValue<number> }) {
const ref = useRef<HTMLButtonElement>(null);
const reduceMotion = useReducedMotion();
const distance = useTransform(mouseX, (x) => {
const box = ref.current?.getBoundingClientRect();
return box ? x - box.left - box.width / 2 : Infinity;
});
const target = useTransform(distance, [-REACH, 0, REACH], [BASE, MAX, BASE]);
// Width, not scale, so the neighbors slide aside as an icon grows.
const size = useSpring(target, { stiffness: 400, damping: 30, mass: 0.3 });
return (
<motion.button
ref={ref}
type='button'
aria-label={app.name}
style={{
width: reduceMotion ? BASE : size,
height: reduceMotion ? BASE : size
}}
className='group relative shrink-0 outline-none'
>
<img src={app.icon} alt='' className='size-full rounded-[24%]' />
<span className='pointer-events-none absolute bottom-full left-1/2 mb-2 -translate-x-1/2 rounded-md bg-black/75 px-2 py-1 text-xs whitespace-nowrap text-white opacity-0 transition-opacity group-hover:opacity-100 group-focus-visible:opacity-100'>
{app.name}
</span>
{app.open && (
<span className='absolute -bottom-1.5 left-1/2 size-1 -translate-x-1/2 rounded-full bg-white' />
)}
</motion.button>
);
}Build a macOS-style dock centered at the bottom of the hero: 9 rounded-square 48px app icons in a frosted glass bar with 8px gaps. As the pointer moves along the bar, grow the icon under it to 80px and its neighbors less, back to 48px at 140px away, through a spring (stiffness 400, damping 30). Grow width and height so neighbors slide aside. Show the app name in a dark pill above the hovered or focused icon, a 4px white dot under open apps, and bounce an icon twice when clicked. Under prefers-reduced-motion, keep icons at 48px.
Paste into Layerwise or any AI coding tool.
What is Dock?
A dock is a bar of app icons borrowed from the macOS desktop. As the pointer moves along it, the icon underneath grows the most and its neighbors grow a little less, so a wave of magnification follows the cursor. The app’s name appears in a small label above the icon, and a dot under an icon means that app is open.
To build one, track the pointer’s x position in a motion value, measure each icon’s distance from it, and map that distance to a size: largest at 0, back to normal about 140px away. Run the size through a spring so it eases instead of snapping, and grow width and height rather than scale, so the neighbors slide aside instead of overlapping.
On the web, a dock works as a playful launcher in a portfolio, a landing page hero, or a desktop-style app. For ordinary site navigation, a plain nav bar is clearer. Give every icon an accessible name and show its label on keyboard focus too, because a row of pictures is hard to tell apart. Touch screens have no hover, so the icons must work as plain buttons, and under reduced motion keep them at their normal size.
Often confused with
- Magnetic button
- A magnetic button shifts toward the pointer. Dock icons stay in their row and grow based on how close the pointer is.
Related terms
All termsHover effect
A visual change, such as a lift, glow, or zoom, that happens when the mouse pointer moves over an element to show it can be clicked.
Spring animation
An animation driven by simulated spring physics in place of a fixed duration and curve, so motion can overshoot, settle, and react naturally.
Tooltip
A small label that appears next to an element when you hover over it or focus it, naming an icon button or adding a short hint.
Magnetic button
A button that leans toward the mouse pointer as it gets close, then springs back when the pointer leaves.
Build it with Layerwise
Describe your app, watch it run in a live preview, and publish it with a database, storage, and sign-in built in.
