Skip to content

Commit

Permalink
Add settings drawer
Browse files Browse the repository at this point in the history
  • Loading branch information
matt765 committed Sep 13, 2024
1 parent 6371acf commit 5799b88
Show file tree
Hide file tree
Showing 43 changed files with 1,143 additions and 223 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,12 @@
- reorganize color palette
- allow selecting text without closing the question
- add arrow navigation for mobile resolution

## 1.0.6 (13-09-2024)

- add 5 new themes
- adjust scrollbar styles
- add SCSS mixins for all themes
- add ripple animation for timer button
- optimize question store data handling
- add settings drawer
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "front-end-questions",
"version": "1.0.5",
"version": "1.0.6",
"private": true,
"license": "CC-BY-NC-ND-4.0",
"description": "Free educational application that contains base of front-end related interview questions.",
Expand Down
11 changes: 11 additions & 0 deletions src/assets/icons/ArrowDownLine.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const ArrowDownLine = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
width="24"
height="24"
>
<path d="M13.0001 16.1716L18.3641 10.8076L19.7783 12.2218L12.0001 20L4.22192 12.2218L5.63614 10.8076L11.0001 16.1716V4H13.0001V16.1716Z"></path>
</svg>
);
11 changes: 11 additions & 0 deletions src/assets/icons/PaletteIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const PaletteIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
width="24"
height="24"
>
<path d="M12 2C17.5222 2 22 5.97778 22 10.8889C22 13.9556 19.5111 16.4444 16.4444 16.4444H14.4778C13.5556 16.4444 12.8111 17.1889 12.8111 18.1111C12.8111 18.5333 12.9778 18.9222 13.2333 19.2111C13.5 19.5111 13.6667 19.9 13.6667 20.3333C13.6667 21.2556 12.9 22 12 22C6.47778 22 2 17.5222 2 12C2 6.47778 6.47778 2 12 2ZM10.8111 18.1111C10.8111 16.0843 12.451 14.4444 14.4778 14.4444H16.4444C18.4065 14.4444 20 12.851 20 10.8889C20 7.1392 16.4677 4 12 4C7.58235 4 4 7.58235 4 12C4 16.19 7.2226 19.6285 11.324 19.9718C10.9948 19.4168 10.8111 18.7761 10.8111 18.1111ZM7.5 12C6.67157 12 6 11.3284 6 10.5C6 9.67157 6.67157 9 7.5 9C8.32843 9 9 9.67157 9 10.5C9 11.3284 8.32843 12 7.5 12ZM16.5 12C15.6716 12 15 11.3284 15 10.5C15 9.67157 15.6716 9 16.5 9C17.3284 9 18 9.67157 18 10.5C18 11.3284 17.3284 12 16.5 12ZM12 9C11.1716 9 10.5 8.32843 10.5 7.5C10.5 6.67157 11.1716 6 12 6C12.8284 6 13.5 6.67157 13.5 7.5C13.5 8.32843 12.8284 9 12 9Z"></path>
</svg>
);
11 changes: 11 additions & 0 deletions src/assets/icons/SettingsIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const SettingsIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
width="24"
height="24"
>
<path d="M8.68637 4.00008L11.293 1.39348C11.6835 1.00295 12.3167 1.00295 12.7072 1.39348L15.3138 4.00008H19.0001C19.5524 4.00008 20.0001 4.4478 20.0001 5.00008V8.68637L22.6067 11.293C22.9972 11.6835 22.9972 12.3167 22.6067 12.7072L20.0001 15.3138V19.0001C20.0001 19.5524 19.5524 20.0001 19.0001 20.0001H15.3138L12.7072 22.6067C12.3167 22.9972 11.6835 22.9972 11.293 22.6067L8.68637 20.0001H5.00008C4.4478 20.0001 4.00008 19.5524 4.00008 19.0001V15.3138L1.39348 12.7072C1.00295 12.3167 1.00295 11.6835 1.39348 11.293L4.00008 8.68637V5.00008C4.00008 4.4478 4.4478 4.00008 5.00008 4.00008H8.68637ZM6.00008 6.00008V9.5148L3.5148 12.0001L6.00008 14.4854V18.0001H9.5148L12.0001 20.4854L14.4854 18.0001H18.0001V14.4854L20.4854 12.0001L18.0001 9.5148V6.00008H14.4854L12.0001 3.5148L9.5148 6.00008H6.00008ZM12.0001 16.0001C9.79094 16.0001 8.00008 14.2092 8.00008 12.0001C8.00008 9.79094 9.79094 8.00008 12.0001 8.00008C14.2092 8.00008 16.0001 9.79094 16.0001 12.0001C16.0001 14.2092 14.2092 16.0001 12.0001 16.0001ZM12.0001 14.0001C13.1047 14.0001 14.0001 13.1047 14.0001 12.0001C14.0001 10.8955 13.1047 10.0001 12.0001 10.0001C10.8955 10.0001 10.0001 10.8955 10.0001 12.0001C10.0001 13.1047 10.8955 14.0001 12.0001 14.0001Z"></path>
</svg>
);
42 changes: 33 additions & 9 deletions src/components/common/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,50 @@
import React from "react";
import classNames from "classnames";

