nexus/ui/src/components/ThemeExportTabs.tsx

102 lines
2.5 KiB
TypeScript

import { useCallback, useState } from "react";
import { Copy, Check } from "lucide-react";
import {
Tabs,
TabsList,
TabsTrigger,
TabsContent,
} from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface ThemeExports {
css: string;
tailwind: string;
vscode: string;
json: string;
}
interface ThemeExportTabsProps {
exports: ThemeExports;
className?: string;
}
type TabKey = "css" | "tailwind" | "vscode" | "json";
const TABS: { key: TabKey; label: string }[] = [
{ key: "css", label: "CSS Variables" },
{ key: "tailwind", label: "Tailwind Config" },
{ key: "vscode", label: "VS Code Theme" },
{ key: "json", label: "JSON" },
];
function CopyButton({
text,
tabLabel,
}: {
text: string;
tabLabel: string;
}) {
const [copied, setCopied] = useState(false);
const handleCopy = useCallback(async () => {
try {
await navigator.clipboard.writeText(text);
setCopied(true);
window.setTimeout(() => setCopied(false), 2000);
} catch {
// clipboard write failed silently
}
}, [text]);
return (
<Button
variant="ghost"
size="sm"
onClick={handleCopy}
aria-label={`Copy ${tabLabel}`}
title={`Copy ${tabLabel}`}
className="h-7 gap-1 text-xs"
>
{copied ? (
<>
<Check className="size-3" />
Copied!
</>
) : (
<>
<Copy className="size-3" />
Copy {tabLabel}
</>
)}
</Button>
);
}
export function ThemeExportTabs({ exports, className }: ThemeExportTabsProps) {
return (
<Tabs defaultValue="css" className={cn("w-full", className)}>
<TabsList>
{TABS.map((tab) => (
<TabsTrigger key={tab.key} value={tab.key}>
{tab.label}
</TabsTrigger>
))}
</TabsList>
{TABS.map((tab) => (
<TabsContent key={tab.key} value={tab.key}>
<div className="relative rounded-md border border-border bg-secondary">
<div className="flex items-center justify-between border-b border-border px-3 py-1.5">
<span className="text-xs text-muted-foreground">{tab.label}</span>
<CopyButton text={exports[tab.key]} tabLabel={tab.label} />
</div>
<pre className="overflow-x-auto p-3 text-[14px] font-mono leading-relaxed">
<code>{exports[tab.key]}</code>
</pre>
</div>
</TabsContent>
))}
</Tabs>
);
}