~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
57 lines · 2.0 KB Raw History
import { useEffect, useRef } from 'react';
import { Count } from '#/components/atoms/count.jsx';
import { Link } from '#/components/atoms/link.jsx';
import { cn } from '#/lib/utils.js';

/**
 * A row of tabs, each one a real address.
 *
 * Tabs held in component state look the same and share nothing: a reload
 * lands on the first one and a shared link points at the wrong view. Each of
 * these is a link, so the browser's own history and a copied URL both work.
 *
 * Pass `tabs` as `{key, href, label, count}`. A count of 0 is printed, since
 * "0 offered" is an answer and an absent number is not. The row scrolls
 * sideways where a narrow window cannot hold every tab, so a label never
 * wraps onto a second line, and the open tab brings itself into view.
 */
export function TabBar({ tabs, active, className }) {
  const open = useRef(null);
  useEffect(() => {
    open.current?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
  }, []);

  return (
    <div
      className={cn(
        '-mb-px flex min-w-0 gap-1 touch-pan-x overflow-x-auto overflow-y-hidden overscroll-x-contain border-border border-b [scrollbar-width:none]',
        className,
      )}
      role="tablist"
    >
      {tabs.map((tab) => {
        const current = tab.key === active;
        return (
          <Link
            key={tab.key}
            ref={current ? open : undefined}
            href={tab.href}
            role="tab"
            aria-selected={current}
            className={cn(
              'flex shrink-0 items-center gap-1.5 whitespace-nowrap border-b-2 px-3 py-2.5 text-[13px] no-underline transition-colors hover:no-underline',
              current
                ? 'border-key font-medium text-foreground'
                : 'border-transparent text-muted-foreground hover:text-foreground',
            )}
          >
            {tab.label}
            {tab.count !== undefined && (
              <Count value={tab.count} active={current} />
            )}
          </Link>
        );
      })}
    </div>
  );
}