Dock
motion-primitives/dockFreeComponent
A macOS-style dock component with scaling and movement effects.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/ibelick/motion-primitives/HEAD/public/c/dock.jsonSource
1'use client';23import {4 motion,5 MotionValue,6 useMotionValue,7 useSpring,8 useTransform,9 type SpringOptions,10 AnimatePresence,11} from 'motion/react';12import {13 Children,14 cloneElement,15 createContext,16 useContext,17 useEffect,18 useMemo,19 useRef,20 useState,21} from 'react';22import { cn } from '@/lib/utils';2324const DOCK_HEIGHT = 128;25const DEFAULT_MAGNIFICATION = 80;26const DEFAULT_DISTANCE = 150;27const DEFAULT_PANEL_HEIGHT = 64;2829export type DockProps = {30 children: React.ReactNode;31 className?: string;32 distance?: number;33 panelHeight?: number;34 magnification?: number;35 spring?: SpringOptions;36};3738export type DockItemProps = {39 className?: string;40 children: React.ReactNode;41 onClick?: () => void;42};4344export type DockLabelProps = {45 className?: string;46 children: React.ReactNode;47};4849export type DockIconProps = {50 className?: string;51 children: React.ReactNode;52};5354export type DocContextType = {55 mouseX: MotionValue;56 spring: SpringOptions;57 magnification: number;58 distance: number;59};6061export type DockProviderProps = {62 children: React.ReactNode;63 value: DocContextType;64};6566const DockContext = createContext<DocContextType | undefined>(undefined);6768function DockProvider({ children, value }: DockProviderProps) {69 return <DockContext.Provider value={value}>{children}</DockContext.Provider>;70}7172function useDock() {73 const context = useContext(DockContext);74 if (!context) {75 throw new Error('useDock must be used within an DockProvider');76 }77 return context;78}7980function Dock({81 children,82 className,83 spring = { mass: 0.1, stiffness: 150, damping: 12 },84 magnification = DEFAULT_MAGNIFICATION,85 distance = DEFAULT_DISTANCE,86 panelHeight = DEFAULT_PANEL_HEIGHT,87}: DockProps) {88 const mouseX = useMotionValue(Infinity);89 const isHovered = useMotionValue(0);9091 const maxHeight = useMemo(() => {92 return Math.max(DOCK_HEIGHT, magnification + magnification / 2 + 4);93 }, [magnification]);9495 const heightRow = useTransform(isHovered, [0, 1], [panelHeight, maxHeight]);96 const height = useSpring(heightRow, spring);9798 return (99 <motion.div100 style={{101 height: height,102 scrollbarWidth: 'none',103 }}104 className='mx-2 flex max-w-full items-end overflow-x-auto'105 >106 <motion.div107 onMouseMove={({ pageX }) => {108 isHovered.set(1);109 mouseX.set(pageX);110 }}111 onMouseLeave={() => {112 isHovered.set(0);113 mouseX.set(Infinity);114 }}115// … truncated
What it pulls in
npm packages
Files it writes
More from motion-primitives
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | motion-primitives | Components | Free | 1 dep | |
| Animated Backgroundanimated-background | motion-primitives | Components | Free | 1 dep | |
| Animated Groupanimated-group | motion-primitives | Components | Free | 1 dep | |
| Animated Numberanimated-number | motion-primitives | Components | Free | 1 dep | |
| Border Trailborder-trail | motion-primitives | Components | Free | 1 dep | |
| Carouselcarousel | motion-primitives | Components | Free | 1 dep | |
| Cursorcursor | motion-primitives | Components | Free | 1 dep | |
| Dialogdialog | motion-primitives | Components | Free | 1 dep · 2 files |
