ApplicationAnimated Dock
Animated Dock
A dock with animated icons that grow on hover.
Preview
Code
"use client";
import React, { useRef } from "react";
import {
MotionValue,
motion,
useMotionValue,
useSpring,
useTransform,
} from "motion/react";
import clsx from "clsx";
import { twMerge } from "tailwind-merge";
import Link from "next/link";
const cn = (...args: any[]) => {
return twMerge(clsx(args));
};
interface AnimatedDockProps {
className?: string;
items: DockItemData[];
}
interface DockItemData {
link: string;
Icon: React.ReactNode;
target?: string;
}
export const AnimatedDock = ({ className, items }: AnimatedDockProps) => {
let mouseX = useMotionValue(Infinity);
return (
<motion.div
onMouseMove={(e) => mouseX.set(e.pageX)}
onMouseLeave={() => mouseX.set(Infinity)}
className={cn(
"mx-auto flex h-16 items-end gap-4 rounded-2xl bg-primary/10 shadow-md border-opacity-5 px-4 pb-3",
className,
)}
>
{items.map((item, index) => (
<DockItem key={index} mouseX={mouseX}>
<Link
href={item.link}
target={item.target}
className="grow flex items-center justify-center w-full h-full text-primary-foreground"
>
{item.Icon}
</Link>
</DockItem>
))}
</motion.div>
);
};
export const DockItem = ({
mouseX,
children,
}: {
mouseX: MotionValue;
children: React.ReactNode;
}) => {
let ref = useRef<HTMLDivElement>(null);
let distance = useTransform(mouseX, (val) => {
let bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };
return val - bounds.x - bounds.width / 2;
});
let widthSync = useTransform(distance, [-150, 0, 150], [40, 80, 40]);
let width = useSpring(widthSync, { mass: 0.1, stiffness: 150, damping: 12 });
return (
<motion.div
ref={ref}
style={{ width }}
className="aspect-square w-10 rounded-full bg-primary text-secondary-foreground flex items-center justify-center "
>
<div className="flex items-center justify-center w-full h-full grow">
{children}
</div>
</motion.div>
);
};
Usage
import { FaDiscord, FaGithub, FaLinkedin } from "react-icons/fa";
import { FaXTwitter } from "react-icons/fa6";
import { AnimatedDock } from "@/components/library/application/animated-dock";
<AnimatedDock
items={[
{
link: "https://github.com/preetsuthar17",
target: "_blank",
Icon: <FaGithub size={22} />,
},
{
link: "https://x.com/preetsuthar17",
target: "_blank",
Icon: <FaXTwitter size={22} />,
},
{
link: "https://dsc.gg/hextastudio",
target: "_blank",
Icon: <FaDiscord size={22} />,
},
{
link: "https://linkedin.com/in/preetsuthar17",
target: "_blank",
Icon: <FaLinkedin size={22} />,
},
]}
/>;
Props
AnimatedDock Props
Prop | Type | Default |
---|---|---|
className | string | - |
items | DockItemData[] | - |
DockItem Props
Prop | Type | Default |
---|---|---|
link | string | - |
Icon | ReactNode | - |
target | string | - |
Edit on GitHub
Last updated on