Fuma studio

Snippet

Installation

npx shadcn@latest add http://fumastudio/com/r/snippet.json
components/fumastudio/snippet.tsx
"use client";

import { CodeBlock } from "@/components/fumastudio/code-block";
import { CheckCircleFilled } from "@/components/fumastudio/icons";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useClipboard } from "@/hooks/use-clipboard";
import { Snippet } from "@trythis/nextjs";
import { Copy } from "lucide-react";
import { useState } from "react";

const RequestSnippets = (props: { snippets: Snippet[] }) => {
	const { snippets } = props;
	const hasSnippets: boolean = snippets.length > 0;
	const { isCopied, copyValue } = useClipboard();
	const [selectedId, setSelectedId] = useState<string>(
		snippets[0]?.id || "",
	);

	if (!hasSnippets) {
		return (
			<div className="flex items-center justify-center text-sm h-9 rounded-xl text-muted-foreground">
				No defined request.
			</div>
		);
	}

	const selectedSnippet: Snippet | undefined = snippets.find(
		(s) => s.id === selectedId,
	);

	return (
		<div className="w-full">
			<Tabs
				value={selectedId}
				onValueChange={setSelectedId}
				className="gap-0">
				<TabsList className="text-foreground w-full rounded-none bg-transparent px-1.5 h-10 flex items-center justify-between">
					<div className="flex flex-wrap items-center gap-x-1.5">
						{snippets.map((snippet) => (
							<TabsTrigger
								key={snippet.id}
								value={snippet.id}
								className="hover:bg-muted-foreground/15 px-1.5 py-1 text-xs hover:text-foreground data-[state=active]:after:bg-muted-foreground relative after:absolute after:inset-x-0 after:bottom-0 after:-mb-1 after:h-0.5 data-[state=active]:bg-transparent">
								{snippet.language}
							</TabsTrigger>
						))}
					</div>

					<button
						className="flex items-center ml-auto transition-colors text-muted-foreground hover:text-foreground"
						onClick={() => {
							if (selectedSnippet) {
								copyValue(selectedSnippet.code);
							}
						}}
						title="Copy snippet">
						{!isCopied && <Copy className="size-4" />}

						{isCopied && (
							<CheckCircleFilled className="size-5 cursor-pointer" />
						)}
					</button>
				</TabsList>

				{snippets.map((snippet) => (
					<TabsContent
						key={snippet.id}
						value={snippet.id}
						className="relative w-full overflow-scroll border h-44 max-h-48 scrollbar-hide border-input rounded-xl">
						<div className="text-sm">
							<CodeBlock
								code={snippet.code}
								language={snippet.syntax}
							/>
						</div>
					</TabsContent>
				))}
			</Tabs>
		</div>
	);
};

const ResponseSnippets = (props: { snippets: Snippet[] }) => {
	const { snippets } = props;
	const hasSnippets = snippets.length > 0;
	const { isCopied, copyValue } = useClipboard();

	const [selectedId, setSelectedId] = useState<string>(
		hasSnippets ? snippets[0].id : "",
	);

	if (!hasSnippets) {
		return (
			<div className="flex items-center justify-center text-sm h-9 rounded-xl text-muted-foreground">
				No defined response.
			</div>
		);
	}

	const selectedSnippet = snippets.find((s) => s.id === selectedId);

	return (
		<div className="w-full">
			<Tabs
				value={selectedId}
				onValueChange={setSelectedId}
				className="gap-0">
				<TabsList className="text-foreground w-full rounded-none bg-transparent px-1.5 h-10 flex items-center justify-between">
					<div className="flex flex-wrap items-center gap-x-1.5">
						{snippets.map((snippet) => (
							<TabsTrigger
								key={snippet.id}
								value={snippet.id}
								className="hover:bg-muted-foreground/15 px-1.5 py-1 text-xs hover:text-foreground data-[state=active]:after:bg-muted-foreground data-[state=active]:hover:bg-muted-foreground/15 relative after:absolute after:inset-x-0 after:bottom-0 after:-mb-1 after:h-0.5 data-[state=active]:bg-transparent data-[state=active]:shadow-none">
								{snippet.id}
							</TabsTrigger>
						))}
					</div>

					<button
						className="flex items-center ml-auto transition-colors text-muted-foreground hover:text-foreground"
						onClick={() => {
							if (selectedSnippet) {
								copyValue(selectedSnippet.code);
							}
						}}
						title="Copy snippet">
						{!isCopied && <Copy className="size-4" />}

						{isCopied && (
							<CheckCircleFilled className="size-5 cursor-pointer" />
						)}
					</button>
				</TabsList>

				{snippets.map((snippet) => (
					<TabsContent
						key={snippet.id}
						value={snippet.id}
						className="relative w-full overflow-scroll border h-44 max-h-48 scrollbar-hide border-input rounded-xl">
						<div className="text-sm">
							<CodeBlock
								code={snippet.code}
								language="Json"
							/>
						</div>
					</TabsContent>
				))}
			</Tabs>
		</div>
	);
};

export { RequestSnippets, ResponseSnippets };

Props

On this page