From 641d5f36d25aa5d4ac1bd7cc51280824a417420d Mon Sep 17 00:00:00 2001
From: Krish Parekh <73629899+Krish-Parekh@users.noreply.github.com>
Date: Sun, 7 Dec 2025 11:08:54 +0530
Subject: [PATCH] Feat/code blocks with copy
---
apps/marketing/src/components/CodeExample.tsx | 15 +++---
packages/ui/src/code-block-with-copy.tsx | 53 +++++++++++++++++++
packages/ui/styles/globals.css | 7 ++-
3 files changed, 68 insertions(+), 7 deletions(-)
create mode 100644 packages/ui/src/code-block-with-copy.tsx
diff --git a/apps/marketing/src/components/CodeExample.tsx b/apps/marketing/src/components/CodeExample.tsx
index ef72fa9..e6667fd 100644
--- a/apps/marketing/src/components/CodeExample.tsx
+++ b/apps/marketing/src/components/CodeExample.tsx
@@ -1,5 +1,6 @@
import { Button } from "@usesend/ui/src/button";
import { CodeBlock } from "@usesend/ui/src/code-block";
+import { CodeBlockWithCopy } from "@usesend/ui/src/code-block-with-copy";
import { LangToggle } from "./CodeLangToggle";
const TS_CODE = `import { UseSend } from "usesend-js";
@@ -149,12 +150,14 @@ export function CodeExample() {
className={idx === 0 ? "block" : "hidden"}
>
{/* Cast to any to align with shiki BundledLanguage without importing types here */}
-
- {l.code}
-
+
+
+ {l.code}
+
+
))}
diff --git a/packages/ui/src/code-block-with-copy.tsx b/packages/ui/src/code-block-with-copy.tsx
new file mode 100644
index 0000000..7df4dc7
--- /dev/null
+++ b/packages/ui/src/code-block-with-copy.tsx
@@ -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 (
+
+ {children}
+
+
+ );
+}
+
diff --git a/packages/ui/styles/globals.css b/packages/ui/styles/globals.css
index 9d32116..711a5a5 100644
--- a/packages/ui/styles/globals.css
+++ b/packages/ui/styles/globals.css
@@ -139,13 +139,18 @@
}
}
+/* Prevent italic styling in Shiki code blocks */
+.shiki,
+.shiki span {
+ font-style: normal !important;
+}
+
@media (prefers-color-scheme: dark) {
.shiki,
.shiki span {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
/* Optional, if you also want font styles */
- font-style: var(--shiki-dark-font-style) !important;
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}