Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 803f8fe

Browse files
committedOct 27, 2024
Initial commit
0 parents  commit 803f8fe

29 files changed

+3413
-0
lines changed
 

‎.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

‎README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# React + TypeScript + Vite
2+
3+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4+
5+
Currently, two official plugins are available:
6+
7+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9+
10+
## Expanding the ESLint configuration
11+
12+
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13+
14+
- Configure the top-level `parserOptions` property like this:
15+
16+
```js
17+
export default tseslint.config({
18+
languageOptions: {
19+
// other options...
20+
parserOptions: {
21+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
22+
tsconfigRootDir: import.meta.dirname,
23+
},
24+
},
25+
})
26+
```
27+
28+
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
29+
- Optionally add `...tseslint.configs.stylisticTypeChecked`
30+
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
31+
32+
```js
33+
// eslint.config.js
34+
import react from 'eslint-plugin-react'
35+
36+
export default tseslint.config({
37+
// Set the react version
38+
settings: { react: { version: '18.3' } },
39+
plugins: {
40+
// Add the react plugin
41+
react,
42+
},
43+
rules: {
44+
// other rules...
45+
// Enable its recommended rules
46+
...react.configs.recommended.rules,
47+
...react.configs['jsx-runtime'].rules,
48+
},
49+
})
50+
```

‎eslint.config.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import js from '@eslint/js'
2+
import globals from 'globals'
3+
import reactHooks from 'eslint-plugin-react-hooks'
4+
import reactRefresh from 'eslint-plugin-react-refresh'
5+
import tseslint from 'typescript-eslint'
6+
7+
export default tseslint.config(
8+
{ ignores: ['dist'] },
9+
{
10+
extends: [js.configs.recommended, ...tseslint.configs.recommended],
11+
files: ['**/*.{ts,tsx}'],
12+
languageOptions: {
13+
ecmaVersion: 2020,
14+
globals: globals.browser,
15+
},
16+
plugins: {
17+
'react-hooks': reactHooks,
18+
'react-refresh': reactRefresh,
19+
},
20+
rules: {
21+
...reactHooks.configs.recommended.rules,
22+
'react-refresh/only-export-components': [
23+
'warn',
24+
{ allowConstantExport: true },
25+
],
26+
},
27+
},
28+
)

‎index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + React + TS</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>

‎package-lock.json

Lines changed: 2634 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "quicksnip",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "tsc -b && vite build",
9+
"lint": "eslint .",
10+
"preview": "vite preview"
11+
},
12+
"dependencies": {
13+
"react": "^18.3.1",
14+
"react-dom": "^18.3.1",
15+
"react-router-dom": "^6.27.0"
16+
},
17+
"devDependencies": {
18+
"@eslint/js": "^9.11.1",
19+
"@types/react": "^18.3.10",
20+
"@types/react-dom": "^18.3.0",
21+
"@vitejs/plugin-react-swc": "^3.5.0",
22+
"eslint": "^9.11.1",
23+
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
24+
"eslint-plugin-react-refresh": "^0.4.12",
25+
"globals": "^15.9.0",
26+
"typescript": "^5.5.3",
27+
"typescript-eslint": "^8.7.0",
28+
"vite": "^5.4.8"
29+
}
30+
}

‎public/data/index.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"languages": ["JavaScript", "Python"]
3+
}

‎public/data/javascript.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"language": "JavaScript",
3+
"categories": [
4+
{
5+
"categoryName": "DOM Manipulation",
6+
"snippets": [
7+
{
8+
"title": "Add a class to an element",
9+
"description": "Add a CSS class to a DOM element.",
10+
"code": "document.getElementById('myElement').classList.add('myClass');",
11+
"tags": ["dom", "class", "javascript"],
12+
"author": "@technoph1le",
13+
"dateAdded": "2024-10-23"
14+
},
15+
{
16+
"title": "Remove a class from an element",
17+
"description": "Remove a CSS class from a DOM element.",
18+
"code": "document.getElementById('myElement').classList.remove('myClass');",
19+
"tags": ["dom", "class", "javascript"],
20+
"author": "@technoph1le",
21+
"dateAdded": "2024-10-22"
22+
}
23+
]
24+
},
25+
{
26+
"categoryName": "API Requests",
27+
"snippets": [
28+
{
29+
"title": "Fetch data from API",
30+
"description": "Use the Fetch API to retrieve data.",
31+
"code": "fetch('https://api.example.com/data').then(response => response.json()).then(data => console.log(data));",
32+
"tags": ["api", "fetch", "javascript"],
33+
"author": "@technoph1le",
34+
"dateAdded": "2024-10-23"
35+
}
36+
]
37+
}
38+
]
39+
}

