Update domain page UI

This commit is contained in:
KMKoushik
2024-04-13 07:34:13 +10:00
parent 3217387373
commit 293277ed32
9 changed files with 643 additions and 17 deletions

148
packages/ui/code-theme.ts Normal file
View File

@@ -0,0 +1,148 @@
const codeTheme: {
[key: string]: React.CSSProperties;
} = {
hljs: {
display: "block",
overflowX: "auto",
padding: "0.5em",
background: "#070808",
color: "#d6deeb",
},
"hljs-keyword": {
color: "#c792ea",
fontStyle: "italic",
},
"hljs-built_in": {
color: "#addb67",
fontStyle: "italic",
},
"hljs-type": {
color: "#82aaff",
},
"hljs-literal": {
color: "#ff5874",
},
"hljs-number": {
color: "#F78C6C",
},
"hljs-regexp": {
color: "#5ca7e4",
},
"hljs-string": {
color: "#ecc48d",
},
"hljs-subst": {
color: "#d3423e",
},
"hljs-symbol": {
color: "#82aaff",
},
"hljs-class": {
color: "#ffcb8b",
},
"hljs-function": {
color: "#82AAFF",
},
"hljs-title": {
color: "#DCDCAA",
fontStyle: "italic",
},
"hljs-params": {
color: "#7fdbca",
},
"hljs-comment": {
color: "#637777",
fontStyle: "italic",
},
"hljs-doctag": {
color: "#7fdbca",
},
"hljs-meta": {
color: "#82aaff",
},
"hljs-meta-keyword": {
color: "#82aaff",
},
"hljs-meta-string": {
color: "#ecc48d",
},
"hljs-section": {
color: "#82b1ff",
},
"hljs-tag": {
color: "#7fdbca",
},
"hljs-name": {
color: "#7fdbca",
},
"hljs-builtin-name": {
color: "#7fdbca",
},
"hljs-attr": {
color: "#7fdbca",
},
"hljs-attribute": {
color: "#80cbc4",
},
"hljs-variable": {
color: "#addb67",
},
"hljs-bullet": {
color: "#d9f5dd",
},
"hljs-code": {
color: "#80CBC4",
},
"hljs-emphasis": {
color: "#c792ea",
fontStyle: "italic",
},
"hljs-strong": {
color: "#addb67",
fontWeight: "bold",
},
"hljs-formula": {
color: "#c792ea",
},
"hljs-link": {
color: "#ff869a",
},
"hljs-quote": {
color: "#697098",
fontStyle: "italic",
},
"hljs-selector-tag": {
color: "#ff6363",
},
"hljs-selector-id": {
color: "#fad430",
},
"hljs-selector-class": {
color: "#addb67",
fontStyle: "italic",
},
"hljs-selector-attr": {
color: "#c792ea",
fontStyle: "italic",
},
"hljs-selector-pseudo": {
color: "#c792ea",
fontStyle: "italic",
},
"hljs-template-tag": {
color: "#c792ea",
},
"hljs-template-variable": {
color: "#addb67",
},
"hljs-addition": {
color: "#addb67ff",
fontStyle: "italic",
},
"hljs-deletion": {
color: "#EF535090",
fontStyle: "italic",
},
};
export default codeTheme;

View File

@@ -15,6 +15,7 @@
"@types/node": "^20.11.24",
"@types/react": "^18.2.61",
"@types/react-dom": "^18.2.19",
"@types/react-syntax-highlighter": "^15.5.11",
"@unsend/eslint-config": "workspace:*",
"@unsend/tailwind-config": "workspace:*",
"@unsend/typescript-config": "workspace:*",
@@ -32,12 +33,14 @@
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"add": "^2.0.6",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"lucide-react": "^0.359.0",
"next-themes": "^0.3.0",
"pnpm": "^8.15.5",
"react-syntax-highlighter": "^15.5.0",
"sonner": "^1.4.41",
"tailwind-merge": "^2.2.2",
"tailwindcss-animate": "^1.0.7"

97
packages/ui/src/code.tsx Normal file
View File

@@ -0,0 +1,97 @@
import { Light as SyntaxHighlighter } from "react-syntax-highlighter";
import js from "react-syntax-highlighter/dist/esm/languages/hljs/javascript";
import ruby from "react-syntax-highlighter/dist/esm/languages/hljs/ruby";
import php from "react-syntax-highlighter/dist/esm/languages/hljs/php";
import python from "react-syntax-highlighter/dist/esm/languages/hljs/python";
// import { nightOwl } from "react-syntax-highlighter/dist/esm/styles/hljs";
import codeTheme from "../code-theme";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs";
import { Button } from "./button";
import { ClipboardCopy, Check } from "lucide-react";
import { useState } from "react";
type Language = "js" | "ruby" | "php" | "python";
type CodeProps = {
codeBlocks: {
language: Language;
code: string;
display?: string;
}[];
};
SyntaxHighlighter.registerLanguage("js", js);
SyntaxHighlighter.registerLanguage("ruby", ruby);
SyntaxHighlighter.registerLanguage("php", php);
SyntaxHighlighter.registerLanguage("python", python);
export const Code: React.FC<CodeProps> = ({ codeBlocks }) => {
const [selectedTab, setSelectedTab] = useState(
codeBlocks[0]?.language ?? "js"
);
const [isCopied, setIsCopied] = useState(false);
const copyToClipboard = async (code: string) => {
try {
await navigator.clipboard.writeText(code);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000); // Reset the icon back to clipboard after 2 seconds
} catch (err) {
alert("Failed to copy code");
}
};
return (
<div className="rounded-md bg-background border">
<Tabs
defaultValue={codeBlocks[0]?.language}
onValueChange={(val) => setSelectedTab(val as Language)}
>
<div className="flex justify-between items-center border-b py-1 px-2">
<TabsList className="w-full rounded-none justify-start bg-transparent h-12">
<div className="">
{codeBlocks.map((block) => (
<TabsTrigger
key={block.language}
value={block.language}
className="data-[state=active]:bg-accent py-0.5 px-4"
>
{block.language}
</TabsTrigger>
))}
</div>
</TabsList>
<Button
size="icon"
variant="icon"
onClick={() =>
copyToClipboard(
codeBlocks.find((block) => block.language === selectedTab)
?.code || ""
)
}
>
{isCopied ? (
<Check className="h-4 w-4" />
) : (
<ClipboardCopy className="h-4 w-4" />
)}
</Button>
</div>
{codeBlocks.map((block) => (
<TabsContent
key={block.language}
value={block.language}
className="py-2"
>
<div className="overflow-auto max-w-[38rem] h-[20rem]">
<SyntaxHighlighter language={block.language} style={codeTheme}>
{block.code}
</SyntaxHighlighter>
</div>
</TabsContent>
))}
</Tabs>
</div>
);
};

55
packages/ui/src/tabs.tsx Normal file
View File

@@ -0,0 +1,55 @@
"use client";
import * as React from "react";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import { cn } from "../lib/utils";
const Tabs = TabsPrimitive.Root;
const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
className
)}
{...props}
/>
));
TabsList.displayName = TabsPrimitive.List.displayName;
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
className
)}
{...props}
/>
));
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className
)}
{...props}
/>
));
TabsContent.displayName = TabsPrimitive.Content.displayName;
export { Tabs, TabsList, TabsTrigger, TabsContent };