Skip to content

Commit c4b281a

Browse files
committedDec 14, 2024
ui and ux adjustments
·
v2.0.0v0.5.0
1 parent a0d7395 commit c4b281a

File tree

13 files changed

+249
-138
lines changed

13 files changed

+249
-138
lines changed
 

‎public/data/css.json‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
"description": "Adjusts font size based on viewport width.",
88
"code": "h1 {\n font-size: calc(1.5rem + 2vw);\n}",
99
"tags": ["css", "font", "responsive", "typography"],
10-
"author": "@technoph1le"
10+
"author": "dostonnabotov"
1111
},
1212
{
1313
"title": "Letter Spacing",
1414
"description": "Adds space between letters for better readability.",
1515
"code": "p {\n letter-spacing: 0.05em;\n}",
1616
"tags": ["css", "typography", "spacing"],
17-
"author": "@technoph1le"
17+
"author": "dostonnabotov"
1818
}
1919
]
2020
},
@@ -26,14 +26,14 @@
2626
"description": "Ensures the footer always stays at the bottom of the page.",
2727
"code": "body {\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n}\n\nfooter {\n margin-top: auto;\n}",
2828
"tags": ["css", "layout", "footer", "sticky"],
29-
"author": "@technoph1le"
29+
"author": "dostonnabotov"
3030
},
3131
{
3232
"title": "Equal-Width Columns",
3333
"description": "Creates columns with equal widths using flexbox.",
3434
"code": ".columns {\n display: flex;\n justify-content: space-between;\n}\n\n.column {\n flex: 1;\n margin: 0 10px;\n}",
3535
"tags": ["css", "flexbox", "columns", "layout"],
36-
"author": "@technoph1le"
36+
"author": "dostonnabotov"
3737
}
3838
]
3939
},
@@ -45,14 +45,14 @@
4545
"description": "Creates a hover effect with a color transition.",
4646
"code": ".button {\n background-color: #007bff;\n color: white;\n padding: 10px 20px;\n border: none;\n border-radius: 5px;\n cursor: pointer;\n transition: background-color 0.3s ease;\n}\n\n.button:hover {\n background-color: #0056b3;\n}",
4747
"tags": ["css", "button", "hover", "transition"],
48-
"author": "@technoph1le"
48+
"author": "dostonnabotov"
4949
},
5050
{
5151
"title": "3D Button Effect",
5252
"description": "Adds a 3D effect to a button when clicked.",
5353
"code": ".button {\n background-color: #28a745;\n color: white;\n padding: 10px 20px;\n border: none;\n border-radius: 5px;\n box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);\n transition: transform 0.1s;\n}\n\n.button:active {\n transform: translateY(2px);\n box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);\n}",
5454
"tags": ["css", "button", "3D", "effect"],
55-
"author": "@technoph1le"
55+
"author": "dostonnabotov"
5656
}
5757
]
5858
},
@@ -64,14 +64,14 @@
6464
"description": "Applies a blur effect to the background of an element.",
6565
"code": ".blur-background {\n backdrop-filter: blur(10px);\n background: rgba(255, 255, 255, 0.5);\n}",
6666
"tags": ["css", "blur", "background", "effects"],
67-
"author": "@technoph1le"
67+
"author": "dostonnabotov"
6868
},
6969
{
7070
"title": "Hover Glow Effect",
7171
"description": "Adds a glowing effect on hover.",
7272
"code": ".glow {\n background-color: #f39c12;\n padding: 10px 20px;\n border-radius: 5px;\n transition: box-shadow 0.3s ease;\n}\n\n.glow:hover {\n box-shadow: 0 0 15px rgba(243, 156, 18, 0.8);\n}",
7373
"tags": ["css", "hover", "glow", "effects"],
74-
"author": "@technoph1le"
74+
"author": "dostonnabotov"
7575
}
7676
]
7777
}