‎public/data/python.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"language": "Python",
3+
"categories": [
4+
{
5+
"categoryName": "File Handling",
6+
"snippets": [
7+
{
8+
"title": "Read a File",
9+
"description": "Reads the entire content of a file.",
10+
"code": "with open('file.txt', 'r') as file:\n content = file.read()\n print(content)",
11+
"tags": ["file", "read", "python"],
12+
"author": "@technoph1le",
13+
"dateAdded": "2024-10-23"
14+
},
15+
{
16+
"title": "Write to a File",
17+
"description": "Writes a string to a file.",
18+
"code": "with open('file.txt', 'w') as file:\n file.write('Hello, World!')",
19+
"tags": ["file", "write", "python"],
20+
"author": "@technoph1le",
21+
"dateAdded": "2024-10-23"
22+
}
23+
]
24+
},
25+
{
26+
"categoryName": "Data Structures",
27+
"snippets": [
28+
{
29+
"title": "Reverse a List",
30+
"description": "Reverses a list using slicing.",
31+
"code": "my_list = [1, 2, 3, 4, 5]\nreversed_list = my_list[::-1]\nprint(reversed_list)",
32+
"tags": ["list", "reverse", "python"],
33+
"author": "@technoph1le",
34+
"dateAdded": "2024-10-23"
35+
},
36+
{
37+
"title": "Dictionary Comprehension",
38+
"description": "Creates a dictionary with squares of numbers.",
39+
"code": "squares = {x: x*x for x in range(6)}\nprint(squares)",
40+
"tags": ["dictionary", "comprehension", "python"],
41+
"author": "@technoph1le",
42+
"dateAdded": "2024-10-23"
43+
}
44+
]
45+
}
46+
]
47+
}
Binary file not shown.
632 KB
Binary file not shown.

‎public/vite.svg

Lines changed: 1 addition & 0 deletions
Loading

‎src/components/Button.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { ReactNode } from "react";
2+
3+
type ButtonProps = {
4+
as?: "button" | "link";
5+
href?: string;
6+
children: ReactNode;
7+
};
8+
9+
const Button = ({ as = "button", href, children, ...props }: ButtonProps) => {
10+
return as === "button" ? (
11+
<button className="button" {...props}>
12+
{children}
13+
</button>
14+
) : (
15+
<a className="button" href={href} {...props}>
16+
{children}
17+
</a>
18+
);
19+
};
20+
21+
export default Button;

