42 lines · 1.3 KB
import { cn } from "~/utils/cn";
import { TONE_SURFACE, type Tone } from "~/ui/tones";

type Props = {
  tone?: Tone;
  /** `output` renders a live region for values that appear after an action (tokens, secrets). */
  as?: "div" | "output" | "p" | "li";
  /** Use `alert` for errors that need announcing. */
  role?: "alert" | "status";
  children: React.ReactNode;
  className?: string;
};

export function Callout({ tone = "neutral", as: Tag = "div", role, children, className }: Props) {
  return (
    <Tag role={role} className={cn("block rounded-md px-3 py-2 text-sm", TONE_SURFACE[tone], className)}>
      {children}
    </Tag>
  );
}

export function ErrorBanner({ message }: { message: string | null }) {
  if (!message) return null;
  return (
    <Callout tone="danger" role="alert">
      {message}
    </Callout>
  );
}

const SHOWN_ONCE = "Copy it now — it won't be shown again.";

/** One-time reveal of a freshly minted secret, announced via a live region. */
export function SecretReveal({ value, hint = SHOWN_ONCE }: { value: string; hint?: React.ReactNode }) {
  return (
    <Callout as="output" tone="success" className="space-y-1 p-3">
      <p className="text-xs">{hint}</p>
      <code className="block font-mono text-sm break-all text-white">{value}</code>
    </Callout>
  );