‎public/data/javascript.json‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
"description": "Removes duplicate values from an array.",
88
"code": "const removeDuplicates = (arr) => [...new Set(arr)];\n\n// Usage:\nconst numbers = [1, 2, 2, 3, 4, 4, 5];\nconsole.log(removeDuplicates(numbers)); // Output: [1, 2, 3, 4, 5]",
99
"tags": ["javascript", "array", "deduplicate", "utility"],
10-
"author": "@technoph1le"
10+
"author": "dostonnabotov"
1111
},
1212
{
1313
"title": "Flatten Array",
1414
"description": "Flattens a multi-dimensional array.",
1515
"code": "const flattenArray = (arr) => arr.flat(Infinity);\n\n// Usage:\nconst nestedArray = [1, [2, [3, [4]]]];\nconsole.log(flattenArray(nestedArray)); // Output: [1, 2, 3, 4]",
1616
"tags": ["javascript", "array", "flatten", "utility"],
17-
"author": "@technoph1le"
17+
"author": "dostonnabotov"
1818
}
1919
]
2020
},
@@ -26,14 +26,14 @@
2626
"description": "Capitalizes the first letter of a string.",
2727
"code": "const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);\n\n// Usage:\nconsole.log(capitalize('hello')); // Output: 'Hello'",
2828
"tags": ["javascript", "string", "capitalize", "utility"],
29-
"author": "@technoph1le"
29+
"author": "dostonnabotov"
3030
},
3131
{
3232
"title": "Reverse String",
3333
"description": "Reverses the characters in a string.",
3434
"code": "const reverseString = (str) => str.split('').reverse().join('');\n\n// Usage:\nconsole.log(reverseString('hello')); // Output: 'olleh'",
3535
"tags": ["javascript", "string", "reverse", "utility"],
36-
"author": "@technoph1le"
36+
"author": "dostonnabotov"
3737
}
3838
]
3939
},
@@ -45,14 +45,14 @@
4545
"description": "Formats a date in 'YYYY-MM-DD' format.",
4646
"code": "const formatDate = (date) => date.toISOString().split('T')[0];\n\n// Usage:\nconsole.log(formatDate(new Date())); // Output: '2024-12-10'",
4747
"tags": ["javascript", "date", "format", "utility"],
48-
"author": "@technoph1le"
48+
"author": "dostonnabotov"
4949
},
5050
{
5151
"title": "Get Time Difference",
5252
"description": "Calculates the time difference in days between two dates.",
5353
"code": "const getTimeDifference = (date1, date2) => {\n const diff = Math.abs(date2 - date1);\n return Math.ceil(diff / (1000 * 60 * 60 * 24));\n};\n\n// Usage:\nconst date1 = new Date('2024-01-01');\nconst date2 = new Date('2024-12-31');\nconsole.log(getTimeDifference(date1, date2)); // Output: 365",
5454
"tags": ["javascript", "date", "time-difference", "utility"],
55-
"author": "@technoph1le"
55+
"author": "dostonnabotov"
5656
}
5757
]
5858
},
@@ -64,14 +64,14 @@
6464
"description": "Delays a function execution until after a specified time.",
6565
"code": "const debounce = (func, delay) => {\n let timeout;\n return (...args) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => func(...args), delay);\n };\n};\n\n// Usage:\nwindow.addEventListener('resize', debounce(() => console.log('Resized!'), 500));",
6666
"tags": ["javascript", "utility", "debounce", "performance"],
67-
"author": "@technoph1le"
67+
"author": "dostonnabotov"
6868
},
6969
{
7070
"title": "Throttle Function",
7171
"description": "Limits a function execution to once every specified time interval.",
7272
"code": "const throttle = (func, limit) => {\n let lastFunc;\n let lastRan;\n return (...args) => {\n const context = this;\n if (!lastRan) {\n func.apply(context, args);\n lastRan = Date.now();\n } else {\n clearTimeout(lastFunc);\n lastFunc = setTimeout(() => {\n if (Date.now() - lastRan >= limit) {\n func.apply(context, args);\n lastRan = Date.now();\n }\n }, limit - (Date.now() - lastRan));\n }\n };\n};\n\n// Usage:\ndocument.addEventListener('scroll', throttle(() => console.log('Scrolled!'), 1000));",
7373
"tags": ["javascript", "utility", "throttle", "performance"],
74-
"author": "@technoph1le"
74+
"author": "dostonnabotov"
7575
}
7676
]
7777
},
@@ -83,14 +83,14 @@
8383
"description": "Toggles a class on an element.",
8484
"code": "const toggleClass = (element, className) => {\n element.classList.toggle(className);\n};\n\n// Usage:\nconst element = document.querySelector('.my-element');\ntoggleClass(element, 'active');",
8585
"tags": ["javascript", "dom", "class", "utility"],
86-
"author": "@technoph1le"
86+
"author": "dostonnabotov"
8787
},
8888
{
8989
"title": "Smooth Scroll to Element",
9090
"description": "Scrolls smoothly to a specified element.",
9191
"code": "const smoothScroll = (element) => {\n element.scrollIntoView({ behavior: 'smooth' });\n};\n\n// Usage:\nconst target = document.querySelector('#target');\nsmoothScroll(target);",
9292
"tags": ["javascript", "dom", "scroll", "ui"],
93-
"author": "@technoph1le"
93+
"author": "dostonnabotov"
9494
}
9595
]
9696
}

