This commit is contained in:
Ivan Dimitrov 2023-11-12 15:46:27 +02:00
parent c6522bb851
commit f30dfc1f98
7 changed files with 51 additions and 46 deletions

View File

@ -9,7 +9,8 @@ import rehypeRaw from "rehype-raw";
import rehypeHighlight from "rehype-highlight";
import { notFound } from "next/navigation";
import Link from "next/link";
import CodeBlock from "$components/code-block";
import CopyButton from "$components/copy-button";
import { getText } from "@/app/lib/react";
type Params = {
slug: string[]
@ -75,7 +76,10 @@ export default function Content({ params }: Props) {
},
pre({ children, className }) {
return (
<CodeBlock className={className}>{children}</CodeBlock>
<div className="relative">
<CopyButton text={getText(children)} />
<pre className={`${className || ""}`}>{children}</pre>
</div>
)
}
}}

View File

@ -1,40 +0,0 @@
"use client"
import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { ReactNode, useState } from "react"
type Props = {
className?: string
children?: ReactNode
}
const getText = (node: any) => {
const props = node.props
if (!props) {
return node
}
const c = props.children
return typeof c === "string" ? c : c.map(getText).join("")
}
const CodeBlock = ({ className, children }: Props) => {
const [visible, setVisible] = useState("invisible")
return (
<div style={{ position: 'relative' }}>
<button
className="absolute top-5 right-5"
onClick={() => {
navigator.clipboard.writeText(getText(children))
setVisible("visible")
setTimeout(() => setVisible("invisible"), 1000)
}}
>
<span className={`${visible} absolute bottom-5 left-5`}><FontAwesomeIcon className="text-green-400" icon={faCheck} /></span>
<FontAwesomeIcon icon={faCopy} />
</button>
<pre className={`${className || ""}`}>{children}</pre>
</div>
)
}
export default CodeBlock;

View File

@ -0,0 +1,27 @@
"use client"
import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { useState } from "react"
type Props = {
text: string
}
const CopyButton = ({ text }: Props) => {
const [visible, setVisible] = useState("invisible")
return (
<button
className="absolute top-5 right-5"
onClick={() => {
navigator.clipboard.writeText(text)
setVisible("visible")
setTimeout(() => setVisible("invisible"), 1000)
}}
>
<span className={`${visible} absolute bottom-5 left-5`}><FontAwesomeIcon className="text-green-400" icon={faCheck} /></span>
<FontAwesomeIcon className="" icon={faCopy} />
</button>
)
}
export default CopyButton;

View File

@ -6,10 +6,10 @@ const Links = () =>
<div className="grid w-full h-full place-content-center">
<div className={"grid grid-cols-2 gap-4 place-content-center"}>
<Link aria-label="GitHub" href={process.env.NEXT_PUBLIC_GITHUB_URL!} target="_blank">
<FontAwesomeIcon icon={faGithub} />
<FontAwesomeIcon className="svg-link" icon={faGithub} />
</Link>
<Link aria-label="GitLab" href={process.env.NEXT_PUBLIC_GITLAB_URL!} target="_blank">
<FontAwesomeIcon icon={faGitlab} />
<FontAwesomeIcon className="svg-link" icon={faGitlab} />
</Link>
</div>
</div>

View File

@ -6,7 +6,7 @@ const mailto = `mailto:${email}`
const Contact = () =>
<div className="w-full h-full p-2 grid place-content-center">
<div className="flex flex-row gap-4">
<a aria-label={mailto} href={mailto}><FontAwesomeIcon icon={faEnvelope} /></a>
<a aria-label={mailto} href={mailto}><FontAwesomeIcon className="svg-link" icon={faEnvelope} /></a>
</div>
</div>

View File

@ -11,7 +11,11 @@ main {
}
svg {
@apply w-14 h-14 text-amber-100 hover:text-cyan-500
@apply hover:text-cyan-500
}
.svg-link {
@apply w-14 h-14
}
.btn {

10
src/app/lib/react.ts Normal file
View File

@ -0,0 +1,10 @@
import { ReactNode } from "react"
export const getText = (node: ReactNode | any) => {
const props = node.props
if (!props) {
return node
}
const c = props.children
return typeof c === "string" ? c : c.map(getText).join("")
}