Docs
Go back
Component by
OV
OblivionTSX
mac-dock
"use client"
import React, { useRef } from "react"
import { motion, useMotionValue, useSpring, useTransform } from "framer-motion"
import { Home, Search, Bell, Settings, User } from "lucide-react"
export const componentMeta = {
name: "Mac-Style Dock",
description: "An interactive navigation dock where icons physically react and scale based on cursor proximity.",
props: {}
}
interface DockItemProps {
icon: React.ElementType
mouseX: any // MotionValue<number> but easier to use any if user hasn't typed their project
}
function DockItem({ icon: Icon, mouseX }: DockItemProps) {
const ref = useRef<HTMLDivElement>(null)
// We calculate distance from the center of this specific icon
const distance = useTransform(mouseX, (val: number) => {
const rect = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 }
return val - rect.x - rect.width / 2
})
// Width transformation based on proximity mapping
const widthSync = useTransform(distance, [-150, 0, 150], [40, 80, 40])
const width = useSpring(widthSync, { mass: 0.1, stiffness: 150, damping: 12 })
return (
<motion.div
ref={ref}
style={{ width }}
className="flex aspect-square items-center justify-center rounded-full bg-white dark:bg-zinc-800 border border-black/5 dark:border-white/10 shadow-sm transition-colors hover:bg-neutral-50 dark:hover:bg-zinc-700 mx-1"
>
<Icon className="h-2/5 w-2/5 text-neutral-600 dark:text-neutral-300" />
</motion.div>
)
}
export default function MacDock() {
const mouseX = useMotionValue(Infinity)
const items = [Home, Search, Bell, Settings, User]
return (
<div className="flex items-center justify-center w-full py-12">
<motion.div
onMouseMove={(e: React.MouseEvent) => mouseX.set(e.pageX)}
onMouseLeave={() => mouseX.set(Infinity)}
className="flex h-16 items-end rounded-2xl bg-white/50 dark:bg-zinc-900/50 backdrop-blur-xl border border-white dark:border-white/10 px-3 pb-3 pt-3 shadow-[0_0_20px_rgba(0,0,0,0.05)]"
>
{items.map((Icon, i) => (
<DockItem key={i} icon={Icon} mouseX={mouseX} />
))}
</motion.div>
</div>
)
}"use client"
import React, { useRef } from "react"
import { motion, useMotionValue, useSpring, useTransform } from "framer-motion"
import { Home, Search, Bell, Settings, User } from "lucide-react"
export const componentMeta = {
name: "Mac-Style Dock",
description: "An interactive navigation dock where icons physically react and scale based on cursor proximity.",
props: {}
}
interface DockItemProps {
icon: React.ElementType
mouseX: any // MotionValue<number> but easier to use any if user hasn't typed their project
}
function DockItem({ icon: Icon, mouseX }: DockItemProps) {
const ref = useRef<HTMLDivElement>(null)
// We calculate distance from the center of this specific icon
const distance = useTransform(mouseX, (val: number) => {
const rect = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 }
return val - rect.x - rect.width / 2
})
// Width transformation based on proximity mapping
const widthSync = useTransform(distance, [-150, 0, 150], [40, 80, 40])
const width = useSpring(widthSync, { mass: 0.1, stiffness: 150, damping: 12 })
return (
<motion.div
ref={ref}
style={{ width }}
className="flex aspect-square items-center justify-center rounded-full bg-white dark:bg-zinc-800 border border-black/5 dark:border-white/10 shadow-sm transition-colors hover:bg-neutral-50 dark:hover:bg-zinc-700 mx-1"
>
<Icon className="h-2/5 w-2/5 text-neutral-600 dark:text-neutral-300" />
</motion.div>
)
}
export default function MacDock() {
const mouseX = useMotionValue(Infinity)
const items = [Home, Search, Bell, Settings, User]
return (
<div className="flex items-center justify-center w-full py-12">
<motion.div
onMouseMove={(e: React.MouseEvent) => mouseX.set(e.pageX)}
onMouseLeave={() => mouseX.set(Infinity)}
className="flex h-16 items-end rounded-2xl bg-white/50 dark:bg-zinc-900/50 backdrop-blur-xl border border-white dark:border-white/10 px-3 pb-3 pt-3 shadow-[0_0_20px_rgba(0,0,0,0.05)]"
>
{items.map((Icon, i) => (
<DockItem key={i} icon={Icon} mouseX={mouseX} />
))}
</motion.div>
</div>
)
}Save to favoritesCopy to Figma
React
Mac-Style Dock
An interactive navigation dock where icons physically react and scale based on cursor proximity.
Installation
$ npx @cosmoo/oblivion add mac-dockDependencies
npm install framer-motion lucide-reactUsage Example
tsx
import MacDock from "@/components/oblivion/mac-dock"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<MacDock />
</div>
)
}import MacDock from "@/components/oblivion/mac-dock"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<MacDock />
</div>
)
}