Skip to content

Commit f842a51

Browse files
committed
Refactored code and removed unused parts
1 parent ecbd3ee commit f842a51

18 files changed

+102
-149
lines changed

src/App.tsx

+17-21
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,28 @@
1-
import Footer from "./layouts/Footer";
1+
import { useAppContext } from "./contexts/AppContext";
2+
23
import Header from "./layouts/Header";
34
import Banner from "./layouts/Banner";
4-
import LanguageSelector from "./components/LanguageSelector";
5-
import CategoryList from "./components/CategoryList";
6-
import { useAppContext } from "./contexts/AppContext";
5+
import Sidebar from "./layouts/Sidebar";
6+
import Footer from "./layouts/Footer";
7+
78
import SnippetList from "./components/SnippetList";
89

910
const App = () => {
1011
const { category } = useAppContext();
1112

1213
return (
13-
<>
14-
<div className="container flow" data-flow-space="xl">
15-
<Header />
16-
<Banner />
17-
<main className="main">
18-
<aside className="sidebar flow">
19-
<LanguageSelector />
20-
<CategoryList />
21-
</aside>
22-
<section className="flow">
23-
<h2 className="section-title">{category}</h2>
24-
<SnippetList />
25-
</section>
26-
</main>
27-
<Footer />
28-
</div>
29-
</>
14+
<div className="container flow" data-flow-space="xl">
15+
<Header />
16+
<Banner />
17+
<main className="main">
18+
<Sidebar />
19+
<section className="flow">
20+
<h2 className="section-title">{category}</h2>
21+
<SnippetList />
22+
</section>
23+
</main>
24+
<Footer />
25+
</div>
3026
);
3127
};
3228

src/components/Button.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { MouseEventHandler, ReactNode } from "react";
22