‎src/components/Icons.tsx

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
const DEFAULT_ICON_COLOR = "var(--text-primary)";
2+
3+
export const LogoIcon = () => {
4+
return (
5+
<svg
6+
width="44"
7+
height="30"
8+
viewBox="0 0 44 30"
9+
fill="none"
10+
xmlns="http://www.w3.org/2000/svg"
11+
>
12+
<path
13+
d="M11.1623 3.96725C8.96775 3.96725 7.9365 4.62725 8.0685 5.94725L8.5635 11.021C8.58 11.1695 8.58825 11.384 8.58825 11.6645C8.58825 12.4565 8.3985 13.067 8.019 13.496C7.6395 13.9085 7.05375 14.189 6.26175 14.3375C7.07025 14.486 7.656 14.7665 8.019 15.179C8.3985 15.575 8.58825 16.1772 8.58825 16.9857C8.58825 17.2662 8.58 17.489 8.5635 17.654L8.0685 22.7277C8.0025 23.4537 8.25 23.9653 8.811 24.2623C9.372 24.5593 10.1558 24.7078 11.1623 24.7078V26.366C9.67725 26.366 8.4645 26.1103 7.524 25.5988C6.5835 25.0873 6.11325 24.221 6.11325 23C6.11325 22.7855 6.1215 22.6205 6.138 22.505L6.65775 17.8025C6.67425 17.687 6.6825 17.522 6.6825 17.3075C6.6825 16.5815 6.41025 16.0452 5.86575 15.6987C5.32125 15.3522 4.33125 15.179 2.89575 15.179V13.496C4.33125 13.496 5.32125 13.331 5.86575 13.001C6.41025 12.6545 6.6825 12.1182 6.6825 11.3922C6.6825 11.1942 6.67425 11.0375 6.65775 10.922L6.138 6.17C6.1215 6.0545 6.11325 5.8895 6.11325 5.675C6.11325 4.454 6.5835 3.58775 7.524 3.07625C8.4645 2.56475 9.67725 2.309 11.1623 2.309V3.96725Z"
14+
fill="url(#paint0_linear_11_2)"
15+
/>
16+
<path
17+
d="M30.8281 13.3735L18.5599 25.9883C18.219 26.3378 17.6536 25.9329 17.8752 25.4982L22.2421 16.881C22.2751 16.8159 22.291 16.7435 22.288 16.6706C22.2851 16.5977 22.2635 16.5267 22.2253 16.4646C22.1871 16.4024 22.1335 16.3511 22.0698 16.3156C22.0061 16.28 21.9343 16.2614 21.8613 16.2616H12.6758C12.5919 16.2615 12.5099 16.2367 12.4401 16.1902C12.3702 16.1437 12.3157 16.0777 12.2832 16.0003C12.2507 15.9229 12.2418 15.8377 12.2576 15.7553C12.2734 15.6729 12.3131 15.597 12.3718 15.5371L23.7507 4.00902C24.0803 3.67518 24.6286 4.04169 24.4454 4.47497L21.1823 12.1674C21.1547 12.2327 21.1437 12.3037 21.1505 12.3742C21.1572 12.4447 21.1814 12.5125 21.2209 12.5713C21.2604 12.6301 21.3139 12.6781 21.3766 12.711C21.4393 12.7439 21.5092 12.7607 21.5801 12.7598L30.517 12.649C30.6013 12.6477 30.6842 12.6714 30.755 12.7171C30.8259 12.7629 30.8816 12.8286 30.915 12.9061C30.9485 12.9835 30.9582 13.0691 30.943 13.1521C30.9278 13.235 30.8883 13.3116 30.8295 13.3721L30.8281 13.3735Z"
18+
stroke="url(#paint1_linear_11_2)"
19+
stroke-width="1.65"
20+
/>
21+
<path
22+
d="M31.8878 2.309C33.3728 2.309 34.5855 2.56475 35.526 3.07625C36.4665 3.58775 36.9368 4.454 36.9368 5.675C36.9368 5.8895 36.9285 6.0545 36.912 6.17L36.3923 10.922C36.3758 11.0045 36.3675 11.1282 36.3675 11.2932C36.3675 12.0357 36.6563 12.5885 37.2338 12.9515C37.8278 13.3145 38.8013 13.496 40.1543 13.496V15.179C38.7848 15.179 37.8113 15.3605 37.2338 15.7235C36.6563 16.0865 36.3675 16.6475 36.3675 17.4065C36.3675 17.5715 36.3758 17.7035 36.3923 17.8025L36.912 22.505C36.9285 22.6205 36.9368 22.7855 36.9368 23C36.9368 24.221 36.4665 25.0873 35.526 25.5988C34.5855 26.1103 33.3728 26.366 31.8878 26.366V24.7078C32.8943 24.7078 33.678 24.5593 34.239 24.2623C34.8 23.9653 35.0475 23.4537 34.9815 22.7277L34.4865 17.654C34.4535 17.324 34.437 17.1012 34.437 16.9857C34.437 16.1607 34.6433 15.5502 35.0558 15.1542C35.4683 14.7582 36.1365 14.4942 37.0605 14.3622C36.1695 14.1972 35.5095 13.9085 35.0805 13.496C34.668 13.067 34.4618 12.4482 34.4618 11.6397C34.4618 11.3757 34.47 11.1695 34.4865 11.021L34.9815 5.94725C35.1135 4.62725 34.0823 3.96725 31.8878 3.96725V2.309Z"
23+
fill="url(#paint2_linear_11_2)"
24+
/>
25+
<defs>
26+
<linearGradient
27+
id="paint0_linear_11_2"
28+
x1="2.0336e-07"
29+
y1="14.6512"
30+
x2="15"
31+
y2="14.6512"
32+
gradientUnits="userSpaceOnUse"
33+
>
34+
<stop stop-color="#00B4D8" />
35+
<stop offset="1" stop-color="#2A2A2A" />
36+
</linearGradient>
37+
<linearGradient
38+
id="paint1_linear_11_2"
39+
x1="12.25"
40+
y1="14.7414"
41+
x2="30.95"
42+
y2="14.7414"
43+
gradientUnits="userSpaceOnUse"
44+
>
45+
<stop stop-color="#00B4D8" />
46+
<stop offset="1" stop-color="#2A2A2A" />
47+
</linearGradient>
48+
<linearGradient
49+
id="paint2_linear_11_2"
50+
x1="28.2"
51+
y1="14.6512"
52+
x2="43.2"
53+
y2="14.6512"
54+
gradientUnits="userSpaceOnUse"
55+
>
56+
<stop stop-color="#00B4D8" />
57+
<stop offset="1" stop-color="#2A2A2A" />
58+
</linearGradient>
59+
</defs>
60+
</svg>
61+
);
62+
};
63+
64+
export const SearchIcon = ({ fillColor = DEFAULT_ICON_COLOR }) => {
65+
return (
66+
<svg
67+
width="24"
68+
height="24"
69+
viewBox="0 0 24 24"
70+
fill="none"
71+
xmlns="http://www.w3.org/2000/svg"
72+
>
73+
<path
74+
d="M19.6 21L13.3 14.7C12.8 15.1 12.225 15.4167 11.575 15.65C10.925 15.8833 10.2333 16 9.5 16C7.68333 16 6.146 15.3707 4.888 14.112C3.63 12.8533 3.00067 11.316 3 9.5C2.99933 7.684 3.62867 6.14667 4.888 4.888C6.14733 3.62933 7.68467 3 9.5 3C11.3153 3 12.853 3.62933 14.113 4.888C15.373 6.14667 16.002 7.684 16 9.5C16 10.2333 15.8833 10.925 15.65 11.575C15.4167 12.225 15.1 12.8 14.7 13.3L21 19.6L19.6 21ZM9.5 14C10.75 14 11.8127 13.5627 12.688 12.688C13.5633 11.8133 14.0007 10.7507 14 9.5C13.9993 8.24933 13.562 7.187 12.688 6.313C11.814 5.439 10.7513 5.00133 9.5 5C8.24867 4.99867 7.18633 5.43633 6.313 6.313C5.43967 7.18967 5.002 8.252 5 9.5C4.998 10.748 5.43567 11.8107 6.313 12.688C7.19033 13.5653 8.25267 14.0027 9.5 14Z"
75+
fill={fillColor}
76+
/>
77+
</svg>
78+
);
79+
};
80+
81+
export const GitHubIcon = ({ fillColor = DEFAULT_ICON_COLOR }) => {
82+
return (
83+
<svg
84+
width="24"
85+
height="24"
86+
viewBox="0 0 24 24"
87+
fill="none"
88+
xmlns="http://www.w3.org/2000/svg"
89+
>
90+
<path
91+
d="M12 2C10.6868 2 9.38642 2.25866 8.17317 2.7612C6.95991 3.26375 5.85752 4.00035 4.92893 4.92893C3.05357 6.8043 2 9.34784 2 12C2 16.42 4.87 20.17 8.84 21.5C9.34 21.58 9.5 21.27 9.5 21V19.31C6.73 19.91 6.14 17.97 6.14 17.97C5.68 16.81 5.03 16.5 5.03 16.5C4.12 15.88 5.1 15.9 5.1 15.9C6.1 15.97 6.63 16.93 6.63 16.93C7.5 18.45 8.97 18 9.54 17.76C9.63 17.11 9.89 16.67 10.17 16.42C7.95 16.17 5.62 15.31 5.62 11.5C5.62 10.39 6 9.5 6.65 8.79C6.55 8.54 6.2 7.5 6.75 6.15C6.75 6.15 7.59 5.88 9.5 7.17C10.29 6.95 11.15 6.84 12 6.84C12.85 6.84 13.71 6.95 14.5 7.17C16.41 5.88 17.25 6.15 17.25 6.15C17.8 7.5 17.45 8.54 17.35 8.79C18 9.5 18.38 10.39 18.38 11.5C18.38 15.32 16.04 16.16 13.81 16.41C14.17 16.72 14.5 17.33 14.5 18.26V21C14.5 21.27 14.66 21.59 15.17 21.5C19.14 20.16 22 16.42 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7362 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2Z"
92+
fill={fillColor}
93+
/>
94+
</svg>
95+
);
96+
};
97+
98+
export const SwitchIcon = ({ fillColor = DEFAULT_ICON_COLOR }) => {
99+
return (
100+
<svg
101+
width="24"
102+
height="24"
103+
viewBox="0 0 24 24"
104+
fill="none"
105+
xmlns="http://www.w3.org/2000/svg"
106+
>
107+
<path
108+
d="M3 9.5H21L15 3.5M21.3995 14.5H3.3995L9.3995 20.5"
109+
stroke={fillColor}
110+
stroke-width="2"
111+
stroke-linecap="round"
112+
stroke-linejoin="round"
113+
/>
114+
</svg>
115+
);
116+
};

