# Hero Orbiting Icons — Tailwind Hero Section

> An integrations hero where app icons ride three counter-rotating rings over a horizon, staying upright as they rise and set around a glowing core.

- Category: [Hero Sections](https://pixelpapa.com/components/heroes.md)
- Tags: hero, orbit, icons, integrations, loop
- Dependencies: lucide-react, motion (plus React and Tailwind CSS v4)
- Last updated: 2026-11-13
- Live preview: https://pixelpapa.com/components/heroes/hero-orbiting-icons

## Install

```bash
npx shadcn@latest add "https://pixelpapa.com/r/hero-orbiting-icons.json"
```

The file is written to `components/pixelpapa/hero-orbiting-icons.tsx`. To install manually, run `npm install lucide-react motion` and copy the source below into your project. It imports `cn` from `@/lib/utils`, which every shadcn project has.

## Source

```tsx
"use client";

import {
  ArrowRight,
  Calendar,
  ChartLine,
  Cloud,
  CreditCard,
  Database,
  FileText,
  Globe,
  Lock,
  Mail,
  MessageCircle,
  Music,
  Camera,
  type LucideIcon,
} from "lucide-react";
import { motion } from "motion/react";

type Ring = { size: number; seconds: number; reverse?: boolean; icons: LucideIcon[] };

type HeroOrbitingIconsProps = {
  rings?: Ring[];
};

const defaultRings: Ring[] = [
  { size: 340, seconds: 36, icons: [Mail, Calendar, Database, Lock] },
  { size: 580, seconds: 54, reverse: true, icons: [Cloud, CreditCard, MessageCircle, FileText, Globe, Camera] },
  { size: 820, seconds: 76, icons: [ChartLine, Music, Mail, Database, Calendar, Cloud, Lock, FileText] },
];

const ease = [0.22, 1, 0.36, 1] as const;
const tints = ["var(--chart-1)", "var(--chart-2)", "var(--chart-3)", "var(--chart-4)", "var(--chart-5)"];

export default function HeroOrbitingIcons({ rings = defaultRings }: HeroOrbitingIconsProps) {
  return (
    <section className="relative overflow-hidden bg-background px-6 pt-24 sm:pt-28">
      <style>{`
        @keyframes pp-hero-orbiting-icons-spin { to { transform: rotate(360deg); } }
        @keyframes pp-hero-orbiting-icons-pulse { 0%, 100% { opacity: 0.5; transform: scale(1); } 50% { opacity: 0.9; transform: scale(1.12); } }
      `}</style>
      <motion.div
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.8, ease }}
        className="relative z-10 mx-auto max-w-2xl text-center"
      >
        <p className="text-sm font-medium text-primary">140 integrations and counting</p>
        <h1 className="mt-4 text-5xl font-semibold tracking-tight text-balance text-foreground sm:text-6xl">
          Everything your team uses, in one orbit
        </h1>
        <p className="mx-auto mt-5 max-w-lg text-lg text-muted-foreground">
          Halo keeps your mail, calendar, billing and data in sync, so a change in one tool shows up in all the others.
        </p>
        <div className="mt-8 flex flex-wrap justify-center gap-3">
          <a href="#" className="group inline-flex h-11 items-center gap-2 rounded-full bg-primary px-6 text-sm font-medium text-primary-foreground shadow-lg shadow-primary/25">
            Connect your stack
            <ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
          </a>
          <a href="#" className="inline-flex h-11 items-center rounded-full border border-border bg-card px-6 text-sm font-medium text-foreground hover:bg-muted">
            Browse integrations
          </a>
        </div>
      </motion.div>

      {/* Only the top half of the system shows; icons rise over the horizon and set again. */}
      <motion.div
        aria-hidden
        initial={{ opacity: 0, scale: 0.9 }}
        animate={{ opacity: 1, scale: 1 }}
        transition={{ duration: 1.2, delay: 0.2, ease }}
        className="relative mx-auto mt-12 h-[450px] max-w-5xl origin-bottom [mask-image:linear-gradient(to_top,transparent,black_18%)]"
      >
        {rings.map((ring, r) => (
          <div
            key={ring.size}
            className="absolute bottom-0 left-1/2 rounded-full border border-border motion-reduce:[animation-play-state:paused]"
            style={{
              width: ring.size,
              height: ring.size,
              marginLeft: -ring.size / 2,
              marginBottom: -ring.size / 2,
              animation: `pp-hero-orbiting-icons-spin ${ring.seconds}s linear -${ring.seconds / 3}s infinite ${ring.reverse ? "reverse" : "normal"}`,
            }}
          >
            {ring.icons.map((Icon, i) => {
              const a = (i / ring.icons.length) * Math.PI * 2;
              return (
                <span
                  key={i}
                  className="absolute -mt-6 -ml-6 size-12"
                  style={{ left: `${(50 + 50 * Math.cos(a)).toFixed(2)}%`, top: `${(50 + 50 * Math.sin(a)).toFixed(2)}%` }}
                >
                  {/* Counter-rotation keeps each tile upright. */}
                  <span
                    className="flex size-12 items-center justify-center rounded-2xl border border-border bg-card shadow-lg motion-reduce:[animation-play-state:paused]"
                    style={{
                      color: tints[(i + r) % tints.length],
                      animation: `pp-hero-orbiting-icons-spin ${ring.seconds}s linear -${ring.seconds / 3}s infinite ${ring.reverse ? "normal" : "reverse"}`,
                    }}
                  >
                    <Icon className="size-5" />
                  </span>
                </span>
              );
            })}
          </div>
        ))}
        <div className="absolute bottom-0 left-1/2 -ml-16 -mb-16 flex size-32 items-start justify-center rounded-full bg-primary pt-7 text-primary-foreground shadow-2xl shadow-primary/40">
          <span
            className="absolute -inset-6 rounded-full bg-primary/30 blur-xl motion-reduce:animate-none"
            style={{ animation: "pp-hero-orbiting-icons-pulse 4s ease-in-out infinite" }}
          />
          <span className="relative size-7 rounded-full border-[6px] border-current" />
        </div>
      </motion.div>
    </section>
  );
}
```

## AI prompt

```text
Add the "Hero Orbiting Icons" component from PixelPapa UI to this project.

What it is: An integrations hero where app icons ride three counter-rotating rings over a horizon, staying upright as they rise and set around a glowing core.
Category: Hero Sections. Depends on: lucide-react, motion.

1. Install it with the shadcn CLI:
   npx shadcn@latest add "https://pixelpapa.com/r/hero-orbiting-icons.json"
   (If the CLI is unavailable, fetch that URL, write files[0].content to components/pixelpapa/hero-orbiting-icons.tsx and install the listed dependencies.)
2. Import it from "@/components/pixelpapa/hero-orbiting-icons" and place it where I describe below.
3. Keep its animation timings and accessibility attributes. Replace the demo copy and data with content that fits my product, and use my existing theme tokens (bg-background, text-foreground, bg-primary, border-border) rather than hard-coded colours.

Where to use it: <describe the page and position here>
```

## More hero sections

- [Hero Before After Toggle](https://pixelpapa.com/components/heroes/hero-before-after-toggle.md) (Pro): A hero with a Before / After switch: the same nine request cards spring from a scattered pile into three labelled, colour-coded lanes and back.
- [Hero Cursor Spotlight](https://pixelpapa.com/components/heroes/hero-cursor-spotlight.md) (Pro): An always-dark hero where a soft light trails the pointer and reveals a hidden grid of service nodes; it wanders on its own until you move.
- [Hero Dashboard Lift](https://pixelpapa.com/components/heroes/hero-dashboard-lift.md): Centered headline over a product window that tilts flat as you scroll, with staggered entrance.
- [Hero Drifting Card Rows](https://pixelpapa.com/components/heroes/hero-drifting-card-rows.md) (Pro): Three tilted rows of small UI cards drift in opposite directions behind a headline that sits in a soft cleared pocket.
- [Hero Editorial Serif](https://pixelpapa.com/components/heroes/hero-editorial-serif.md) (Pro): A magazine-style opener: an oversized serif headline rises line by line from behind hairlines that draw across an asymmetric grid.
- [Hero Grid Cells Reveal](https://pixelpapa.com/components/heroes/hero-grid-cells-reveal.md): A hero on a spreadsheet-like grid where cells light up in rings that ripple out from the headline, and individual cells glow under the pointer.
