SPB Git forge

spb/countryatlas

Public
20commits 1branches 0releases
268.3 MBsize
maindefault branch
12 days agolast push
TypeScript 57% Python 38.6% JavaScript 3.6% CSS 0.6%
1.9 KB · 46 lines tsx
Raw Blame History
1'use client';2import { Check, Copy } from 'lucide-react';3import { useState } from 'react';4import { t } from '@/i18n';5import { cn } from '@/lib/cn';67/** Small "Copy" button for code snippets (clipboard API; falls back to a hidden textarea select). */8export function CopyButton({ text, className, label }: { text: string; className?: string; label?: string }) {9  const [done, setDone] = useState(false);10  const copy = async () => {11    try {12      await navigator.clipboard.writeText(text);13    } catch {14      const ta = document.createElement('textarea');15      ta.value = text;16      document.body.appendChild(ta);17      ta.select();18      document.execCommand('copy');19      ta.remove();20    }21    setDone(true);22    setTimeout(() => setDone(false), 1600);23  };24  return (25    <button type="button" onClick={copy} className={cn('inline-flex min-h-[36px] items-center gap-1 rounded-sm border border-rule px-2 text-xs text-ink-2 hover:bg-surface-2 hover:text-ink', className)} aria-live="polite">26      {done ? <Check size={13} aria-hidden /> : <Copy size={13} aria-hidden />}27      {done ? t('indicator.copied') : label ?? t('indicator.copy')}28    </button>29  );30}3132/** Monospace code block with a thin toolbar (language · copy) above the scrollable code — the button never covers code. */33export function CodeBlock({ code, className, lang }: { code: string; className?: string; lang?: string }) {34  return (35    <div className={cn('min-w-0 rounded-sm border border-rule bg-surface', className)}>36      <div className="flex items-center justify-between gap-2 border-b border-rule px-2 py-1">37        <span className="font-mono text-2xs uppercase tracking-wide text-ink-3">{lang ?? ''}</span>38        <CopyButton text={code} className="min-h-[32px] border-0" />39      </div>40      <pre className="overflow-x-auto p-3 font-mono text-xs leading-relaxed text-ink" data-lang={lang}>41        <code>{code}</code>42      </pre>43    </div>44  );45}46