‎src/components/Logo.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { LogoIcon } from "./Icons";
2+
3+
const Logo = () => {
4+
return (
5+
<a className="logo" href="/">
6+
<LogoIcon />
7+
<span>QuickSnip</span>
8+
</a>
9+
);
10+
};
11+
12+
export default Logo;

‎src/components/SearchInput.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { SearchIcon } from "./Icons";
2+
3+
const SearchInput = () => {
4+
return (
5+
<div className="search-field">
6+
<label htmlFor="search">
7+
<SearchIcon />
8+
</label>
9+
<input
10+
type="search"
11+
id="search"
12+
placeholder="Search here..."
13+
autoComplete="off"
14+
/>
15+
</div>
16+
);
17+
};
18+
19+
export default SearchInput;

‎src/layouts/Footer.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const Footer = () => {
2+
return <p>Footer</p>;
3+
};
4+
5+
export default Footer;

‎src/layouts/Header.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Button from "../ui/Button";
2+
import { GitHubIcon } from "../ui/Icons";
3+
import Logo from "../ui/Logo";
4+
import SearchInput from "../ui/SearchInput";
5+
6+
const Header = () => {
7+
return (
8+
<header className="header">
9+
<Logo />
10+
<nav className="primary-nav">
11+
<SearchInput />
12+
<Button as="link" href="https://google.com">
13+
<GitHubIcon />
14+
<span>Add your snippet</span>
15+
</Button>
16+
</nav>
17+
</header>
18+
);
19+
};
20+
21+
export default Header;