‎public/data/python.json‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
"description": "Reverses the characters in a string.",
88
"code": "def reverse_string(s):\n return s[::-1]\n\n# Usage:\nprint(reverse_string('hello')) # Output: 'olleh'",
99
"tags": ["python", "string", "reverse", "utility"],
10-
"author": "@technoph1le"
10+
"author": "dostonnabotov"
1111
},
1212
{
1313
"title": "Check Palindrome",
1414
"description": "Checks if a string is a palindrome.",
1515
"code": "def is_palindrome(s):\n s = s.lower().replace(' ', '')\n return s == s[::-1]\n\n# Usage:\nprint(is_palindrome('A man a plan a canal Panama')) # Output: True",
1616
"tags": ["python", "string", "palindrome", "utility"],
17-
"author": "@technoph1le"
17+
"author": "dostonnabotov"
1818
}
1919
]
2020
},
@@ -26,14 +26,14 @@
2626
"description": "Flattens a multi-dimensional list into a single list.",
2727
"code": "def flatten_list(lst):\n return [item for sublist in lst for item in sublist]\n\n# Usage:\nnested_list = [[1, 2], [3, 4], [5]]\nprint(flatten_list(nested_list)) # Output: [1, 2, 3, 4, 5]",
2828
"tags": ["python", "list", "flatten", "utility"],
29-
"author": "@technoph1le"
29+
"author": "dostonnabotov"
3030
},
3131
{
3232
"title": "Remove Duplicates",
3333
"description": "Removes duplicate elements from a list while maintaining order.",
3434
"code": "def remove_duplicates(lst):\n return list(dict.fromkeys(lst))\n\n# Usage:\nprint(remove_duplicates([1, 2, 2, 3, 4, 4, 5])) # Output: [1, 2, 3, 4, 5]",
3535
"tags": ["python", "list", "duplicates", "utility"],
36-
"author": "@technoph1le"
36+
"author": "dostonnabotov"
3737
}
3838
]
3939
},
@@ -45,14 +45,14 @@
4545
"description": "Reads all lines from a file and returns them as a list.",
4646
"code": "def read_file_lines(filepath):\n with open(filepath, 'r') as file:\n return file.readlines()\n\n# Usage:\nlines = read_file_lines('example.txt')\nprint(lines)",
4747
"tags": ["python", "file", "read", "utility"],
48-
"author": "@technoph1le"
48+
"author": "dostonnabotov"
4949
},
5050
{
5151
"title": "Write to File",
5252
"description": "Writes content to a file.",
5353
"code": "def write_to_file(filepath, content):\n with open(filepath, 'w') as file:\n file.write(content)\n\n# Usage:\nwrite_to_file('example.txt', 'Hello, World!')",
5454
"tags": ["python", "file", "write", "utility"],
55-
"author": "@technoph1le"
55+
"author": "dostonnabotov"
5656
}
5757
]
5858
},
@@ -64,14 +64,14 @@
6464
"description": "Calculates the factorial of a number.",
6565
"code": "def factorial(n):\n if n == 0:\n return 1\n return n * factorial(n - 1)\n\n# Usage:\nprint(factorial(5)) # Output: 120",
6666
"tags": ["python", "math", "factorial", "utility"],
67-
"author": "@technoph1le"
67+
"author": "dostonnabotov"
6868
},
6969
{
7070
"title": "Check Prime Number",
7171
"description": "Checks if a number is a prime number.",
7272
"code": "def is_prime(n):\n if n <= 1:\n return False\n for i in range(2, int(n**0.5) + 1):\n if n % i == 0:\n return False\n return True\n\n# Usage:\nprint(is_prime(17)) # Output: True",
7373
"tags": ["python", "math", "prime", "check"],
74-
"author": "@technoph1le"
74+
"author": "dostonnabotov"
7575
}
7676
]
7777
},
@@ -83,14 +83,14 @@
8383
"description": "Measures the execution time of a code block.",
8484
"code": "import time\n\ndef measure_time(func, *args):\n start = time.time()\n result = func(*args)\n end = time.time()\n print(f'Execution time: {end - start:.6f} seconds')\n return result\n\n# Usage:\ndef slow_function():\n time.sleep(2)\n\nmeasure_time(slow_function)",
8585
"tags": ["python", "time", "execution", "utility"],
86-
"author": "@technoph1le"
86+
"author": "dostonnabotov"
8787
},
8888
{
8989
"title": "Generate Random String",
9090
"description": "Generates a random alphanumeric string.",
9191
"code": "import random\nimport string\n\ndef random_string(length):\n letters_and_digits = string.ascii_letters + string.digits\n return ''.join(random.choice(letters_and_digits) for _ in range(length))\n\n# Usage:\nprint(random_string(10)) # Output: Random 10-character string",
9292
"tags": ["python", "random", "string", "utility"],
93-
"author": "@technoph1le"
93+
"author": "dostonnabotov"
9494
}
9595
]
9696
}

