Motion Dock
100xui/motion-dockFreeBlock
A reusable component where tooltips slide smoothly between dock items, making the motion dock feel natural and easy to use.
Live preview
live · rendered by the registry
Rendered by 100xui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://100xui.com/r/motion-dock.jsonSource
1"use client";23import React from "react";4import {5 useAnimate,6 motion,7 AnimatePresence,8 usePresence,9 useMotionValue,10 type Transition,11 type AnimationPlaybackControlsWithThen,12 type HTMLMotionProps,13} from "motion/react";14import { cn } from "@/lib/utils";1516import { usePrevious } from "@/hooks/use-previous";17import { useDebouncedState } from "@/hooks/use-debounced-state";1819interface DockItem extends Omit<HTMLMotionProps<"button">, "ref"> {20 icon: React.ReactElement;21 tooltip: string;22}2324export interface MotionDockProps extends React.ComponentProps<"div"> {25 dockItems: DockItem[];26 tooltipBorderRadius?: React.CSSProperties["borderRadius"];27}28const TRANSITION: Transition = {29 duration: 0.2,30 ease: [0.76, 0, 0.24, 1], // easeInOutQuart31};32export function MotionDock({33 dockItems,34 className,35 tooltipBorderRadius = "var(--radius-sm)",36 ...rest37}: MotionDockProps) {38 const [activeItem, setActiveItem] = useDebouncedState<number>(-1, 100);39 const dockRef = React.useRef<HTMLDivElement>(null);4041 const handleReset = () => setActiveItem(-1);4243 return (44 <div className={cn(className, "!relative !w-fit")} {...rest}>45 <div46 ref={dockRef}47 className="bg-background text-foreground border-border flex gap-0.5 rounded-full border p-1 shadow-sm"48 onMouseLeave={handleReset}49 onBlurCapture={handleReset}50 >51 {dockItems.map(52 ({ icon, tooltip, onMouseEnter, onFocus, className, ...rest }, i) => (53 <motion.button54 key={tooltip}55 aria-label={tooltip}56 onFocus={(e) => {57 setActiveItem(i);58 onFocus?.(e);59 }}60 onMouseEnter={(e) => {61 setActiveItem(i);62 onMouseEnter?.(e);63 }}64 data-dockitem={i}65 className={cn(66 "hover:text-accent-foreground hover:bg-accent focus-visible:text-accent-foreground focus-visible:bg-accent focus-visible:ring-ring focus-visible:ring-offset-background cursor-pointer rounded-full p-1.5 transition-colors duration-150 ease-out focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-none",67 className68 )}69 {...rest}70 >71 {icon}72 </motion.button>73 )74 )}75 </div>76 <AnimatePresence>77 {activeItem >= 0 && (78 <ToolTipsContainer79 activeItem={activeItem}80// … truncated
What it pulls in
npm packages
Files it writes
More from 100xui
All 14 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Apple galleryapple-gallery | 100xui | Blocks | Free | 1 dep | |
| Chat bento cardchat-bento-card | 100xui | Blocks | Free | 1 dep | |
| demosdemos | 100xui | Blocks | Free | no deps · 12 files | |
| In-page navbarin-page-navbar | 100xui | Blocks | Free | 1 dep · 2 files | |
| internalsinternals | 100xui | Blocks | Free | no deps · 4 files | |
| iPhone 3D mockupiphone-3d-mockup | 100xui | Blocks | Free | no deps | |
| Menu wheelmenu-wheel | 100xui | Blocks | Free | 1 dep | |
| Morph modalmorph-modal | 100xui | Blocks | Free | 1 dep |
