Skip to content

Commit 0b88ca2

Browse files
committed
[FEATURE] Added Copy button with Toast notification
Added Copy Button which copies the code snippet and gives a toast notification saying Code is Copied.
1 parent df00c24 commit 0b88ca2

File tree

6 files changed

+43
-14
lines changed

6 files changed

+43
-14
lines changed

components/codePreview/index.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useRef, useState } from "react";
1+
import React, { useCallback, useRef, useState } from "react";
22
import "highlight.js/styles/atom-one-light.css";
33
import { Algorithm } from "lib/models";
44
import {
@@ -27,7 +27,9 @@ import {
2727
MoreHoriz,
2828
OpenInNew,
2929
PlayArrow,
30+
FileCopyOutlined,
3031
} from "@material-ui/icons";
32+
import { toast } from "react-hot-toast";
3133
import NextLink from "next/link";
3234
import { StringParam, useQueryParam, withDefault } from "next-query-params";
3335
import classes from "./style.module.css";
@@ -45,6 +47,12 @@ export default function CodePreview({ algorithm }: { algorithm: Algorithm }) {
4547
const fabRef = useRef();
4648
const [mobileMoreMenuOpen, setMobileMoreMenuOpen] = useState(false);
4749

50+
const copyCode = useCallback(async () => {
51+
const codeText = document.querySelector(".style_pre__k555n")?.textContent;
52+
await navigator.clipboard.writeText(codeText);
53+
toast.success("Code Snippet Copied!");
54+
}, []);
55+
4856
return (
4957
<div className={`${classes.container}`}>
5058
<div className={classes.codeBox}>
@@ -86,6 +94,10 @@ export default function CodePreview({ algorithm }: { algorithm: Algorithm }) {
8694
<Fullscreen />
8795
<Typography>{t("fullscreen")}</Typography>
8896
</MenuItem>
97+
<MenuItem onClick={() => copyCode()}>
98+
<FileCopyOutlined />
99+
<Typography>{t("Copy Code")}</Typography>
100+
</MenuItem>
89101
<Link
90102
href={implementations[selectedLanguague].url}
91103
target="_blank"
@@ -101,6 +113,9 @@ export default function CodePreview({ algorithm }: { algorithm: Algorithm }) {
101113
) : (
102114
<>
103115
<div className={classes.buttonsTop}>
116+
<IconButton className={classes.copycode} onClick={copyCode}>
117+
<FileCopyOutlined />
118+
</IconButton>
104119
<Button
105120
startIcon={<OpenInNew />}
106121
href={implementations[selectedLanguague].url}

components/searchBar/index.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,13 @@ export default function SearchBar({
3838

3939
function handleInput(event: FormEvent) {
4040
setQuery((event.target as HTMLInputElement).value);
41-
const searchValue = (event.target as HTMLInputElement).value;
4241
// When input value is null, set error & empty state to `true` and do nothing.
4342

44-
if (!smallScreen) {
45-
if (searchValue) {
46-
debounce(() => {
47-
router.push(`/search?q=${searchValue}`);
48-
});
49-
} else {
50-
debounce(() => {
51-
router.push(`/`);
52-
});
53-
}
54-
}
55-
if (!searchValue) {
43+
if (!smallScreen)
44+
debounce(() => {
45+
router.push(`/search?q=${(event.target as HTMLInputElement).value}`);
46+
});
47+
if (!(event.target as HTMLInputElement).value) {
5648
setIsEmpty(true);
5749
setIsError(true);
5850
return;

hooks/toast-provider.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use client";
2+
3+
import { Toaster } from "react-hot-toast";
4+
5+
export default function ToastProvider() {
6+
return <Toaster />;
7+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"react": "^17.0.2",
4848
"react-devicons": "^2.11.0-rev.2",
4949
"react-dom": "^17.0.2",
50+
"react-hot-toast": "^2.4.1",
5051
"rehype-highlight": "<5.0.0",
5152
"rehype-stringify": "<9.0.0",
5253
"remark-gfm": "<2.0.0",

pages/_app.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { QueryProvider } from "hooks/query";
1111
import { DarkThemeProvider } from "hooks/darkTheme";
1212
import DefaultLayout from "layouts/default";
1313
import { NextQueryParamProvider } from "next-query-params";
14+
import ToastProvider from "hooks/toast-provider";
1415

1516
function MyApp({ Component, pageProps }: AppProps) {
1617
const [isDarkTheme, setIsDarkTheme] = useState(false);
@@ -32,6 +33,7 @@ function MyApp({ Component, pageProps }: AppProps) {
3233
<ThemeProvider theme={isDarkTheme ? darkTheme : lightTheme}>
3334
<QueryProvider>
3435
<NextQueryParamProvider>
36+
<ToastProvider />
3537
<Head />
3638
<CssBaseline />
3739
<NextNprogress

yarn.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,6 +2317,11 @@ globby@^11.1.0:
23172317
merge2 "^1.4.1"
23182318
slash "^3.0.0"
23192319

2320+
goober@^2.1.10:
2321+
version "2.1.14"
2322+
resolved "https://registry.yarnpkg.com/goober/-/goober-2.1.14.tgz#4a5c94fc34dc086a8e6035360ae1800005135acd"
2323+
integrity sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==
2324+
23202325
has-bigints@^1.0.1:
23212326
version "1.0.1"
23222327
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
@@ -3802,6 +3807,13 @@ react-dom@^17.0.2:
38023807
object-assign "^4.1.1"
38033808
scheduler "^0.20.2"
38043809

3810+
react-hot-toast@^2.4.1:
3811+
version "2.4.1"
3812+
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
3813+
integrity sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==
3814+
dependencies:
3815+
goober "^2.1.10"
3816+
38053817
react-i18next@^11.8.13:
38063818
version "11.13.0"
38073819
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.13.0.tgz#7b6f23f717154a44cf3f70d62a9368152bf8a73f"

0 commit comments

Comments
 (0)