Skip to content

Commit

Permalink
Added a copy button in playground editor (#176)
Browse files Browse the repository at this point in the history
* Made the copy to clipboard component and added it to playground editor and code snippets

* Fixed the copy button click event handler type

* Fixed copyToClipboard function argument type

* Made changes as per review suggestions

* Added logic to hide the copy to clipboard button only on medium viewports and above

Co-authored-by: Shubham Singh <shubham.singh1@spinny.com>
  • Loading branch information
shubh0107 and shubhamspinny committed Mar 21, 2022
1 parent d1b487f commit dd076b3
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 27 deletions.
36 changes: 22 additions & 14 deletions apps/docs/components/Code/CodeEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const Editor = dynamic(() => import("react-simple-code-editor"), {
ssr: false,
});

const CopyToClipboard = dynamic(() => import("../../CopyToClipboard"), {
ssr: false,
});

const CodeEditor = (props: Props) => {
const { handleChange, code } = props;

Expand All @@ -22,20 +26,24 @@ const CodeEditor = (props: Props) => {
.join("\n");

return (
<div className="editorContainer">
<Editor
value={code}
onValueChange={(code) => handleChange(code)}
highlight={(code) => highlightWithLineNumbers(code)}
padding={10}
textareaClassName="codeArea"
className="editor"
id="codeEditor"
style={{
fontFamily: "monospace",
fontSize: 16,
}}
/>
<div className="playground-editor group">
{/* Wrapping Editor component in a separate div to control its height and overflow */}
<div className="editor-container">
<Editor
value={code}
onValueChange={(code) => handleChange(code)}
highlight={(code) => highlightWithLineNumbers(code)}
padding={10}
textareaClassName="codeArea"
className="editor"
id="codeEditor"
style={{
fontFamily: "monospace",
fontSize: 16,
}}
/>
</div>
<CopyToClipboard text={code} />
</div>
);
};
Expand Down
21 changes: 21 additions & 0 deletions apps/docs/components/CopyToClipboard/CopyIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { SVGProps } from "react";

export default function CopyIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
className="w-6 h-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={1.5}
{...props}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
/>
</svg>
);
}
9 changes: 9 additions & 0 deletions apps/docs/components/CopyToClipboard/TickIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SVGProps } from "react";

export default function TickIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2} {...props}>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
</svg>
);
}
51 changes: 51 additions & 0 deletions apps/docs/components/CopyToClipboard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useEffect, useRef, useState } from "react";
import CopyIcon from "./CopyIcon";
import TickIcon from "./TickIcon";

interface Props {
text: string;
}

export default function CopyToClipboard(props: Props) {
const { text } = props;
const [copySuccess, setCopySuccess] = useState(false);
const buttonRef = useRef<HTMLButtonElement>(null);

useEffect(() => {
if (copySuccess) {
setTimeout(() => {
setCopySuccess(false);
}, 3000);
}
}, [copySuccess]);

function copyToClipboard(e: React.MouseEvent) {
e.stopPropagation();
if (text) {
navigator.clipboard?.writeText(text).then(() => {
setCopySuccess(true);
}).catch(error => {
console.log(error);
});
}
}

return (
<>
<button
ref={buttonRef}
className={"md:hidden absolute top-2 right-2 sm:top-4 sm:right-4 group-hover:flex items-center justify-center p-1 sm:p-2 border border-[#f0f6fc1a] text-base font-medium rounded-md text-gray-400 bg-[#333] hover:bg-[#4d4d4d] cursor-pointer transition-all duration-100 " + (copySuccess ? 'text-bhagwa-300 border-bhagwa-300' : '')}
onClick={copyToClipboard}
>
{copySuccess ?
<>
<TickIcon />
<span className="copied-text absolute top-1/2 -translate-y-1/2 right-[calc(100%+8px)] p-1 rounded-md text-xs font-normal text-bhagwa-300 bg-[#666] border border-transparent">
Copied!
</span>
</>
: <CopyIcon />}
</button>
</>
);
}
24 changes: 14 additions & 10 deletions apps/docs/components/Documentation/Snippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ import React from "react";
import { highlight } from "prismjs";

import { bhaiLangSyntax } from "../common/syntax";

import CopyToClipboard from "../CopyToClipboard";

const Snippet = (props: Props) => {
const { code } = props;

return (
<div
className="bg-editorBackground py-2 px-2 my-6 text-sm text-white documentation-code"
dangerouslySetInnerHTML={{
__html: highlight(code, bhaiLangSyntax, "bhaiLang").replace(
new RegExp("\n", 'g'),
"<br/>"
).replace(new RegExp(' ', 'g'), '&emsp;'),
}}
></div>
<div className="relative snippet-container group">
<div
className="bg-editorBackground py-2 px-2 my-6 text-sm text-white documentation-code"
dangerouslySetInnerHTML={{
__html: highlight(code, bhaiLangSyntax, "bhaiLang").replace(
new RegExp("\n", 'g'),
"<br/>"
).replace(new RegExp(' ', 'g'), '&emsp;'),
}}
></div>
<CopyToClipboard text={code} />
</div>
);

};
type Props = { code: string };
export default React.memo(Snippet);
23 changes: 20 additions & 3 deletions apps/docs/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ html {
min-height: 70vh;
}

.editorContainer{
tab-size: 4ch;
.playground-editor{
position: relative;
}

.editor-container {
height: 60vh;
overflow: auto;
tab-size: 4ch;
color: #fff;
background-color: #333;
}
Expand Down Expand Up @@ -48,7 +52,7 @@ html {
outline: none;
padding-top: 1rem;
padding-left: 5rem !important;
z-index: 999999999;
/* z-index: 999999999; */
white-space: nowrap;
}

Expand Down Expand Up @@ -79,4 +83,17 @@ html {

.documentation-code {
font-family: monospace;
}

.copied-text::after {
position: absolute;
right: -6px;
top: 50%;
transform: translateY(-50%);
content: "";
width: 0px;
height: 0px;
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
border-left: 8px solid #666;
}

0 comments on commit dd076b3

Please sign in to comment.