import styles from "./styles/Checkbox.module.scss";
import { useHydrated } from "@/hooks/useHydrated";

interface CheckboxProps {
id: string;
checked: boolean;
onChange: (checked: boolean) => void;
label?: string;
transparent?: boolean;
}

export const Checkbox = ({ id, checked, onChange, label }: CheckboxProps) => {
export const Checkbox = ({
id,
checked,
onChange,
label,
transparent = false,
}: CheckboxProps) => {
const isHydrated = useHydrated();

return (
<div className={styles.checkboxContainer}>
<input
type="checkbox"
id={id}
checked={checked}
onChange={(e) => onChange(e.target.checked)}
className={styles.checkbox}
/>
<div
className={classNames(styles.checkboxWrapper, {
[styles.transparent]: transparent,
})}
onClick={() => onChange(!checked)}
>
{isHydrated && checked && (
<div
className={classNames(styles.checkboxIcon, {
[styles.transparentIcon]: transparent,
})}
>
</div>
)}
</div>
{label && (
<label htmlFor={id} className={styles.checkboxLabel}>
<label
htmlFor={id}
className={styles.checkboxLabel}
onClick={() => onChange(!checked)}
>
{label}
</label>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const Dropdown = ({
closeOnClick = true,
}: DropdownProps) => {
return (
<div ref={dropdownRef} className={styles.dropdownWrapper}>
<div ref={dropdownRef} className={`${styles.dropdownWrapper} midnightBlur`}>
{items.map((item, idx) => (
<div
key={idx}
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const Modal = ({ isOpen, onClose, children }: ModalProps) => {

return (
<div className={styles.modalOverlay} onClick={onClose}>
<div className={styles.modalContent} onClick={(e) => e.stopPropagation()}>
<div className={`${styles.modalContent} midnightBlur`} onClick={(e) => e.stopPropagation()}>
<button className={styles.closeButton} onClick={onClose}>
&times;
</button>
Expand Down
21 changes: 17 additions & 4 deletions src/components/common/OutlinedButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,32 @@ import React from "react";

import { firaSans } from "@/styles/fonts";
import styles from "./styles/OutlinedButton.module.scss";
import classNames from "classnames";

interface OutlinedButtonProps {
onClick: (event: React.MouseEvent<HTMLElement>) => void;
text: string;
coloredBorder?: boolean;
smallPadding?: boolean;
}

export const OutlinedButton = ({ onClick, text }: OutlinedButtonProps) => {
export const OutlinedButton = ({
onClick,
text,
coloredBorder = false,
smallPadding = false
}: OutlinedButtonProps) => {
return (
<div
<button
onClick={onClick}
className={`${styles.outlinedButton} ${firaSans.className}`}
className={classNames(
styles.outlinedButton,
firaSans.className,
{ [styles.coloredBorder]: coloredBorder },
{ [styles.smallPadding]: smallPadding }
)}
>
{text}
</div>
</button>
);
};
78 changes: 78 additions & 0 deletions src/components/common/Select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// components/common/Select.tsx
import React, { useEffect, useState } from "react";
import { useSelect } from "../../hooks/useSelect";
import styles from "./styles/Select.module.scss";
import { ArrowDown } from "@/assets/icons/ArrowDownIcon";
import { ArrowUp } from "@/assets/icons/ArrowUpIcon";

interface SelectProps {
options: string[];
value: string;
onChange: (value: string) => void;
}

export const Select = ({ options, value, onChange }: SelectProps) => {
const { isSelectOpen, toggleSelect, closeSelect, selectRef, toggleRef } =
useSelect();
const [initialRenderComplete, setInitialRenderComplete] = useState(false);

useEffect(() => {
// Setting the initial render complete after mounting to avoid SSR/client-side mismatch that causes hydration errors
setInitialRenderComplete(true);
}, []);

useEffect(() => {
if (options.length && !options.includes(value)) {
onChange(options[0]);
}
}, [options, value, onChange]);

if (!initialRenderComplete) {
return null;
}

return (
<div className={styles.selectWrapper}>
<div
className={styles.selectDisplay}
onClick={toggleSelect}
ref={toggleRef}
tabIndex={0}
role="combobox"
aria-haspopup="listbox"
aria-expanded={isSelectOpen}
aria-label="Select option"
>
{value && value.charAt(0).toUpperCase() + value.slice(1)}
<div className={styles.selectDisplayArrow}>
{isSelectOpen ? (
<ArrowUp width="24px" height="24px" />
) : (
<ArrowDown width="24px" height="24px" />
)}
</div>
</div>
{isSelectOpen && (
<div
ref={selectRef}
className={`${styles.selectDropdownWrapper} midnightBlur`}
role="listbox"
>
{options.map((option, index) => (
<div
key={index}
className={styles.selectDropdownRow}
role="option"
onClick={() => {
onChange(option);
closeSelect();
}}
>
{option.charAt(0).toUpperCase() + option.slice(1)}
</div>
))}
</div>
)}
</div>
);
};
48 changes: 42 additions & 6 deletions src/components/common/styles/Checkbox.module.scss
Original file line number Diff line number Diff line change
@@ -1,15 +1,51 @@
.checkboxContainer {
display: flex;
align-items: center;
position: relative;
width: 100%;
height: 100%;
cursor: pointer;
}

.checkboxLabel {
padding-left: 0.7rem;
cursor: pointer;
.checkboxWrapper {
width: 1.1rem;
height: 1.1rem;
border-color: var(--border-checkbox);
border-style: solid;
border-width: 1px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: var(--bg-checkbox);
transition: 0.1s;

&:hover {
border-color: var(--border-checkbox-hover);
}

&.transparent {
background-color: rgba(255, 255, 255, 0);
width: 1.4rem;
height: 1.4rem;
}
}

.checkbox {
width: 1rem;
height: 1rem;
.checkboxIcon {
color: var(--text-primary);
font-size: 0.75rem;
position: absolute;

&.transparentIcon {
display: flex;
color: var(--text-primary);
font-size: 1rem;
left: 0.25rem;
bottom: 0rem;
}
}

.checkboxLabel {
padding-left: 0.7rem;
cursor: pointer;
}
2 changes: 1 addition & 1 deletion src/components/common/styles/Dropdown.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
display: flex;
align-items: center;
justify-content: center;
color: var(--text-secondary);
color: var(--icon-dropdown);
width: 1.2rem;
height: 1.2rem;
}
2 changes: 1 addition & 1 deletion src/components/common/styles/Loader.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
height: 4rem;
margin-right: 4rem;
margin-bottom: 6rem;
color: var(--text-secondary);
color: var(--icon-loader);
}
2 changes: 1 addition & 1 deletion src/components/common/styles/Modal.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
font-size: 1.5rem;
cursor: pointer;
transition: 0.1s;
color: var(--content-text-primary);
color: white;
&:hover {
transform: scale(1.1);
}
Expand Down
16 changes: 15 additions & 1 deletion src/components/common/styles/OutlinedButton.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
border-color: var(--border-main);
background: rgba(255, 255, 255, 0.01);
border-radius: 10px;
padding: 1rem 2rem;
padding-top: 1rem;
padding-bottom: 1rem;
padding-left: 2rem;
padding-right: 2rem;
width: 100%;
height: 100%;
color: var(--text-primary);
font-size: 0.9rem;
cursor: pointer;
transition: 0.2s;
Expand All @@ -15,3 +19,13 @@
background: var(--bg-outlined-button-hover);
}
}

.coloredBorder {
border-color: var(--main-color);
}

.smallPadding {
padding-left: 0.2rem;
padding-right: 0.2rem;
font-size: 0.85rem;
}
Loading

0 comments on commit 5799b88

Please sign in to comment.