chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
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>
);
}