sheets
This commit is contained in:
parent
c6522bb851
commit
f30dfc1f98
@ -9,7 +9,8 @@ import rehypeRaw from "rehype-raw";
|
|||||||
import rehypeHighlight from "rehype-highlight";
|
import rehypeHighlight from "rehype-highlight";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
import Link from "next/link";
|
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 = {
|
type Params = {
|
||||||
slug: string[]
|
slug: string[]
|
||||||
@ -75,7 +76,10 @@ export default function Content({ params }: Props) {
|
|||||||
},
|
},
|
||||||
pre({ children, className }) {
|
pre({ children, className }) {
|
||||||
return (
|
return (
|
||||||
<CodeBlock className={className}>{children}</CodeBlock>
|
<div className="relative">
|
||||||
|
<CopyButton text={getText(children)} />
|
||||||
|
<pre className={`${className || ""}`}>{children}</pre>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -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;
|
|
27
src/app/components/copy-button.tsx
Normal file
27
src/app/components/copy-button.tsx
Normal 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;
|
@ -6,10 +6,10 @@ const Links = () =>
|
|||||||
<div className="grid w-full h-full place-content-center">
|
<div className="grid w-full h-full place-content-center">
|
||||||
<div className={"grid grid-cols-2 gap-4 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">
|
<Link aria-label="GitHub" href={process.env.NEXT_PUBLIC_GITHUB_URL!} target="_blank">
|
||||||
<FontAwesomeIcon icon={faGithub} />
|
<FontAwesomeIcon className="svg-link" icon={faGithub} />
|
||||||
</Link>
|
</Link>
|
||||||
<Link aria-label="GitLab" href={process.env.NEXT_PUBLIC_GITLAB_URL!} target="_blank">
|
<Link aria-label="GitLab" href={process.env.NEXT_PUBLIC_GITLAB_URL!} target="_blank">
|
||||||
<FontAwesomeIcon icon={faGitlab} />
|
<FontAwesomeIcon className="svg-link" icon={faGitlab} />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,7 +6,7 @@ const mailto = `mailto:${email}`
|
|||||||
const Contact = () =>
|
const Contact = () =>
|
||||||
<div className="w-full h-full p-2 grid place-content-center">
|
<div className="w-full h-full p-2 grid place-content-center">
|
||||||
<div className="flex flex-row gap-4">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -11,7 +11,11 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
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 {
|
.btn {
|
||||||
|
10
src/app/lib/react.ts
Normal file
10
src/app/lib/react.ts
Normal 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("")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user