‎src/layouts/Sidebar.tsx

Whitespace-only changes.

‎src/main.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function App() {
2+
return (
3+
<div>
4+
<h1>App Loaded</h1>
5+
</div>
6+
);
7+
}
8+
9+
export default App;

‎src/services/api.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export const getLanguages = async () => {
2+
try {
3+
const res = await fetch("/data/index.json");
4+
const data = await res.json();
5+
6+
return data.languages;
7+
} catch (error) {
8+
console.error("Error occured: ", error);
9+
}
10+
};
11+
12+
export const getSnippetsByLanguage = async (language: string) => {
13+
try {
14+
const res = await fetch(`/data/${language}.json`);
15+
const data = await res.json();
16+
17+
return data;
18+
} catch (error) {
19+
console.error("Error occured: ", error);
20+
}
21+
};

‎src/styles/main.css

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/*------------------------------------*\
2+
#SETTINGS
3+
\*------------------------------------*/
4+
@font-face {
5+
font-family: "Source Sans 3";
6+
src: url("/fonts/SourceSans3-VariableFont_wght.ttf");
7+
font-style: normal;
8+
}
9+
10+
@font-face {
11+
font-family: "Source Sans 3";
12+
src: url("/fonts/SourceSans3-Italic-VariableFont_wght.ttf");
13+
font-style: italic;
14+
}
15+
16+
:root {
17+
--clr-neutral-200: #e0e0e0;
18+
--clr-neutral-300: #b3b3b3;
19+
--clr-neutral-500: #3c3c3c;
20+
--clr-neutral-700: #2a2a2a;
21+
--clr-neutral-900: #1c1c1c;
22+
23+
--clr-accent: #00b4b8;
24+
25+
--gradient-primary: linear-gradient(
26+
90deg,
27+
var(--clr-accent) 0%,
28+
var(--clr-neutral-700) 100%
29+
);
30+
--gradient-secondary: linear-gradient(
31+
90deg,
32+
var(--clr-neutral-500) 0%,
33+
var(--clr-neutral-700) 100%
34+
);
35+
36+
--bg-primary: var(--clr-neutral-900);
37+
--bg-secondary: var(--clr-neutral-700);
38+
--text-primary: var(--clr-neutral-200);
39+
--text-secondary: var(--clr-neutral-300);
40+
--border-color: var(--clr-neutral-500);
41+
42+
--ff-primary: "Source Sans 3", sans-serif;
43+
44+
--fs-400: 1rem;
45+
--fs-500: 1.125rem;
46+
--fs-600: 1.5rem;
47+
--fs-700: 2rem;
48+
--fs-800: 2.5rem;
49+
50+
--fw-bold: 700;
51+
--fw-semi: 600;
52+
--fw-normal: 400;
53+
54+
--border-radius-md: 0.5rem;
55+
--border-radius-lg: 0.75rem;
56+
}
57+
58+
/*------------------------------------*\
59+
#GENERIC
60+
\*------------------------------------*/
61+
/**
62+
* @link https://piccalil.li/blog/a-more-modern-css-reset/
63+
*/
64+
*,
65+
*::before,
66+
*::after {
67+
box-sizing: border-box;
68+
}
69+
70+
body,
71+
h1,
72+
h2,
73+
h3,
74+
h4,
75+
p {
76+
margin: 0;
77+
}
78+
79+
body {
80+
min-height: 100vh;
81+
line-height: 1.5;
82+
}
83+
84+
h1,
85+
h2,
86+
h3,
87+
h4,
88+
button,
89+
input,
90+
label {
91+
line-height: 1.1;
92+
}
93+
94+
h1,
95+
h2,
96+
h3,
97+
h4 {
98+
text-wrap: balance;
99+
}
100+
101+
img,
102+
picture {
103+
max-width: 100%;
104+
display: block;
105+
}
106+
107+
input,
108+
button,
109+
textarea,
110+
select {
111+
font-family: inherit;
112+
font-size: inherit;
113+
}
114+
115+
/*------------------------------------*\
116+
#BASE
117+
\*------------------------------------*/
118+
html {
119+
color-scheme: dark;
120+
}
121+
122+
body {
123+
font-family: var(--ff-primary);
124+
background-color: var(--bg-primary);
125+
color: var(--text-secondary);
126+
}
127+
128+
/*------------------------------------*\
129+
#COMPONENTS
130+
\*------------------------------------*/
131+
.button {
132+
display: inline-flex;
133+
min-height: 3rem;
134+
align-items: center;
135+
gap: 0.75rem;
136+
background-color: var(--bg-secondary);
137+
border: 1px solid var(--border-color);
138+
padding: 0.75em 1.125em;
139+
color: var(--text-primary);
140+
border-radius: var(--border-radius-md);
141+
cursor: pointer;
142+
line-height: 1.1;
143+
text-decoration: none;
144+
145+
&:active {
146+
scale: 0.95;
147+
}
148+
}
149+
150+
.search-field {
151+
display: inline-flex;
152+
align-items: center;
153+
min-height: 3rem;
154+
gap: 0.75rem;
155+
border: 1px solid var(--border-color);
156+
border-radius: var(--border-radius-md);
157+
padding: 0.75em 1.125em;
158+
}
159+
160+
.search-field > input {
161+
background-color: transparent;
162+
border: none;
163+
164+
&:focus {
165+
outline: none;
166+
}
167+
}
168+
169+
.logo {
170+
display: inline-flex;
171+
gap: 0.25em;
172+
color: var(--text-primary);
173+
text-decoration: none;
174+
175+
& > span {
176+
font-size: var(--fs-600);
177+
font-weight: var(--fw-bold);
178+
}
179+
}
180+
181+
/*------------------------------------*\
182+
#UTILS
183+
\*------------------------------------*/
184+
/* Layout */
185+
.container {
186+
max-width: 80rem;
187+
width: 100%;
188+
padding-inline: clamp(1rem, 4vw, 3rem);
189+
margin-inline: auto;
190+
}
191+
192+
/* Text */
193+
.main-title {
194+
font-size: var(--fs-800);
195+
font-weight: var(--fw-bold);
196+
color: var(--text-primary);
197+
}
198+
199+
.section-title {
200+
font-size: var(--fs-600);
201+
font-weight: var(--fw-bold);
202+
color: var(--text-primary);
203+
}
204+
205+
.text-highlight {
206+
background-image: var(--gradient-primary);
207+
background-clip: text;
208+
-webkit-background-clip: text;
209+
-webkit-text-fill-color: transparent;
210+
}
211+
212+
.divider {
213+
width: 100%;
214+
height: 1px;
215+
background-image: var(--gradient-primary);
216+
border: none;
217+
}
218+
219+
/*------------------------------------*\
220+
#HEADER
221+
\*------------------------------------*/
222+
.header {
223+
padding-block: 2rem;
224+
display: flex;
225+
align-items: center;
226+
justify-content: space-between;
227+
gap: 2rem;
228+
flex-wrap: wrap;
229+
}
230+
231+
.primary-nav {
232+
display: flex;
233+
align-items: center;
234+
flex-wrap: wrap;
235+
gap: 1.5rem;
236+
}
237+
238+
/*------------------------------------*\
239+
#MAIN
240+
\*------------------------------------*/
241+
.heading {
242+
display: grid;
243+
gap: 0.5em;
244+
padding-block: 2rem;
245+
text-align: center;
246+
}

