102 lines
2.5 KiB
TypeScript
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>
|
|
);
|
|
}
|