Navigation Button

A button that changes its icon when you hover over it. Perfect for navigation and external links.

Install dependencies

npm i framer-motion

Utility function

Create a file lib/utils.ts and paste this code

import { ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); }

Navigation Button

Create a file navigation-button.tsx in your components folder and paste this code

'use client'; import { ArrowUpRight, Eye } from 'lucide-react'; import Link from 'next/link'; import React, { useState } from 'react'; import { AnimatePresence, motion } from 'framer-motion'; import { cn } from '@/lib/utils'; interface ButtonProps { text: string; href: string; target?: '_self' | '_blank' | '_parent' | '_top'; className?: string; icon?: React.ReactNode; } const NavigationButton = ({ href, text = 'Open', icon = undefined, target = '_blank', className = '' }: ButtonProps) => { const [hovered, setHovered] = useState(false); return ( <div className="flex items-start"> <Link href={href} target={target}> <AnimatePresence mode="popLayout"> <button className={cn( 'flex items-center gap-1 outline-none cursor-pointer text-zinc-400 hover:text-blue-400 font-semibold shadow-sm py-2 px-4 hover:brightness-125 active:brightness-105 transition-opacity duration-100 rounded-lg', className )} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} > {!hovered && ( <motion.div key={'eye-btn' + href} initial={{ x: -10, opacity: 0 }} animate={{ x: 0, opacity: 1 }} exit={{ x: -10, opacity: 0 }} transition={{ ease: 'linear', duration: 0.1 }} > {icon ? icon : <Eye size={14} />} </motion.div> )} <motion.p layout transition={{ duration: 0.1, ease: 'linear' }} className="text-xs sm:text-sm whitespace-nowrap" > {text} </motion.p> {hovered && ( <motion.div key={'arrow-btn' + href} initial={{ x: 10, opacity: 0 }} animate={{ x: 0, opacity: 1 }} exit={{ x: 10, opacity: 0 }} transition={{ ease: 'linear', duration: 0.1 }} > <ArrowUpRight size={14} /> </motion.div> )} </button> </AnimatePresence> </Link> </div> ); }; export default NavigationButton;

Usage

<NavigationButton href="https://twitter.com/samitkapoorr" text="Open twitter" />