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

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
47 lines · 1.6 KB Raw History
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>
  );
}