Feat/code blocks with copy
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { Button } from "@usesend/ui/src/button";
|
import { Button } from "@usesend/ui/src/button";
|
||||||
import { CodeBlock } from "@usesend/ui/src/code-block";
|
import { CodeBlock } from "@usesend/ui/src/code-block";
|
||||||
|
import { CodeBlockWithCopy } from "@usesend/ui/src/code-block-with-copy";
|
||||||
import { LangToggle } from "./CodeLangToggle";
|
import { LangToggle } from "./CodeLangToggle";
|
||||||
|
|
||||||
const TS_CODE = `import { UseSend } from "usesend-js";
|
const TS_CODE = `import { UseSend } from "usesend-js";
|
||||||
@@ -149,12 +150,14 @@ export function CodeExample() {
|
|||||||
className={idx === 0 ? "block" : "hidden"}
|
className={idx === 0 ? "block" : "hidden"}
|
||||||
>
|
>
|
||||||
{/* Cast to any to align with shiki BundledLanguage without importing types here */}
|
{/* Cast to any to align with shiki BundledLanguage without importing types here */}
|
||||||
|
<CodeBlockWithCopy code={l.code}>
|
||||||
<CodeBlock
|
<CodeBlock
|
||||||
lang={l.shiki as any}
|
lang={l.shiki as any}
|
||||||
className="p-4 rounded-[10px]"
|
className="p-4 rounded-[10px]"
|
||||||
>
|
>
|
||||||
{l.code}
|
{l.code}
|
||||||
</CodeBlock>
|
</CodeBlock>
|
||||||
|
</CodeBlockWithCopy>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import { CheckIcon } from "lucide-react";
|
||||||
|
import { Button } from "./button";
|
||||||
|
import { cn } from "../lib/utils";
|
||||||
|
import { Copy } from "lucide-react";
|
||||||
|
interface CodeBlockWithCopyProps {
|
||||||
|
code: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CodeBlockWithCopy({
|
||||||
|
code,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
}: CodeBlockWithCopyProps) {
|
||||||
|
const [isCopied, setIsCopied] = React.useState(false);
|
||||||
|
|
||||||
|
const copyToClipboard = async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(code);
|
||||||
|
setIsCopied(true);
|
||||||
|
setTimeout(() => setIsCopied(false), 2000);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to copy: ", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn("relative group", className)}>
|
||||||
|
{children}
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className={cn(
|
||||||
|
"absolute top-2 right-2 h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity",
|
||||||
|
"bg-background/80 backdrop-blur-sm hover:bg-background/90 border border-border/50"
|
||||||
|
)}
|
||||||
|
onClick={copyToClipboard}
|
||||||
|
aria-label="Copy code"
|
||||||
|
>
|
||||||
|
{isCopied ? (
|
||||||
|
<CheckIcon className="h-4 w-4 text-green-500" />
|
||||||
|
) : (
|
||||||
|
<Copy className="h-4 w-4" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -139,13 +139,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prevent italic styling in Shiki code blocks */
|
||||||
|
.shiki,
|
||||||
|
.shiki span {
|
||||||
|
font-style: normal !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
.shiki,
|
.shiki,
|
||||||
.shiki span {
|
.shiki span {
|
||||||
color: var(--shiki-dark) !important;
|
color: var(--shiki-dark) !important;
|
||||||
background-color: var(--shiki-dark-bg) !important;
|
background-color: var(--shiki-dark-bg) !important;
|
||||||
/* Optional, if you also want font styles */
|
/* Optional, if you also want font styles */
|
||||||
font-style: var(--shiki-dark-font-style) !important;
|
|
||||||
font-weight: var(--shiki-dark-font-weight) !important;
|
font-weight: var(--shiki-dark-font-weight) !important;
|
||||||
text-decoration: var(--shiki-dark-text-decoration) !important;
|
text-decoration: var(--shiki-dark-text-decoration) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user