# Navbar Pill Glide

> A navbar with its links in a frosted pill, where a soft highlight glides to whichever link you point at and a lime line along the pill tracks how far down the page you are. The logo dot circles its ring as you scroll, the bar slips away going down, and on narrow screens a round toggle wipes the full menu open from where it sits, with large rolling links and a poster that swaps as you hover them.

A shadcn/ui block from the [@tween-ui](https://tween-ui.vercel.app) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/tween-ui/navbar-pill-glide).

- Page, with a live preview: https://shadcn.exchange/r/tween-ui/navbar-pill-glide
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/tween-ui/navbar-pill-glide-light-fe47bc07829f84f1.png
- Registry item: https://tween-ui.vercel.app/r/navbar-pill-glide.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://tween-ui.vercel.app/r/navbar-pill-glide.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `@gsap/react`, `gsap`

## Notes from the registry

Docs, props and examples: https://tween-ui.vercel.app/block/navbar-pill-glide
Pass your own `links` and put your page inside as `children`; every link but home goes in the pill, and all of them fill the mobile menu.

## Files

### `components/tweenui/navbar-pill-glide.tsx`

```tsx
'use client';

import {
  useCallback,
  useEffect,
  useId,
  useRef,
  useState,
  type ComponentPropsWithoutRef,
  type ReactNode,
} from 'react';
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';
import { cn } from '@/lib/utils';

gsap.registerPlugin(useGSAP);

const prefersReducedMotion = () =>
  typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

export interface NavbarPillGlideLink {
  label: string;
  href: string;
  image?: string;
}

export interface NavbarPillGlideAction {
  label: string;
  href: string;
}

export type NavbarPillGlideSocialIcon = 'github' | 'x' | 'linkedin' | 'dribbble';

export interface NavbarPillGlideSocial {
  label: string;
  href: string;
  icon: NavbarPillGlideSocialIcon;
}

export interface NavbarPillGlideProps extends Omit<
  ComponentPropsWithoutRef<'section'>,
  'children'
> {
  brand?: string;
  logo?: ReactNode;
  homeHref?: string;
  links?: NavbarPillGlideLink[];
  currentHref?: string;
  primaryAction?: NavbarPillGlideAction;
  secondaryAction?: NavbarPillGlideAction;
  socials?: NavbarPillGlideSocial[];
  email?: string;
  children?: ReactNode;
}

const SITE = 'https://tween-ui.vercel.app';
const REPO = 'https://github.com/StaticMania/tween-ui';

const poster = (kind: 'block' | 'component', name: string) =>
  `${SITE}/media/${kind}s/${name}-poster.webp`;

const DEFAULT_LINKS: NavbarPillGlideLink[] = [
  { label: 'Home', href: '/', image: poster('block', 'gyro-gallery') },
  { label: 'Components', href: '/components', image: poster('component', 'sliding-tabs') },
  { label: 'Blocks', href: '/components#blocks', image: poster('block', 'shutter-slider') },
  { label: 'Setup', href: '/installation/setup-guide', image: poster('block', 'integration-hub') },
  { label: 'MCP', href: '/installation/mcp', image: poster('block', 'kinetic-type-ring') },
];

const DEFAULT_PRIMARY: NavbarPillGlideAction = {
  label: 'Get started',
  href: '/installation/setup-guide',
};

const DEFAULT_SECONDARY: NavbarPillGlideAction = { label: 'GitHub', href: REPO };

const DEFAULT_SOCIALS: NavbarPillGlideSocial[] = [{ label: 'GitHub', href: REPO, icon: 'github' }];

const TWEEN_MARK = (
  <svg aria-hidden="true" viewBox="0 0 24 24" className="size-7 shrink-0">
    <rect width="24" height="24" rx="6" fill="#045f64" />
    <path
      d="M5 19 C 9.5 8.9, 5 5, 19 5"
      fill="none"
      stroke="#c6f56f"
      strokeWidth="2"
      strokeLinecap="round"
    />
    <circle cx="19" cy="5" r="1.8" fill="#c6f56f" />
  </svg>
);

const CONTAINER = 'mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8';

const HIDE_AFTER = 240;
const SCROLL_TOLERANCE = 6;
const DESKTOP_QUERY = '(min-width: 1024px)';

const EASE_OUT_EXPO = 'ease-[cubic-bezier(0.16,1,0.3,1)]';

const focusRing =
  'focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-[#c6f56f]';

const SOCIAL_PATHS: Record<NavbarPillGlideSocialIcon, ReactNode> = {
  github: (
    <>
      <path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4" />
      <path d="M9 18c-4.51 2-5-2-7-2" />
    </>
  ),
  x: (
    <path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z" />
  ),
  linkedin: (
    <>
      <path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z" />
      <rect width="4" height="12" x="2" y="9" />
      <circle cx="4" cy="4" r="2" />
    </>
  ),
  dribbble: (
    <>
      <circle cx="12" cy="12" r="10" />
      <path d="M19.13 5.09C15.22 9.14 10 10.44 2.25 10.94" />
      <path d="M21.75 12.84c-6.62-1.41-12.14 1-16.38 6.32" />
      <path d="M8.56 2.75c4.37 6 6 9.42 8 17.72" />
    </>
  ),
};

const cleanHref = (href: string) => href.split(/[?#]/)[0]?.replace(/\/+$/, '') || '/';

const isCurrentHref = (href: string, currentHref: string) => {
  const target = cleanHref(href);
  const current = cleanHref(currentHref);
  if (target === '/') return current === '/';
  return current === target || current.startsWith(`${target}/`);
};

const isExternal = (href: string) => /^https?:/.test(href);

const externalProps = (href: string) =>
  isExternal(href) ? { target: '_blank', rel: 'noopener noreferrer' } : {};

function RollText({ text, className }: { text: string; className?: string }) {
  return (
    <>
      <span
        aria-hidden="true"
        className={cn('inline-flex h-[1.2em] overflow-hidden leading-[1.2em]', className)}
      >
        {Array.from(text).map((char, index) => (
          <span
            key={`${char}-${index}`}
            className={cn(
              'inline-block whitespace-pre [text-shadow:0_1.2em_currentColor]',
              'transition-transform duration-[550ms] group-hover/roll:-translate-y-full group-focus-visible/roll:-translate-y-full',
              EASE_OUT_EXPO,
              'motion-reduce:transition-none motion-reduce:group-hover/roll:translate-y-0 motion-reduce:group-focus-visible/roll:translate-y-0'
            )}
            style={{ transitionDelay: `${index * 16}ms` }}
          >
            {char}
          </span>
        ))}
      </span>
      <span className="sr-only">{text}</span>
    </>
  );
}

function ArrowSwap() {
  const arrowClass = cn(
    'col-start-1 row-start-1 size-4 transition-transform duration-[550ms] motion-reduce:transition-none',
    EASE_OUT_EXPO
  );
  const arrowPath = <path d="M7 17 17 7M7 7h10v10" />;

  return (
    <span aria-hidden="true" className="grid size-4 overflow-hidden">
      {[
        'group-hover/roll:translate-x-[110%] group-hover/roll:-translate-y-[110%]',
        '-translate-x-[110%] translate-y-[110%] group-hover/roll:translate-0',
      ].map((motion) => (
        <svg
          key={motion}
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
          className={cn(arrowClass, motion)}
        >
          {arrowPath}
        </svg>
      ))}
    </span>
  );
}

function ActionLink({
  action,
  variant,
  className,
}: {
  action: NavbarPillGlideAction;
  variant: 'primary' | 'outline';
  className?: string;
}) {
  return (
    <a
      href={action.href}
      {...externalProps(action.href)}
      className={cn(
        'group/roll relative isolate inline-flex h-11 items-center justify-center gap-3 overflow-hidden rounded-full px-5 text-[15px] font-medium whitespace-nowrap',
        'transition-[scale,color,border-color] duration-500 active:scale-[0.96] motion-reduce:transition-none',
        EASE_OUT_EXPO,
        focusRing,
        variant === 'primary'
          ? 'bg-[#c6f56f] text-[#03110f]'
          : 'border border-[#9fd4d6]/25 text-[#e8f3f2] hover:border-[#e8f3f2] hover:text-[#03110f]',
        className
      )}
    >
      <span
        aria-hidden="true"
        className={cn(
          'pointer-events-none absolute top-1/2 left-1/2 -z-10 aspect-square w-[260%] -translate-1/2 scale-0 rounded-full bg-[#e8f3f2] transition-transform duration-[650ms] group-hover/roll:scale-100 motion-reduce:transition-none',
          EASE_OUT_EXPO
        )}
      />
      <RollText text={action.label} />
      {variant === 'primary' ? <ArrowSwap /> : null}
    </a>
  );
}

function SamplePage({ linkCount }: { linkCount: number }) {
  const headingId = useId();

  return (
    <section
      aria-labelledby={headingId}
      className="relative isolate flex h-full min-h-full flex-col overflow-hidden pt-24 pb-10 sm:pt-28 sm:pb-14"
    >
      <span
        aria-hidden="true"
        className="pointer-events-none absolute inset-0 -z-10 bg-[repeating-linear-gradient(90deg,rgb(159_212_214/0.06)_0_1px,transparent_1px_48px),repeating-linear-gradient(0deg,rgb(159_212_214/0.045)_0_1px,transparent_1px_48px)] [mask-image:radial-gradient(ellipse_75%_65%_at_50%_40%,black,transparent)]"
      />
      <span
        aria-hidden="true"
        className="pointer-events-none absolute inset-0 -z-10 bg-[radial-gradient(38%_46%_at_50%_0%,rgb(198_245_111/0.12),transparent_70%),radial-gradient(55%_60%_at_92%_100%,rgb(4_95_100/0.6),transparent_72%),radial-gradient(45%_50%_at_6%_90%,rgb(4_95_100/0.35),transparent_70%)]"
      />
      <div className={cn(CONTAINER, 'flex flex-1 items-center')}>
        <div className="mx-auto max-w-4xl text-center">
          <p className="inline-flex items-center gap-2.5 rounded-full bg-white/[0.04] py-2 pr-4 pl-2.5 text-[10px] leading-none font-medium tracking-[0.2em] text-[#9fd4d6] uppercase ring-1 ring-white/10">
            <span
              aria-hidden="true"
              className="size-2 shrink-0 rounded-full bg-[#c6f56f] shadow-[0_0_5px_#c6f56f,0_0_12px_#c6f56f]"
            />
            {linkCount} links in one pill
          </p>
          <h2
            id={headingId}
            className="mt-8 text-[40px] leading-[0.98] font-medium tracking-[-0.045em] text-balance text-[#e8f3f2] sm:text-6xl md:text-7xl lg:text-[80px]"
          >
            Point at a link.
            <br />
            The pill <span className="text-[#c6f56f]">follows.</span>
          </h2>
          <p className="mx-auto mt-6 max-w-[34rem] text-[15px] leading-relaxed text-pretty text-[#e8f3f2]/60 sm:mt-8 sm:text-base md:text-lg">
            Sweep across the links above and the highlight glides between them. On a narrower screen
            the round button opens the full menu from where it sits.
          </p>
        </div>
      </div>
    </section>
  );
}

export default function NavbarPillGlide({
  brand = 'Tween UI',
  logo = TWEEN_MARK,
  homeHref = '/',
  links = DEFAULT_LINKS,
  currentHref = '/',
  primaryAction = DEFAULT_PRIMARY,
  secondaryAction = DEFAULT_SECONDARY,
  socials = DEFAULT_SOCIALS,
  email,
  children,
  className,
  ...props
}: NavbarPillGlideProps) {
  const [isOpen, setIsOpen] = useState(false);
  const [previewHref, setPreviewHref] = useState(links[0]?.href ?? '');
  const menuId = useId();

  const rootRef = useRef<HTMLElement>(null);
  const barRef = useRef<HTMLDivElement>(null);
  const pillRef = useRef<HTMLDivElement>(null);
  const highlightRef = useRef<HTMLSpanElement>(null);
  const progressRef = useRef<HTMLSpanElement>(null);
  const toggleRef = useRef<HTMLButtonElement>(null);
  const menuRef = useRef<HTMLDivElement>(null);
  const scrollerRef = useRef<HTMLDivElement>(null);
  const timelineRef = useRef<gsap.core.Timeline | null>(null);
  const isOpenRef = useRef(false);

  const pillLinks = links.filter((link) => cleanHref(link.href) !== cleanHref(homeHref));
  const previews = links.filter((link): link is Required<NavbarPillGlideLink> =>
    Boolean(link.image)
  );

  const { contextSafe } = useGSAP(
    () => {
      const bar = barRef.current;
      if (!bar || prefersReducedMotion()) return;
      gsap.fromTo(
        bar.querySelectorAll('[data-nav-item]'),
        { autoAlpha: 0, y: -24 },
        { autoAlpha: 1, y: 0, duration: 1, ease: 'expo.out', stagger: 0.08, clearProps: 'all' }
      );
    },
    { scope: rootRef }
  );

  const glideTo = contextSafe((link: HTMLElement) => {
    const pill = pillRef.current;
    const highlight = highlightRef.current;
    if (!pill || !highlight) return;
    const box = link.getBoundingClientRect();
    const base = pill.getBoundingClientRect();
    const isHidden = Number(gsap.getProperty(highlight, 'opacity')) === 0;
    gsap.to(highlight, {
      x: box.left - base.left,
      width: box.width,
      opacity: 1,
      duration: isHidden || prefersReducedMotion() ? 0 : 0.55,
      ease: 'expo.out',
    });
  });

  const fadeHighlight = contextSafe(() => {
    gsap.to(highlightRef.current, { opacity: 0, duration: 0.35, ease: 'power2.out' });
  });

  const animateMenu = contextSafe((open: boolean) => {
    const root = rootRef.current;
    const menu = menuRef.current;
    const toggle = toggleRef.current;
    if (!root || !menu || !toggle) return;
    const rootBox = root.getBoundingClientRect();
    const toggleBox = toggle.getBoundingClientRect();
    const at = `${toggleBox.left - rootBox.left + toggleBox.width / 2}px ${toggleBox.top - rootBox.top + toggleBox.height / 2}px`;
    const items = menu.querySelectorAll('[data-menu-link]');
    const meta = menu.querySelector('[data-menu-meta]');
    timelineRef.current?.kill();

    if (prefersReducedMotion()) {
      gsap.set(menu, {
        visibility: open ? 'visible' : 'hidden',
        clipPath: open ? 'none' : `circle(0% at ${at})`,
      });
      gsap.set(items, { yPercent: 0 });
      gsap.set(meta, { opacity: 1, y: 0 });
      return;
    }

    timelineRef.current = open
      ? gsap
          .timeline()
          .set(menu, { visibility: 'visible' })
          .fromTo(
            menu,
            { clipPath: `circle(0% at ${at})` },
            { clipPath: `circle(150% at ${at})`, duration: 1, ease: 'expo.inOut' }
          )
          .fromTo(
            items,
            { yPercent: 110 },
            { yPercent: 0, duration: 0.9, ease: 'expo.out', stagger: 0.06 },
            0.35
          )
          .fromTo(
            meta,
            { opacity: 0, y: 20 },
            { opacity: 1, y: 0, duration: 0.6, ease: 'power3.out' },
            0.6
          )
      : gsap
          .timeline()
          .to(items, { yPercent: -110, duration: 0.45, ease: 'power3.in', stagger: 0.03 })
          .to(menu, { clipPath: `circle(0% at ${at})`, duration: 0.8, ease: 'expo.inOut' }, 0.15)
          .set(menu, { visibility: 'hidden' });
  });

  const setOpen = useCallback(
    (open: boolean) => {
      if (open === isOpenRef.current) return;
      isOpenRef.current = open;
      setIsOpen(open);
      animateMenu(open);
      if (open) gsap.to(barRef.current, { yPercent: 0, duration: 0.8, ease: 'expo.out' });
    },
    [animateMenu]
  );

  useEffect(() => {
    const scroller = scrollerRef.current;
    const bar = barRef.current;
    const progress = progressRef.current;
    if (!scroller || !bar || !progress) return;
    let lastY = scroller.scrollTop;
    let isHidden = false;

    const handleScroll = () => {
      const y = scroller.scrollTop;
      const room = scroller.scrollHeight - scroller.clientHeight;
      const ratio = room > 0 ? y / room : 0;
      const isQuiet = prefersReducedMotion();
      gsap.to(progress, { scaleX: ratio, duration: isQuiet ? 0 : 0.4, ease: 'power2.out' });

      const delta = y - lastY;
      if (Math.abs(delta) < SCROLL_TOLERANCE) return;
      lastY = y;
      const shouldHide = delta > 0 && y > HIDE_AFTER && !isOpenRef.current;
      if (shouldHide === isHidden) return;
      isHidden = shouldHide;
      gsap.to(bar, {
        yPercent: isHidden ? -130 : 0,
        duration: isQuiet ? 0 : isHidden ? 0.5 : 0.8,
        ease: isHidden ? 'power3.in' : 'expo.out',
      });
    };

    scroller.addEventListener('scroll', handleScroll, { passive: true });
    return () => scroller.removeEventListener('scroll', handleScroll);
  }, []);

  useEffect(() => {
    if (!isOpen) return;
    const desktop = window.matchMedia(DESKTOP_QUERY);
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key !== 'Escape') return;
      setOpen(false);
      toggleRef.current?.focus();
    };
    const handleDesktop = (event: MediaQueryListEvent) => {
      if (event.matches) setOpen(false);
    };
    document.addEventListener('keydown', handleKeyDown);
    desktop.addEventListener('change', handleDesktop);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      desktop.removeEventListener('change', handleDesktop);
    };
  }, [isOpen, setOpen]);

  return (
    <section
      ref={rootRef}
      aria-label={`${brand} site`}
      className={cn(
        'relative isolate h-svh min-h-[560px] w-full overflow-hidden bg-[#03110f] text-[#e8f3f2]',
        className
      )}
      {...props}
    >
      <header className="pointer-events-none absolute inset-x-0 top-0 z-30">
        <div ref={barRef} className={cn(CONTAINER, 'flex h-20 items-center justify-between gap-6')}>
          <a
            href={homeHref}
            data-nav-item=""
            aria-label={`${brand} home`}
            className={cn(
              'group/roll pointer-events-auto inline-flex items-center gap-2.5 rounded-full text-[#e8f3f2]',
              focusRing
            )}
          >
            {logo}
            <RollText text={brand} className="text-lg font-semibold tracking-tight" />
          </a>

          {pillLinks.length > 0 ? (
            <nav
              aria-label="Primary"
              data-nav-item=""
              className="pointer-events-auto hidden lg:block"
            >
              <div
                ref={pillRef}
                onMouseLeave={fadeHighlight}
                className="relative rounded-full border border-[#9fd4d6]/15 bg-[#071d1b]/70 p-1 backdrop-blur-xl"
              >
                <span
                  ref={highlightRef}
                  aria-hidden="true"
                  className="absolute inset-y-1 left-0 rounded-full bg-[#e8f3f2]/10 opacity-0"
                />
                <ul className="relative flex items-center">
                  {pillLinks.map((link) => {
                    const isCurrent = isCurrentHref(link.href, currentHref);
                    return (
                      <li key={`${link.label}-${link.href}`}>
                        <a
                          href={link.href}
                          {...externalProps(link.href)}
                          aria-current={isCurrent ? 'page' : undefined}
                          onMouseEnter={(event) => glideTo(event.currentTarget)}
                          onFocus={(event) => glideTo(event.currentTarget)}
                          onBlur={fadeHighlight}
                          className={cn(
                            'group/roll flex h-10 items-center rounded-full px-4 text-sm font-medium transition-colors duration-300 hover:text-[#e8f3f2] focus-visible:outline-2 focus-visible:outline-[#c6f56f]',
                            isCurrent ? 'text-[#e8f3f2]' : 'text-[#9fd4d6]/70'
                          )}
                        >
                          <RollText text={link.label} />
                        </a>
                      </li>
                    );
                  })}
                </ul>
                <span
                  ref={progressRef}
                  aria-hidden="true"
                  className="absolute inset-x-6 -bottom-px h-px origin-left scale-x-0 bg-[#c6f56f]"
                />
              </div>
            </nav>
          ) : null}

          <div data-nav-item="" className="pointer-events-auto flex items-center gap-2">
            <ActionLink
              action={secondaryAction}
              variant="outline"
              className="hidden xl:inline-flex"
            />
            <ActionLink action={primaryAction} variant="primary" className="max-[400px]:px-4" />
            <button
              ref={toggleRef}
              type="button"
              aria-label={isOpen ? 'Close menu' : 'Open menu'}
              aria-expanded={isOpen}
              aria-controls={menuId}
              onClick={() => setOpen(!isOpenRef.current)}
              className={cn(
                'grid size-11 cursor-pointer place-items-center rounded-full border border-[#9fd4d6]/15 bg-[#071d1b]/70 backdrop-blur-xl lg:hidden',
                focusRing
              )}
            >
              <span aria-hidden="true" className="relative block h-3 w-5">
                <span
                  className={cn(
                    'absolute inset-x-0 top-0 h-px bg-[#e8f3f2] transition-transform duration-500 motion-reduce:transition-none',
                    EASE_OUT_EXPO,
                    isOpen && 'translate-y-[5.5px] rotate-45'
                  )}
                />
                <span
                  className={cn(
                    'absolute inset-x-0 bottom-0 h-px bg-[#e8f3f2] transition-transform duration-500 motion-reduce:transition-none',
                    EASE_OUT_EXPO,
                    isOpen && '-translate-y-[5.5px] -rotate-45'
                  )}
                />
              </span>
            </button>
          </div>
        </div>
      </header>

      <div
        ref={menuRef}
        id={menuId}
        inert={!isOpen}
        className="invisible absolute inset-0 z-20 bg-[#03110f] [clip-path:circle(0%_at_100%_0%)]"
      >
        <div className={cn(CONTAINER, 'grid h-full grid-cols-1 gap-10 pt-28 pb-8 md:grid-cols-12')}>
          <nav aria-label="Menu" className="flex min-h-0 flex-col justify-between md:col-span-7">
            <ul className="flex flex-col">
              {links.map((link) => (
                <li key={`${link.label}-${link.href}`} className="overflow-hidden">
                  <a
                    href={link.href}
                    {...externalProps(link.href)}
                    data-menu-link=""
                    aria-current={isCurrentHref(link.href, currentHref) ? 'page' : undefined}
                    onMouseEnter={() => setPreviewHref(link.href)}
                    onFocus={() => setPreviewHref(link.href)}
                    className={cn(
                      'group/roll flex items-baseline py-1 text-[clamp(2.5rem,11vw,5.5rem)] leading-none font-bold tracking-[-0.04em] text-[#e8f3f2] aria-[current=page]:text-[#c6f56f]',
                      focusRing
                    )}
                  >
                    <RollText text={link.label} />
                  </a>
                </li>
              ))}
            </ul>
            <div data-menu-meta="" className="flex flex-wrap items-center gap-3">
              {socials.map((social) => (
                <a
                  key={social.href}
                  href={social.href}
                  target="_blank"
                  rel="noopener noreferrer"
                  aria-label={`${brand} on ${social.label}`}
                  className={cn(
                    'grid size-11 place-items-center rounded-full border border-[#9fd4d6]/15 text-[#9fd4d6]/70 transition-colors duration-300 hover:border-[#e8f3f2] hover:text-[#e8f3f2]',
                    focusRing
                  )}
                >
                  <svg
                    aria-hidden="true"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    strokeWidth="2"
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    className="size-5"
                  >
                    {SOCIAL_PATHS[social.icon]}
                  </svg>
                </a>
              ))}
              {email ? (
                <a
                  href={`mailto:${email}`}
                  className={cn(
                    'group/roll ml-auto rounded-xs text-sm text-[#9fd4d6]/70 transition-colors duration-300 hover:text-[#e8f3f2]',
                    focusRing
                  )}
                >
                  <RollText text={email} />
                </a>
              ) : null}
            </div>
          </nav>
          {previews.length > 0 ? (
            <div
              aria-hidden="true"
              className="relative hidden overflow-hidden rounded-2xl border border-[#9fd4d6]/12 bg-[#071d1b] md:col-span-5 md:block"
            >
              {previews.map((link) => (
                <img
                  key={link.href}
                  src={link.image}
                  alt=""
                  draggable={false}
                  loading="lazy"
                  className={cn(
                    'absolute inset-0 size-full object-cover transition-[opacity,scale] duration-700 motion-reduce:transition-none',
                    EASE_OUT_EXPO,
                    link.href === previewHref ? 'scale-100 opacity-100' : 'scale-[1.06] opacity-0'
                  )}
                />
              ))}
            </div>
          ) : null}
        </div>
      </div>

      <div
        ref={scrollerRef}
        inert={isOpen}
        data-lenis-prevent=""
        className="absolute inset-0 z-10 [scrollbar-width:none] overflow-y-auto [&::-webkit-scrollbar]:hidden"
      >
        {children ?? <SamplePage linkCount={pillLinks.length} />}
      </div>
    </section>
  );
}
```
