feat: Add HTML preview to code blocks
Adds an HTML preview feature to the code block component, allowing users to view the rendered output of their HTML code snippets. This improves the user experience by providing a more interactive and informative way to understand the code.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Tooltip } from "antd"
|
||||
import { CheckIcon, ClipboardIcon } from "lucide-react"
|
||||
import { FC, useState } from "react"
|
||||
import { Tooltip, Modal } from "antd"
|
||||
import { CheckIcon, ClipboardIcon, EyeIcon, Maximize2Icon } from "lucide-react"
|
||||
import { FC, useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
||||
import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism"
|
||||
@@ -10,26 +10,47 @@ interface Props {
|
||||
value: string
|
||||
}
|
||||
|
||||
export const CodeBlock: FC<Props> =({ language, value }) => {
|
||||
export const CodeBlock: FC<Props> = ({ language, value }) => {
|
||||
const [isBtnPressed, setIsBtnPressed] = useState(false)
|
||||
const [previewVisible, setPreviewVisible] = useState(false)
|
||||
const { t } = useTranslation("common")
|
||||
|
||||
const handleCopy = () => {
|
||||
navigator.clipboard.writeText(value)
|
||||
setIsBtnPressed(true)
|
||||
setTimeout(() => {
|
||||
setIsBtnPressed(false)
|
||||
}, 4000)
|
||||
}
|
||||
|
||||
const handlePreview = () => {
|
||||
setPreviewVisible(true)
|
||||
}
|
||||
|
||||
const handlePreviewClose = () => {
|
||||
setPreviewVisible(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="code relative text-base font-sans codeblock bg-zinc-950 rounded-md overflow-hidden">
|
||||
<div className="code relative text-base font-sans codeblock bg-zinc-950 rounded-md overflow-hidden">
|
||||
<div className="flex bg-gray-800 items-center justify-between py-1.5 px-4">
|
||||
<span className="text-xs lowercase text-gray-200">{language}</span>
|
||||
|
||||
<div className="flex items-center">
|
||||
{language.toLowerCase() === "html" && (
|
||||
<Tooltip title={t("preview")}>
|
||||
<button
|
||||
onClick={handlePreview}
|
||||
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-200 hover:bg-gray-700 hover:text-gray-100 focus:outline-none">
|
||||
<EyeIcon className="h-4 w-4" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t("copyToClipboard")}>
|
||||
<button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(value)
|
||||
setIsBtnPressed(true)
|
||||
setTimeout(() => {
|
||||
setIsBtnPressed(false)
|
||||
}, 4000)
|
||||
}}
|
||||
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-200 hover:bg-gray-700 hover:text-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 focus:ring-offset-gray-100">
|
||||
onClick={handleCopy}
|
||||
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-200 hover:bg-gray-700 hover:text-gray-100 focus:outline-none">
|
||||
{!isBtnPressed ? (
|
||||
<ClipboardIcon className="h-4 w-4" />
|
||||
) : (
|
||||
@@ -61,6 +82,24 @@ export const CodeBlock: FC<Props> =({ language, value }) => {
|
||||
{value}
|
||||
</SyntaxHighlighter>
|
||||
</div>
|
||||
{previewVisible && (
|
||||
<Modal
|
||||
open={previewVisible}
|
||||
onCancel={handlePreviewClose}
|
||||
footer={null}
|
||||
width="80%"
|
||||
zIndex={999999}
|
||||
centered
|
||||
bodyStyle={{ padding: 0 }}>
|
||||
<div className="relative w-full h-[80vh]">
|
||||
<iframe
|
||||
srcDoc={value}
|
||||
title="HTML Preview"
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user