Skip to content

Commit

Permalink
Merge pull request #349 from FormidableLabs/feature/code-block-copy
Browse files Browse the repository at this point in the history
Feature/code block copy
  • Loading branch information
jmfulgham authored Apr 20, 2021
2 parents 649077c + 03065df commit cf4948e
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/panel/__image_snapshots__/Mismatch - basic-landscape-snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 65 additions & 8 deletions src/panel/components/CodeHighlight.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { FC, useCallback, ComponentPropsWithoutRef } from "react";
import React, {
FC,
useCallback,
ComponentPropsWithoutRef,
useState,
useEffect,
} from "react";
import styled from "styled-components";

type PrismLanguage = "javascript" | "graphql";
Expand All @@ -9,19 +15,40 @@ export const CodeHighlight: FC<
language: PrismLanguage;
} & ComponentPropsWithoutRef<typeof StyledCodeBlock>
> = ({ code, language, ...props }) => {
const [visible, setVisibility] = useState(false);
const [copy, setCopied] = useState({ state: false });

const handleClick = async () => {
const text = document.getElementsByClassName("language")[0].textContent;
if (text) {
try {
await navigator.clipboard.writeText(text);
setCopied({ state: true });
} catch (err) {
console.error("Failed to copy!", err);
}
}
};

useEffect(() => {
if (!copy) return;
const timeout = setTimeout(function () {
setCopied({ state: false });
}, 1000);
return () => clearTimeout(timeout);
}, [copy]);

const handleRef = useCallback(
(ref: HTMLPreElement | null) => {
if (!ref) {
return;
}

// Create new child node with text
const child = document.createElement("code");
child.textContent = code;
ref.firstChild
? ref.replaceChild(child, ref.firstChild)
: ref.appendChild(child);

// Run prism on element (in web worker/async)
// when code is a chonker
Prism.highlightElement(ref, code.length > 600);
Expand All @@ -30,11 +57,21 @@ export const CodeHighlight: FC<
);

return (
<StyledCodeBlock
{...props}
ref={handleRef}
className={`language language-${language} ${props.className || ""}`}
/>
<Div
onMouseEnter={() => setVisibility(true)}
onMouseLeave={() => setVisibility(false)}
>
<StyledCodeBlock
{...props}
ref={handleRef}
className={`language language-${language} ${props.className || ""}`}
/>
{visible ? (
<CopyButton onClick={handleClick} id="copy-button">
{copy.state ? "Copied" : "Copy"}
</CopyButton>
) : null}
</Div>
);
};

Expand Down Expand Up @@ -89,3 +126,23 @@ const StyledCodeBlock = styled.pre`
background: ${(props) => props.theme.dark["+2"]} !important;
font-size: 12px !important;
`;

const CopyButton = styled.button`
background: ${(props) => props.theme.dark["+2"]} !important;
margin: 1rem;
padding: 0.5rem;
color: white;
border: ${(props) => props.theme.dark["+1"]} !important;
border-radius: 4px;
position: absolute;
top: 0;
right: 6px;
:hover {
background: #adadad !important;
}
`;

const Div = styled.div`
position: relative;
`;

0 comments on commit cf4948e

Please sign in to comment.