‎public/data/scss.json‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,28 @@
77
"description": "A Sass mixin to clamp text to a specific number of lines.",
88
"code": "@mixin line-clamp($number) {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: $number;\n overflow: hidden;\n}",
99
"tags": ["sass", "mixin", "typography", "css"],
10-
"author": "@technoph1le"
10+
"author": "dostonnabotov"
1111
},
1212
{
1313
"title": "Text Overflow Ellipsis",
1414
"description": "Ensures long text is truncated with an ellipsis.",
1515
"code": "@mixin text-ellipsis {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}",
1616
"tags": ["sass", "mixin", "text", "css"],
17-
"author": "@technoph1le"
17+
"author": "dostonnabotov"
1818
},
1919
{
2020
"title": "Font Import Helper",
2121
"description": "Simplifies importing custom fonts in Sass.",
2222
"code": "@mixin import-font($family, $weight: 400, $style: normal) {\n @font-face {\n font-family: #{$family};\n font-weight: #{$weight};\n font-style: #{$style};\n src: url('/fonts/#{$family}-#{$weight}.woff2') format('woff2'),\n url('/fonts/#{$family}-#{$weight}.woff') format('woff');\n }\n}",
2323
"tags": ["sass", "mixin", "fonts", "css"],
24-
"author": "@technoph1le"
24+
"author": "dostonnabotov"
2525
},
2626
{
2727
"title": "Text Gradient",
2828
"description": "Adds a gradient color effect to text.",
2929
"code": "@mixin text-gradient($from, $to) {\n background: linear-gradient(to right, $from, $to);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n}",
3030
"tags": ["sass", "mixin", "gradient", "text", "css"],
31-
"author": "@technoph1le"
31+
"author": "dostonnabotov"
3232
}
3333
]
3434
},
@@ -40,21 +40,21 @@
4040
"description": "Creates a responsive grid container with customizable column counts.",
4141
"code": "@mixin grid-container($columns: 12, $gap: 1rem) {\n display: grid;\n grid-template-columns: repeat($columns, 1fr);\n gap: $gap;\n}",
4242
"tags": ["scss", "grid", "layout", "css"],
43-
"author": "@technoph1le"
43+
"author": "dostonnabotov"
4444
},
4545
{
4646
"title": "Flex Center",
4747
"description": "A mixin to center content using flexbox.",
4848
"code": "@mixin flex-center {\n display: flex;\n justify-content: center;\n align-items: center;\n}",
4949
"tags": ["scss", "flex", "center", "css"],
50-
"author": "@technoph1le"
50+
"author": "dostonnabotov"
5151
},
5252
{
5353
"title": "Aspect Ratio",
5454
"description": "Ensures elements maintain a specific aspect ratio.",
5555
"code": "@mixin aspect-ratio($width, $height) {\n position: relative;\n width: 100%;\n padding-top: ($height / $width) * 100%;\n > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n}",
5656
"tags": ["scss", "aspect-ratio", "layout", "css"],
57-
"author": "@technoph1le"
57+
"author": "dostonnabotov"
5858
}
5959
]
6060
},
@@ -66,14 +66,14 @@
6666
"description": "Animates the fade-in effect.",
6767
"code": "@keyframes fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@mixin fade-in($duration: 1s, $easing: ease-in-out) {\n animation: fade-in $duration $easing;\n}",
6868
"tags": ["scss", "animation", "fade", "css"],
69-
"author": "@technoph1le"
69+
"author": "dostonnabotov"
7070
},
7171
{
7272
"title": "Slide In From Left",
7373
"description": "Animates content sliding in from the left.",
7474
"code": "@keyframes slide-in-left {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(0);\n }\n}\n\n@mixin slide-in-left($duration: 0.5s, $easing: ease-out) {\n animation: slide-in-left $duration $easing;\n}",
7575
"tags": ["scss", "animation", "slide", "css"],
76-
"author": "@technoph1le"
76+
"author": "dostonnabotov"
7777
}
7878
]
7979
},
@@ -85,14 +85,14 @@
8585
"description": "Generates media queries for responsive design.",
8686
"code": "@mixin breakpoint($breakpoint) {\n @if $breakpoint == sm {\n @media (max-width: 576px) { @content; }\n } @else if $breakpoint == md {\n @media (max-width: 768px) { @content; }\n } @else if $breakpoint == lg {\n @media (max-width: 992px) { @content; }\n } @else if $breakpoint == xl {\n @media (max-width: 1200px) { @content; }\n }\n}",
8787
"tags": ["scss", "responsive", "media-queries", "css"],
88-
"author": "@technoph1le"
88+
"author": "dostonnabotov"
8989
},
9090
{
9191
"title": "Clearfix",
9292
"description": "Provides a clearfix utility for floating elements.",
9393
"code": "@mixin clearfix {\n &::after {\n content: '';\n display: block;\n clear: both;\n }\n}",
9494
"tags": ["scss", "clearfix", "utility", "css"],
95-
"author": "@technoph1le"
95+
"author": "dostonnabotov"
9696
}
9797
]
9898
},
@@ -104,14 +104,14 @@
104104
"description": "Applies a customizable border-radius.",
105105
"code": "@mixin border-radius($radius: 4px) {\n border-radius: $radius;\n}",
106106
"tags": ["scss", "border", "radius", "css"],
107-
"author": "@technoph1le"
107+
"author": "dostonnabotov"
108108
},
109109
{
110110
"title": "Box Shadow Helper",
111111
"description": "Generates a box shadow with customizable values.",
112112
"code": "@mixin box-shadow($x: 0px, $y: 4px, $blur: 10px, $spread: 0px, $color: rgba(0, 0, 0, 0.1)) {\n box-shadow: $x $y $blur $spread $color;\n}",
113113
"tags": ["scss", "box-shadow", "css", "effects"],
114-
"author": "@technoph1le"
114+
"author": "dostonnabotov"
115115
}
116116
]
117117
},
@@ -123,7 +123,7 @@
123123
"description": "Generates a styled primary button.",
124124
"code": "@mixin primary-button($bg: #007bff, $color: #fff) {\n background-color: $bg;\n color: $color;\n padding: 0.5rem 1rem;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n\n &:hover {\n background-color: darken($bg, 10%);\n }\n}",
125125
"tags": ["scss", "button", "primary", "css"],
126-
"author": "@technoph1le"
126+
"author": "dostonnabotov"
127127
}
128128
]
129129
}

