Skip to content
FreeInteractive

Animated Tooltip

Use this component in team sections, social proof rows, project collaborators, user presence indicators, and account switchers.

ReactTailwind CSSMotionTooltip

Tyler Reed

Frontend Engineer

Overview

An avatar group with animated hover tooltips for teams, users, and collaborators.

Framework

React

Styling

Tailwind CSS

Animation

Motion

Create a Vite React project

bash
npm create vite@latest my-ui-app -- --template react-ts
cd my-ui-app
npm install

Create a Next.js project

bash
npx create-next-app@latest my-ui-app --typescript --tailwind --eslint
cd my-ui-app

Add Tailwind CSS to Vite

bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Install dependencies

bash
npm install framer-motion

Usage

tsx
<AnimatedTooltip />

Animated Tooltip.tsx

tsx
"use client";

import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";

const people = [
  ["AM", "Ava Morgan", "Product Lead", "from-lime-300 to-sky-400"],
  ["TR", "Tyler Reed", "Frontend Engineer", "from-sky-400 to-purple-400"],
  ["NS", "Nia Shah", "UX Designer", "from-rose-400 to-amber-300"],
  ["IK", "Ishan Kapoor", "Founder", "from-teal-300 to-lime-300"],
  ["ML", "Maya Lin", "PM", "from-purple-400 to-rose-400"],
];

export function AnimatedTooltip() {
  const [active, setActive] = useState(1);

  return (
    <div className="flex -space-x-3">
      {people.map(([initials, name, role, gradient], index) => (
        <div key={name} className="relative">
          <button
            type="button"
            onMouseEnter={() => setActive(index)}
            onFocus={() => setActive(index)}
            className={"flex h-11 w-11 items-center justify-center rounded-full border-2 border-zinc-950 bg-gradient-to-br text-xs font-black text-white " + gradient}
          >
            {initials}
          </button>
          <AnimatePresence>
            {active === index && (
              <motion.div
                initial={{ opacity: 0, y: 8, scale: 0.94 }}
                animate={{ opacity: 1, y: -8, scale: 1 }}
                exit={{ opacity: 0, y: 8, scale: 0.94 }}
                className="absolute bottom-full left-1/2 z-10 mb-2 w-max -translate-x-1/2 rounded-lg bg-white px-3 py-2 text-center text-xs text-zinc-950 shadow-xl"
              >
                <p className="font-bold">{name}</p>
                <p className="text-zinc-500">{role}</p>
              </motion.div>
            )}
          </AnimatePresence>
        </div>
      ))}
    </div>
  );
}