Floating Dock
A macOS-style animated floating dock with smooth hover magnification effects
Overview
A beautiful macOS-inspired floating dock component with smooth magnification effects. Icons elegantly scale and animate based on mouse proximity, creating an intuitive and delightful user experience. Built with Framer Motion for fluid spring animations.
Preview
Installation
Dependencies
npm install motion @tabler/icons-reactThe component requires:
- motion (Framer Motion) - For smooth animations and spring physics
- @tabler/icons-react - For icons (or use your preferred icon library)
- Next.js - For the Link component (can be adapted for other frameworks)
Usage
Basic Implementation
import { FloatingDock } from '@/components/aesthe-ui/floating-dock/floating-dock'
export default function MyPage() {
return (
<div>
{/* Your page content */}
<FloatingDock />
</div>
)
}Custom Links Configuration
Customize the dock by modifying the links array in the FloatingDockCore component:
const links: LinkProps[] = [
{
label: 'Dashboard',
href: '/dashboard',
icon: <LayoutDashboard className="h-full w-full text-neutral-600 dark:text-neutral-300" />,
},
{
label: 'Projects',
href: '/projects',
icon: <FolderKanban className="h-full w-full text-neutral-600 dark:text-neutral-300" />,
},
{
label: 'Messages',
href: '/messages',
icon: <MessageSquare className="h-full w-full text-neutral-600 dark:text-neutral-300" />,
},
// Add more links as needed
]Standalone Component
If you want to make the links configurable via props:
interface FloatingDockProps {
items: LinkProps[]
}
export const FloatingDock = ({ items }: FloatingDockProps) => {
return (
<div className="flex h-screen items-center justify-center">
<FloatingDockCore links={items} />
</div>
)
}Component Structure
Main Components
- FloatingDock - Wrapper component that centers the dock
- FloatingDockCore - Core dock container with mouse tracking
- LinkItem - Individual dock item with magnification logic
Type Definition
type LinkProps = {
label: string // Tooltip label
href: string // Navigation URL
icon: React.ReactNode // Icon component
}Customization
Positioning
Change the dock position by modifying the className:
// Bottom center (default)
className="fixed inset-x-0 bottom-10 mx-auto ..."
// Top center
className="fixed inset-x-0 top-10 mx-auto ..."
// Bottom left
className="fixed bottom-10 left-10 ..."
// Bottom right
className="fixed bottom-10 right-10 ..."Size Adjustments
Modify the size ranges in the useTransform calls:
// Smaller icons (30-60px range)
const widthTransform = useTransform(distance, [-150, 0, 150], [30, 60, 30])
const heightTransform = useTransform(distance, [-150, 0, 150], [30, 60, 30])
// Larger icons (50-100px range)
const widthTransform = useTransform(distance, [-150, 0, 150], [50, 100, 50])
const heightTransform = useTransform(distance, [-150, 0, 150], [50, 100, 50])Animation Physics
Adjust the spring physics for different feels:
// Bouncier animation
const width = useSpring(widthTransform, { mass: 0.2, damping: 8, stiffness: 150 })
// Smoother animation
const width = useSpring(widthTransform, { mass: 0.05, damping: 15, stiffness: 80 })Magnification Distance
Change the distance threshold for magnification effect:
// Shorter range (100px)
const widthTransform = useTransform(distance, [-100, 0, 100], [40, 80, 40])
// Longer range (200px)
const widthTransform = useTransform(distance, [-200, 0, 200], [40, 80, 40])Styling
Customize colors and appearance:
// Dock container
className="... bg-blue-100 dark:bg-blue-900"
// Icon background
className="... bg-gradient-to-br from-purple-400 to-pink-400"
// Tooltip
className="... bg-black text-white border-none"Advanced Features
External Links
For external links, replace Next.js Link with a regular anchor:
<a
href={link.href}
target="_blank"
rel="noopener noreferrer"
>
{/* icon content */}
</a>Active State
Add active state indication:
const pathname = usePathname() // Next.js 13+
const isActive = pathname === link.href
<motion.div
className={cn(
"relative flex aspect-square items-center justify-center rounded-full",
isActive
? "bg-primary text-primary-foreground"
: "bg-gray-200 dark:bg-neutral-700"
)}
style={{ width, height }}
>Click Actions
Add click handlers instead of navigation:
type LinkProps = {
label: string
onClick: () => void
icon: React.ReactNode
}
// In LinkItem component:
<button
onClick={link.onClick}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
{/* icon content */}
</button>Tips
- Keep the number of icons between 4-8 for best visual balance
- Use consistent icon styles (all outline or all filled)
- Test the magnification effect with different mouse speeds
- Consider mobile responsiveness (dock may not work well on touch devices)
- Use semantic labels for accessibility
- Ensure sufficient color contrast for icons in both light and dark modes
Browser Support
Works in all modern browsers that support:
- CSS Grid and Flexbox
- CSS backdrop-filter
- ES6+ JavaScript
- Framer Motion's animation features
For older browsers, consider adding appropriate polyfills or fallbacks.