chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
import { Link } from '#/components/atoms/link.jsx';
import { KIND_META, KIND_ORDER } from '#/lib/file-kinds.js';
import { bytes, num } from '#/lib/format.js';
import { cn } from '#/lib/utils.js';
/**
* Storage by kind as one proportional bar. Segments keep the fixed kind order
* and hues; a 2px gap of card surface separates them. Clicking a segment is
* the same act as its chip: filter to that kind.
*/
export function StorageBar({ facets, filters, hrefFor, onNavigate }) {
const present = KIND_ORDER.map((kind) =>
facets.kinds.find((facet) => facet.kind === kind),
).filter(Boolean);
if (!present.length) return null;
const summary = present
.map((f) => `${KIND_META[f.kind].label} ${bytes(f.bytes)}`)
.join(', ');
return (
<div
className="mt-3 flex h-3 w-full gap-[2px]"
role="img"
aria-label={`Storage by type: ${summary}`}
>
{present.map((facet) => (
<Link
key={facet.kind}
href={hrefFor({
...filters,
kind: filters.kind === facet.kind ? undefined : facet.kind,
})}
onNavigate={onNavigate}
title={`${KIND_META[facet.kind].label} · ${num(facet.count)} · ${bytes(facet.bytes)}`}
className={cn(
'h-full rounded-[4px] transition-opacity',
KIND_META[facet.kind].dot,
filters.kind && filters.kind !== facet.kind
? 'opacity-30 hover:opacity-60'
: 'hover:opacity-85',
)}
style={{ flexGrow: Math.max(facet.bytes, 1), flexBasis: 12 }}
/>
))}
</div>
);
}