jacquardSnapshot

← snapshot

1170 bytes
"use client";

import Link from "next/link";
import { useState } from "react";

const PREFIX_LEN = 12;

/**
 * A content address, shown short, carried full. Short forms are display
 * only — never compare them — so the full id rides in the title and the
 * clipboard.
 */
export function IdChip({
  id,
  kind,
  href,
}: {
  id: string;
  /** Display prefix: snap, dec, att, tree, blob. */
  kind?: string;
  href?: string;
}) {
  const [copied, setCopied] = useState(false);
  const short = `${kind ? `${kind}:` : ""}${id.slice(0, PREFIX_LEN)}`;

  async function copy() {
    try {
      await navigator.clipboard.writeText(id);
      setCopied(true);
      setTimeout(() => setCopied(false), 1200);
    } catch {
      // clipboard unavailable — the title still shows the full id
    }
  }

  if (href) {
    return (
      <Link href={href} className="jac-chip" title={id}>
        {short}
      </Link>
    );
  }
  return (
    <button type="button" className="jac-chip" title={`${id} — click to copy`} onClick={copy}>
      {short}
      <span className="jac-small" aria-live="polite">
        {copied ? "copied" : ""}
      </span>
    </button>
  );
}