‎src/components/Button.tsx‎

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,27 @@
1-
import { MouseEventHandler, ReactNode } from "react";
2-
3-
// TODO: separate LinkButton from Button for clarity
1+
import { ButtonHTMLAttributes, MouseEventHandler, ReactNode } from "react";
42

53
type ButtonProps = {
6-
as?: "button" | "link";
7-
href?: string;
8-
className?: string;
94
isIcon?: boolean;
105
onClick?: MouseEventHandler<HTMLButtonElement>;
116
children: ReactNode;
12-
};
7+
className?: string;
8+
} & ButtonHTMLAttributes<HTMLButtonElement>;
139

1410
const Button = ({
15-
as = "button",
16-
href,
17-
className,
18-
children,
19-
isIcon,
11+
isIcon = false,
12+
className = "",
2013
onClick,
14+
children,
2115
...props
2216
}: ButtonProps) => {
23-
return as === "button" ? (
17+
return (
2418
<button
25-
className={`button ${isIcon ? "button--icon" : ""} ${className || ""}`}
19+
className={`button ${isIcon ? "button--icon" : ""} ${className}`}
2620
onClick={onClick}
2721
{...props}
2822
>
2923
{children}
3024
</button>
31-
) : (
32-
<a className={`button ${className || ""}`} href={href} {...props}>
33-
{children}
34-
</a>
3525
);
3626
};
3727

‎src/components/CodePreview.tsx‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
22
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
3+
import CopyToClipboard from "./CopyToClipboard";
34

45
type Props = {
56
language: string;
@@ -8,14 +9,17 @@ type Props = {
89

910
const CodePreview = ({ language = "markdown", children }: Props) => {
1011
return (
11-
<SyntaxHighlighter
12-
language={language}
13-
style={oneDark}
14-
wrapLines={true}
15-
customStyle={{ margin: "0" }}
16-
>
17-
{children}
18-
</SyntaxHighlighter>
12+
<div className="code-preview">
13+
<CopyToClipboard text={children} className="modal__copy" />
14+
<SyntaxHighlighter
15+
language={language}
16+
style={oneDark}
17+
wrapLines={true}
18+
customStyle={{ margin: "0" }}
19+
>
20+
{children}
21+
</SyntaxHighlighter>
22+
</div>
1923
);
2024
};
2125

‎src/components/Icons.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,11 @@ export const LeftAngleArrowIcon = ({ fillColor = ACCENT_ICON_COLOR }) => (
168168
fill="none"
169169
xmlns="http://www.w3.org/2000/svg"
170170
>
171-
<g clip-path="url(#clip0_97_152)">
171+
<g clipPath="url(#clip0_97_152)">
172172
<path
173173
d="M24.2401 71.28C24.2401 69.0985 22.085 65.841 19.9036 63.1068C17.0988 59.5788 13.7472 56.5006 9.90463 54.1516C7.02343 52.3905 3.53071 50.7 0.720069 50.7M0.720069 50.7C3.53071 50.7 7.02637 49.0095 9.90463 47.2484C13.7472 44.8964 17.0988 41.8183 19.9036 38.2961C22.085 35.559 24.2401 32.2956 24.2401 30.12M0.720069 50.7L34.5301 50.7C54.0134 50.7 69.8101 34.9034 69.8101 15.42L69.8101 0.719996"
174174
stroke={fillColor}
175-
stroke-width="5.88"
175+
strokeWidth="5.88"
176176
/>
177177
</g>
178178
<defs>

‎src/components/LinkButton.tsx‎

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

‎src/components/SnippetList.tsx‎

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ import { SnippetType } from "../types";
33
import { useAppContext } from "../contexts/AppContext";
44
import { useSnippets } from "../hooks/useSnippets";
55

6-
import Button from "./Button";
76
import SnippetModal from "./SnippetModal";
8-
import { ExpandIcon, LeftAngleArrowIcon } from "./Icons";
7+
import { LeftAngleArrowIcon } from "./Icons";
98

109
const SnippetList = () => {
11-
const { language, setSnippet } = useAppContext();
10+
const { language, snippet, setSnippet } = useAppContext();
1211
const { fetchedSnippets } = useSnippets();
1312
const [isModalOpen, setIsModalOpen] = useState(false);
1413

@@ -30,29 +29,33 @@ const SnippetList = () => {
3029
};
3130

3231
return (
33-
<ul role="list" className="snippets">
34-
{fetchedSnippets.map((snippet, idx) => (
35-
<li key={idx} className="snippet">
36-
<div className="snippet__preview">
37-
<img src={language.icon} alt={language.lang} />
38-
</div>
39-
40-
<div className="snippet__content">
41-
<h3 className="snippet__title">{snippet.title}</h3>
42-
<Button isIcon={true} onClick={() => handleOpenModal(snippet)}>
43-
<ExpandIcon />
44-
</Button>
45-
</div>
46-
{isModalOpen && (
47-
<SnippetModal
48-
snippet={snippet}
49-
handleCloseModal={handleCloseModal}
50-
language={language.lang}
51-
/>
52-
)}
53-
</li>
54-
))}
55-
</ul>
32+
<>
33+
<ul role="list" className="snippets">
34+
{fetchedSnippets.map((snippet, idx) => (
35+
<li key={idx}>
36+
<button
37+
className="snippet | flow"
38+
data-flow-space="sm"
39+
onClick={() => handleOpenModal(snippet)}
40+
>
41+
<div className="snippet__preview">
42+
<img src={language.icon} alt={language.lang} />
43+
</div>
44+
45+
<h3 className="snippet__title">{snippet.title}</h3>
46+
</button>
47+
</li>
48+
))}
49+
</ul>
50+
51+
{isModalOpen && snippet && (
52+
<SnippetModal
53+
snippet={snippet}
54+
handleCloseModal={handleCloseModal}
55+
language={language.lang}
56+
/>
57+
)}
58+
</>
5659
);
5760
};
5861

‎src/components/SnippetModal.tsx‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from "react";
22
import ReactDOM from "react-dom";
33
import Button from "./Button";
44
import { CloseIcon } from "./Icons";
5-
import CopyToClipboard from "./CopyToClipboard";
65
import CodePreview from "./CodePreview";
76
import { SnippetType } from "../types";
87
import slugify from "../utils/slugify";
@@ -30,16 +29,21 @@ const SnippetModal: React.FC<Props> = ({
3029
<CloseIcon />
3130
</Button>
3231
</div>
33-
<div className="code-preview">
34-
<CopyToClipboard text={snippet.code} className="modal__copy" />
35-
<CodePreview language={slugify(language)}>{snippet.code}</CodePreview>
36-
</div>
32+
<CodePreview language={slugify(language)}>{snippet.code}</CodePreview>
3733
<p>
3834
<b>Description: </b>
3935
{snippet.description}
4036
</p>
4137
<p>
42-
Contributed by <b>{snippet.author}</b>
38+
Contributed by{" "}
39+
<a
40+
href={`https://github.com/${snippet.author}`}
41+
target="_blank"
42+
rel="noopener noreferrer"
43+
className="styled-link"
44+
>
45+
@{snippet.author}
46+
</a>
4347
</p>
4448
<ul role="list" className="modal__tags">
4549
{snippet.tags.map((tag) => (

‎src/layouts/Footer.tsx‎

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,72 @@ const Footer = () => {
1414
different programming languages.
1515
</p>
1616
<p>
17-
Built by <a href="#">Technophile</a>, and powered by awesome{" "}
18-
<a href="#">community</a>.
17+
Built by{" "}
18+
<a
19+
href="https://github.com/dostonnabotov"
20+
target="_blank"
21+
rel="noopener noreferrer"
22+
className="styled-link"
23+
>
24+
Technophile
25+
</a>
26+
, and powered by awesome{" "}
27+
<a
28+
href="https://github.com/dostonnabotov/quicksnip"
29+
target="_blank"
30+
rel="noopener noreferrer"
31+
className="styled-link"
32+
>
33+
community
34+
</a>
35+
.
1936
</p>
2037
</div>
21-
<nav>
38+
<nav className="footer__nav">
2239
<ul className="flow" data-flow-space="sm">
2340
<li>
24-
<a href="#">Add your own snippet</a>
41+
<a
42+
href="https://github.com/dostonnabotov/quicksnip"
43+
target="_blank"
44+
rel="noopener noreferrer"
45+
className="styled-link"
46+
>
47+
Add your own snippet
48+
</a>
2549
</li>
2650
<li>
27-
<a href="#">Edit this page on GitHub</a>
51+
<a
52+
href="https://github.com/dostonnabotov/quicksnip"
53+
target="_blank"
54+
rel="noopener noreferrer"
55+
className="styled-link"
56+
>
57+
Edit this page on GitHub
58+
</a>
2859
</li>
2960
</ul>
3061
</nav>
31-
<nav>
62+
<nav className="footer__nav">
3263
<ul className="flow" data-flow-space="sm">
3364
<li>
34-
<a href="#">See the community</a>
65+
<a
66+
href="https://github.com/dostonnabotov/quicksnip"
67+
target="_blank"
68+
rel="noopener noreferrer"
69+
className="styled-link"
70+
>
71+
See the community
72+
</a>
3573
</li>
3674
<li>
37-
<a href="#">Support this project</a>
75+
<a
76+
href="https://github.com/dostonnabotov/quicksnip"
77+
target="_blank"
78+
rel="noopener noreferrer"
79+
className="styled-link"
80+
>
81+
Support this project
82+
</a>
3883
</li>
3984
</ul>
4085
</nav>

‎src/layouts/Header.tsx‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Button from "../components/Button";
21
import { GitHubIcon } from "../components/Icons";
2+
import LinkButton from "../components/LinkButton";
33
import Logo from "../components/Logo";
44
import SearchInput from "../components/SearchInput";
55

@@ -9,10 +9,14 @@ const Header = () => {
99
<Logo />
1010
<nav className="primary-nav">
1111
<SearchInput />
12-
<Button as="link" href="https://github.com/dostonnabotov/quicksnip/">
12+
<LinkButton
13+
href="https://github.com/dostonnabotov/quicksnip/"
14+
target="_blank"
15+
rel="noopener noreferrer"
16+
>
1317
<GitHubIcon />
1418
<span>Add your snippet</span>
15-
</Button>
19+
</LinkButton>
1620
</nav>
1721
</header>
1822
);

‎src/styles/main.css‎

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
--bg-secondary: var(--clr-neutral-700);
3838
--text-primary: var(--clr-neutral-200);
3939
--text-secondary: var(--clr-neutral-300);
40+
--text-dark: var(--clr-neutral-900);
4041
--border-color: var(--clr-neutral-500);
4142

4243
--ff-primary: "Source Sans 3", sans-serif;
@@ -330,16 +331,18 @@ ol:where([role="list"]) {
330331
width: 100%;
331332
font-size: var(--fs-500);
332333

333-
&:is(:hover, :focus) {
334-
color: var(--text-primary);
334+
&:is(:hover, :focus-visible):not(.category__btn--active) {
335+
/* color: var(--text-primary); */
336+
background-image: var(--gradient-secondary);
337+
border-radius: var(--br-md);
335338
}
336339
}
337340

338341
.category__btn--active {
339-
background-image: var(--gradient-secondary);
342+
background-color: var(--clr-accent);
340343
border: 1px solid var(--border-color);
341344
font-weight: var(--fw-bold);
342-
color: var(--text-primary);
345+
color: var(--text-dark);
343346
border-radius: var(--br-md);
344347
}
345348

@@ -354,34 +357,32 @@ ol:where([role="list"]) {
354357
}
355358

356359
.snippet {
357-
display: grid;
358-
gap: 0.5em;
359360
width: 100%;
360361
background-color: var(--bg-secondary);
361362
border: 1px solid var(--border-color);
362363
border-radius: var(--br-lg);
363364
padding: 0.75em;
365+
filter: grayscale(100%);
366+
text-align: start;
367+
368+
&:is(:hover, :focus-visible) {
369+
outline: 3px solid var(--clr-neutral-500);
370+
filter: grayscale(0);
371+
}
364372
}
365373

366374
.snippet__preview {
367375
width: 100%;
368376
overflow: hidden;
369377
aspect-ratio: 10 / 3;
370-
background-image: var(--gradient-secondary);
378+
background-color: var(--bg-secondary);
379+
/* background-image: var(--gradient-secondary); */
371380
border: 1px solid var(--border-color);
372381
border-radius: var(--br-md);
373382
position: relative;
374383
padding-inline: 1em;
375384
display: grid;
376385
place-items: center;
377-
filter: grayscale(100%);
378-
}
379-
380-
.snippet__content {
381-
display: flex;
382-
justify-content: space-between;
383-
align-items: center;
384-
gap: 1em;
385386
}
386387

387388
.snippet__title {
@@ -391,6 +392,10 @@ ol:where([role="list"]) {
391392
/*------------------------------------*\
392393
#MODAL
393394
\*------------------------------------*/
395+
body:has(.modal-overlay) {
396+
overflow: hidden;
397+
}
398+
394399
.modal-overlay {
395400
position: fixed;
396401
top: 0;
@@ -402,6 +407,7 @@ ol:where([role="list"]) {
402407
justify-content: center;
403408
align-items: center;
404409
z-index: 1000;
410+
overflow: hidden;
405411
}
406412

407413
.modal {
@@ -427,7 +433,7 @@ ol:where([role="list"]) {
427433
border-radius: var(--br-md);
428434
width: 100%;
429435
overflow-x: auto;
430-
height: 100%;
436+
max-height: 20rem;
431437
position: relative;
432438
}
433439

@@ -441,7 +447,8 @@ ol:where([role="list"]) {
441447

442448
.modal__tags {
443449
display: flex;
444-
gap: 1em;
450+
gap: 0.5em;
451+
flex-wrap: wrap;
445452
}
446453

447454
.modal__tag {
@@ -457,20 +464,52 @@ ol:where([role="list"]) {
457464
#FOOTER
458465
\*------------------------------------*/
459466
.footer {
460-
display: flex;
461-
gap: 2rem;
462-
justify-content: space-between;
467+
display: grid;
468+
gap: clamp(1rem, 2vw, 2rem);
469+
grid-template-columns: 1fr;
470+
grid-template-areas:
471+
"content"
472+
"nav1"
473+
"nav2";
463474
padding-bottom: 3rem;
464475
}
465476

466-
.footer a {
467-
color: var(--text-secondary);
477+
@media (width > 40rem) {
478+
.footer {
479+
grid-template-columns: 3fr 2fr;
480+
grid-template-areas:
481+
"content nav1"
482+
"content nav2";
483+
}
484+
}
468485

469-
&:is(:hover, :focus) {
470-
color: var(--text-primary);
486+
@media (width > 70rem) {
487+
.footer {
488+
grid-template-columns: 2fr 1fr 1fr;
489+
grid-template-areas: "content nav1 nav2";
471490
}
472491
}
473492

493+
.styled-link {
494+
color: var(--text-primary);
495+
text-decoration: none;
496+
font-weight: 600;
497+
498+
&:is(:hover, :focus-visible) {
499+
color: var(--clr-accent);
500+
}
501+
}
502+
503+
.footer__nav:first-child {
504+
grid-area: nav1;
505+
width: 100%;
506+
}
507+
508+
.footer__nav:last-child {
509+
grid-area: nav2;
510+
}
511+
474512
.footer__content {
475-
width: 60ch;
513+
grid-area: content;
514+
max-width: 60ch;
476515
}

0 commit comments

Comments
 (0)
Please sign in to comment.