copy-page-button.tsx 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. "use client";
  2. import { useState } from "react";
  3. import { usePathname } from "next/navigation";
  4. export function CopyPageButton() {
  5. const pathname = usePathname();
  6. const [state, setState] = useState<"idle" | "loading" | "copied">("idle");
  7. const handleCopy = async () => {
  8. setState("loading");
  9. try {
  10. const response = await fetch(
  11. `/api/docs-markdown?path=${encodeURIComponent(pathname)}`,
  12. );
  13. if (!response.ok) {
  14. throw new Error("Failed to fetch markdown");
  15. }
  16. const markdown = await response.text();
  17. await navigator.clipboard.writeText(markdown);
  18. setState("copied");
  19. setTimeout(() => setState("idle"), 2000);
  20. } catch {
  21. setState("idle");
  22. }
  23. };
  24. return (
  25. <button
  26. onClick={handleCopy}
  27. disabled={state === "loading"}
  28. className="flex items-center gap-1.5 px-2.5 py-1.5 text-xs text-muted-foreground hover:text-foreground border border-border rounded-md hover:bg-muted transition-colors disabled:opacity-50"
  29. aria-label="Copy page as Markdown"
  30. >
  31. {state === "copied" ? (
  32. <>
  33. <svg
  34. width="14"
  35. height="14"
  36. viewBox="0 0 24 24"
  37. fill="none"
  38. stroke="currentColor"
  39. strokeWidth="2"
  40. strokeLinecap="round"
  41. strokeLinejoin="round"
  42. >
  43. <polyline points="20 6 9 17 4 12" />
  44. </svg>
  45. Copied
  46. </>
  47. ) : (
  48. <>
  49. <svg
  50. width="14"
  51. height="14"
  52. viewBox="0 0 24 24"
  53. fill="none"
  54. stroke="currentColor"
  55. strokeWidth="2"
  56. strokeLinecap="round"
  57. strokeLinejoin="round"
  58. >
  59. <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
  60. <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
  61. </svg>
  62. Copy Page
  63. </>
  64. )}
  65. </button>
  66. );
  67. }