3+
// TODO: separate LinkButton from Button for clarity
4+
35
type ButtonProps = {
46
as?: "button" | "link";
57
href?: string;

src/components/CodePreview.tsx

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
22
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
33

4-
type CodePreviewProps = {
5-
language?: string;
4+
type Props = {
5+
language: string;
66
children: string;
77
};
88

9-
const CodePreview = ({ language, children }: CodePreviewProps) => {
10-
if (!language) {
11-
language = "markdown"; // for fallback
12-
}
13-
9+
const CodePreview = ({ language = "markdown", children }: Props) => {
1410
return (
1511
<SyntaxHighlighter
1612
language={language}

src/components/CopyToClipboard.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { useState } from "react";
2-
import { useAppContext } from "../contexts/AppContext";
32
import Button from "./Button";
43
import { CopyIcon } from "./Icons";
54

6-
const CopyToClipboard = ({ ...props }) => {
7-
const { snippet } = useAppContext();
8-
const [isCopied, setIsCopied] = useState(false);
5+
type Props = {
6+
text: string;
7+
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
98

10-
const snippetCode = snippet ? snippet.code : "";
9+
const CopyToClipboard = ({ text, ...props }: Props) => {
10+
const [isCopied, setIsCopied] = useState(false);
1111

12-
const copySnippetCode = () => {
12+
const copyText = () => {
1313
navigator.clipboard
14-
.writeText(snippetCode)
14+
.writeText(text)
1515
.then(() => {
1616
setIsCopied(true);
1717
setTimeout(() => setIsCopied(false), 2000);
@@ -20,7 +20,7 @@ const CopyToClipboard = ({ ...props }) => {
2020
};
2121

2222
return (
23-
<Button isIcon={true} onClick={copySnippetCode} {...props}>
23+
<Button isIcon={true} onClick={copyText} {...props}>
2424
{isCopied ? "Copied!" : <CopyIcon />}
2525
</Button>
2626
);

src/components/LanguageSelector.tsx

+12-14
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,18 @@ const LanguageSelector = () => {
2525
}
2626

2727
return (
28-
<>
29-
<select
30-
id="languages"
31-
className="language-selector"
32-
onChange={handleLanguageChange}
33-
defaultValue="CSS"
34-
>
35-
{fetchedLanguages.map((language, idx) => (
36-
<option key={idx} value={language.lang}>
37-
{language.lang}
38-
</option>
39-
))}
40-
</select>
41-
</>
28+
<select
29+
id="languages"
30+
className="language-selector"
31+
onChange={handleLanguageChange}
32+
defaultValue="CSS"
33+
>
34+
{fetchedLanguages.map((language, idx) => (
35+
<option key={idx} value={language.lang}>
36+
{language.lang}
37+
</option>
38+
))}
39+
</select>
4240
);
4341
};
4442

src/components/SnippetList.tsx

+6-37
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@ import { useState } from "react";
22
import { SnippetType } from "../types";
33
import { useAppContext } from "../contexts/AppContext";
44
import { useSnippets } from "../hooks/useSnippets";
5-
import slugify from "../utils/slugify";
65

76
import Button from "./Button";
8-
import CodePreview from "./CodePreview";
97
import SnippetModal from "./SnippetModal";
10-
import CopyToClipboard from "./CopyToClipboard";
11-
import { CloseIcon, ExpandIcon } from "./Icons";
8+
import { ExpandIcon } from "./Icons";
129

1310
const SnippetList = () => {
1411
const { language, setSnippet } = useAppContext();
@@ -33,9 +30,6 @@ const SnippetList = () => {
3330
<li key={idx} className="snippet">
3431
<div className="snippet__preview">
3532
<img src={language.icon} alt={language.lang} />
36-
{/* <Button isIcon={true} className="snippet__copy">
37-
<CopyIcon />
38-
</Button> */}
3933
</div>
4034

4135
<div className="snippet__content">
@@ -45,36 +39,11 @@ const SnippetList = () => {
4539
</Button>
4640
</div>
4741
{isModalOpen && (
48-
<SnippetModal>
49-
<div className="modal | flow" data-flow-space="lg">
50-
<div className="modal__header">
51-
<h2 className="section-title">{snippet.title}</h2>
52-
<Button isIcon={true} onClick={handleCloseModal}>
53-
<CloseIcon />
54-
</Button>
55-
</div>
56-
<div className="code-preview">
57-
<CopyToClipboard className="modal__copy" />
58-
<CodePreview language={slugify(language.lang)}>
59-
{snippet.code}
60-
</CodePreview>
61-
</div>
62-
<p>
63-
<b>Description: </b>
64-
{snippet.description}
65-
</p>
66-
<p>
67-
Contributed by <b>{snippet.author}</b>
68-
</p>
69-
<ul role="list" className="modal__tags">
70-
{snippet.tags.map((tag) => (
71-
<li key={tag} className="modal__tag">
72-
{tag}
73-
</li>
74-
))}
75-
</ul>
76-
</div>
77-
</SnippetModal>
42+
<SnippetModal
43+
snippet={snippet}
44+
handleCloseModal={handleCloseModal}
45+
language={language.lang}
46+
/>
7847
)}
7948
</li>
8049
))}

src/components/SnippetModal.tsx

+42-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,55 @@
11
import React from "react";
22
import ReactDOM from "react-dom";
3+
import Button from "./Button";
4+
import { CloseIcon } from "./Icons";
5+
import CopyToClipboard from "./CopyToClipboard";
6+
import CodePreview from "./CodePreview";
7+
import { SnippetType } from "../types";
8+
import slugify from "../utils/slugify";
39

410
type Props = {
5-
children: React.ReactNode;
11+
snippet: SnippetType;
12+
language: string;
13+
handleCloseModal: () => void;
614
};
715

8-
const SnippetModal: React.FC<Props> = ({ children }) => {
16+
const SnippetModal: React.FC<Props> = ({
17+
snippet,
18+
language,
19+
handleCloseModal,
20+
}) => {
921
const modalRoot = document.getElementById("modal-root");
1022
if (!modalRoot) return null;
1123

1224
return ReactDOM.createPortal(
13-
<div className="modal-overlay">{children}</div>,
25+
<div className="modal-overlay">
26+
<div className="modal | flow" data-flow-space="lg">
27+
<div className="modal__header">
28+
<h2 className="section-title">{snippet.title}</h2>
29+
<Button isIcon={true} onClick={handleCloseModal}>
30+
<CloseIcon />
31+
</Button>
32+
</div>
33+
<div className="code-preview">
34+
<CopyToClipboard text={snippet.code} className="modal__copy" />
35+
<CodePreview language={slugify(language)}>{snippet.code}</CodePreview>
36+
</div>
37+
<p>
38+
<b>Description: </b>
39+
{snippet.description}
40+
</p>
41+
<p>
42+
Contributed by <b>{snippet.author}</b>
43+
</p>
44+
<ul role="list" className="modal__tags">
45+
{snippet.tags.map((tag) => (
46+
<li key={tag} className="modal__tag">
47+
{tag}
48+
</li>
49+
))}
50+
</ul>
51+
</div>
52+
</div>,
1453
modalRoot
1554
);
1655
};

src/contexts/AppContext.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const defaultLanguage: LanguageType = {
99

1010
const defaultCategory: string = "DOM Manipulation";
1111

12+
// TODO: add custom loading and error handling
1213
const defaultState: AppState = {
1314
language: defaultLanguage,
1415
setLanguage: () => {},
File renamed without changes.
File renamed without changes.
File renamed without changes.

src/layouts/Header.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const Header = () => {
99
<Logo />
1010
<nav className="primary-nav">
1111
<SearchInput />
12-
<Button as="link" href="https://google.com">
12+
<Button as="link" href="https://github.com/dostonnabotov/quicksnip/">
1313
<GitHubIcon />
1414
<span>Add your snippet</span>
1515
</Button>

src/layouts/Sidebar.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import LanguageSelector from "../components/LanguageSelector";
12
import CategoryList from "../components/CategoryList";
2-
import LanguageSwitch from "../components/LanguageSwitch";
33

44
const Sidebar = () => {
55
return (
66
<aside className="sidebar flow">
7-
<LanguageSwitch />
7+
<LanguageSelector />
88
<CategoryList />
99
</aside>
1010
);

src/services/api.ts

-10
This file was deleted.

src/styles/main.css

-8
Original file line numberDiff line numberDiff line change
@@ -376,14 +376,6 @@ ol:where([role="list"]) {
376376
filter: grayscale(100%);
377377
}
378378

379-
.snippet__copy {
380-
position: absolute;
381-
z-index: 2;
382-
isolation: isolate;
383-
top: 0.25em;
384-
right: 0.25em;
385-
}
386-
387379
.snippet__content {
388380
display: flex;
389381
justify-content: space-between;

src/types/index.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ export type LanguageType = {
33
icon: string;
44
};
55

6+
export type CategoryType = {
7+
categoryName: string;
8+
snippets: SnippetType[];
9+
};
10+
611
export type SnippetType = {
712
title: string;
813
description: string;
@@ -11,11 +16,6 @@ export type SnippetType = {
1116
author: string;
1217
};
1318

14-
export type CategoryType = {
15-
categoryName: string;
16-
snippets: SnippetType[];
17-
};
18-
1919
export type AppState = {
2020
language: LanguageType;
2121
setLanguage: React.Dispatch<React.SetStateAction<LanguageType>>;

src/utils/filters.ts

-30
This file was deleted.

src/utils/slugify.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ const slugify = (string: string, separator = "-") => {
33
.toString() // Cast to string (optional)
44
.toLowerCase() // Convert the string to lowercase letters
55
.trim() // Remove whitespace from both sides of a string (optional)
6-
.replace(/\s+/g, separator) // Replace spaces with -
6+
.replace(/\s+/g, separator) // Replace spaces with {separator}
77
.replace(/[^\w\-]+/g, "") // Remove all non-word chars
8-
.replace(/\_/g, separator) // Replace _ with -
9-
.replace(/\-\-+/g, separator) // Replace multiple - with single -
8+
.replace(/\_/g, separator) // Replace _ with {separator}
9+
.replace(/\-\-+/g, separator) // Replace multiple - with single {separator}
1010
.replace(/\-$/g, ""); // Remove trailing -
1111
};
1212

0 commit comments

Comments
 (0)