‎src/types/index.ts

Whitespace-only changes.

‎src/utils/slugify.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const slugify = (string: string, separator = "-") => {
2+
return string
3+
.toString() // Cast to string (optional)
4+
.toLowerCase() // Convert the string to lowercase letters
5+
.trim() // Remove whitespace from both sides of a string (optional)
6+
.replace(/\s+/g, separator) // Replace spaces with -
7+
.replace(/[^\w\-]+/g, "") // Remove all non-word chars
8+
.replace(/\_/g, separator) // Replace _ with -
9+
.replace(/\-\-+/g, separator) // Replace multiple - with single -
10+
.replace(/\-$/g, ""); // Remove trailing -
11+
};
12+
13+
export default slugify;

‎src/vite-env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="vite/client" />

‎tsconfig.app.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"useDefineForClassFields": true,
5+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
6+
"module": "ESNext",
7+
"skipLibCheck": true,
8+
9+
/* Bundler mode */
10+
"moduleResolution": "bundler",
11+
"allowImportingTsExtensions": true,
12+
"isolatedModules": true,
13+
"moduleDetection": "force",
14+
"noEmit": true,
15+
"jsx": "react-jsx",
16+
17+
/* Linting */
18+
"strict": true,
19+
"noUnusedLocals": true,
20+
"noUnusedParameters": true,
21+
"noFallthroughCasesInSwitch": true
22+
},
23+
"include": ["src"]
24+
}

‎tsconfig.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"files": [],
3+
"references": [
4+
{ "path": "./tsconfig.app.json" },
5+
{ "path": "./tsconfig.node.json" }
6+
]
7+
}

‎tsconfig.node.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2022",
4+
"lib": ["ES2023"],
5+
"module": "ESNext",
6+
"skipLibCheck": true,
7+
8+
/* Bundler mode */
9+
"moduleResolution": "bundler",
10+
"allowImportingTsExtensions": true,
11+
"isolatedModules": true,
12+
"moduleDetection": "force",
13+
"noEmit": true,
14+
15+
/* Linting */
16+
"strict": true,
17+
"noUnusedLocals": true,
18+
"noUnusedParameters": true,
19+
"noFallthroughCasesInSwitch": true
20+
},
21+
"include": ["vite.config.ts"]
22+
}

‎vite.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from 'vite'
2+
import react from '@vitejs/plugin-react-swc'
3+
4+
// https://vitejs.dev/config/
5+
export default defineConfig({
6+
plugins: [react()],
7+
})

0 commit comments

Comments
 (0)
Please sign in to comment.