import type { ReactNode } from "react";
import { useEffect, useState } from "react";
import { cn, Icon, Tip } from "../kit";
/** Copy a value from the page. The tip says Copied for a moment, and a screen reader hears it. */
export function CopyButton({ value, label }: { value: string; label: string }) {
const [copied, setCopied] = useState(false);
useEffect(() => {
if (!copied) return;
const t = setTimeout(() => setCopied(false), 1600);
return () => clearTimeout(t);
}, [copied]);
const copy = async () => {
try {
await navigator.clipboard.writeText(value);
setCopied(true);
} catch {
// No clipboard here: the value stays on screen to select by hand.
}
};
return (
<span className="inline-flex">
<Tip label={copied ? "Copied" : "Copy"}>
<button
type="button"
aria-label={label}
// Prevent the default so the tip stays open to say Copied.
onPointerDown={(e) => e.preventDefault()}
onClick={(e) => {
e.preventDefault();
void copy();
}}
className={cn(
"inline-flex size-6 cursor-pointer items-center justify-center rounded-md border-0 bg-transparent p-0 transition-colors outline-none hover:bg-quiet hover:text-ink focus-visible:shadow-[0_0_0_2px_var(--color-brand)]",
copied ? "text-green-icon" : "text-subtle",
)}
>
<Icon name={copied ? "check-line" : "file-copy-line"} size={14} />
</button>
</Tip>
<span role="status" className="sr-only">
{copied ? "Copied" : ""}
</span>
</span>
);
}
/** A section's quiet line under its title. */
export const SectionNote = ({ children }: { children: ReactNode }) => <p className="m-0 text-[13.5px] leading-5 text-muted">{children}</p>;