diff options
-rw-r--r-- | client/src/components/CustomSelect/CustomSelect.jsx | 42 | ||||
-rw-r--r-- | client/src/components/CustomSelect/CustomSelect.module.css | 32 | ||||
-rw-r--r-- | client/src/components/Editor/Editor.jsx | 88 | ||||
-rw-r--r-- | client/src/components/Editor/Editor.module.css | 30 | ||||
-rw-r--r-- | client/src/components/Header/Header.jsx | 22 | ||||
-rw-r--r-- | client/src/components/Header/Header.module.css | 29 | ||||
-rw-r--r-- | client/src/pages/Home/Home.jsx | 1 | ||||
-rw-r--r-- | client/src/utils/constants.js | 91 |
8 files changed, 227 insertions, 108 deletions
diff --git a/client/src/components/CustomSelect/CustomSelect.jsx b/client/src/components/CustomSelect/CustomSelect.jsx new file mode 100644 index 0000000..9969a6d --- /dev/null +++ b/client/src/components/CustomSelect/CustomSelect.jsx @@ -0,0 +1,42 @@ +import React, { useState } from "react"; +import styles from "./CustomSelect.module.css"; + +const CustomSelect = ({ options, onSelect }) => { + const [isOpen, setIsOpen] = useState(false); + const [selectedOption, setSelectedOption] = useState( + options.length > 0 ? options[0] : null + ); + + const toggleDropdown = () => { + setIsOpen(!isOpen); + }; + + const handleOptionClick = (option) => { + setSelectedOption(option); + onSelect(option.value); + setIsOpen(false); + }; + + return ( + <div className={styles.select}> + <div className={styles.selected__option} onClick={toggleDropdown}> + {selectedOption ? selectedOption.label : "Select an option"} + </div> + {isOpen && ( + <div className={styles.options}> + {options.map((option) => ( + <div + key={option.value} + className={styles.option} + onClick={() => handleOptionClick(option)} + > + {option.label} + </div> + ))} + </div> + )} + </div> + ); +}; + +export default CustomSelect; diff --git a/client/src/components/CustomSelect/CustomSelect.module.css b/client/src/components/CustomSelect/CustomSelect.module.css new file mode 100644 index 0000000..a3b6520 --- /dev/null +++ b/client/src/components/CustomSelect/CustomSelect.module.css @@ -0,0 +1,32 @@ +.select { + position: relative; + display: inline-block; +} + +.selected__option { + cursor: pointer; + padding: 10px; + border: 1px solid #ccc; + border-radius: 4px; +} + +.options { + position: absolute; + top: 100%; + left: 0; + width: 100%; + border: 1px solid #ccc; + border-top: none; + border-radius: 0 0 4px 4px; + background-color: #ebdbb2; + z-index: 1; +} + +.option { + padding: 10px; + color: #282828; + cursor: pointer; + &:hover { + background-color: #f0f0f0; + } +} diff --git a/client/src/components/Editor/Editor.jsx b/client/src/components/Editor/Editor.jsx index 143abd3..29294a0 100644 --- a/client/src/components/Editor/Editor.jsx +++ b/client/src/components/Editor/Editor.jsx @@ -3,7 +3,8 @@ import { useNavigate, useParams } from "react-router-dom"; import Prism from "prismjs"; import styles from "./Editor.module.css"; import "../prism-themes/prism-gruvbox-dark.css"; -import { SERVER_BASE_URL, SUPPORTED_LANGUAGES } from "../../utils/constants"; +import { SERVER_BASE_URL } from "../../utils/constants"; +import Header from "../Header/Header"; const Editor = () => { const { id } = useParams(); @@ -42,8 +43,8 @@ const Editor = () => { } }; - const handleLanguageChange = (event) => { - setLanguage(event.target.value); + const handleLanguageChange = (value) => { + setLanguage(value); }; useEffect(() => { @@ -71,59 +72,48 @@ const Editor = () => { const lines = useMemo(() => text.split("\n"), [text]); return ( - <div className={styles.container}> - {!id && ( - <> - <select - className={styles.languages} - onChange={handleLanguageChange} - > - {Object.keys(SUPPORTED_LANGUAGES).map((language) => ( - <option - className={styles.languages__option} - key={language} - value={language} - > - {SUPPORTED_LANGUAGES[language]} - </option> - ))} - </select> + <> + <Header isSelectVisible={!id} onLanguageChange={handleLanguageChange} /> + <div className={styles.container}> + {!id && ( <button className={styles.btn__save} onClick={handleClick}> <img src="assets/icons/save.svg" className={styles.btn__icon} /> </button> - </> - )} + )} - <div className={styles.editor}> - <div - className={styles.line__numbers} - ref={lineNumberRef} - onScroll={handleScroll} - > - {lines.map((_, index) => ( - <div key={index + 1} className={styles.line__number}> - {index + 1} - </div> - ))} - </div> - <div className={styles.codespace}> - <textarea - className={styles.codespace__textarea} - onChange={handleTextChange} + <div className={styles.editor}> + <div + className={styles.line__numbers} + ref={lineNumberRef} onScroll={handleScroll} - style={{ display: id ? 'none' : 'block' }} - spellCheck="false" - ref={textareaRef} - placeholder="Type your text here..." - /> - <pre className={styles.codespace__pre}> - <code className={`${styles.codespace__code} language-${language}`}> - {text} - </code> - </pre> + > + {lines.map((_, index) => ( + <div key={index + 1} className={styles.line__number}> + {index + 1} + </div> + ))} + </div> + <div className={styles.codespace}> + <textarea + className={styles.codespace__textarea} + onChange={handleTextChange} + onScroll={handleScroll} + style={{ display: id ? "none" : "block" }} + spellCheck="false" + ref={textareaRef} + placeholder="Type your text here..." + /> + <pre className={styles.codespace__pre}> + <code + className={`${styles.codespace__code} language-${language}`} + > + {text} + </code> + </pre> + </div> </div> </div> - </div> + </> ); }; diff --git a/client/src/components/Editor/Editor.module.css b/client/src/components/Editor/Editor.module.css index 579f3bc..2e42978 100644 --- a/client/src/components/Editor/Editor.module.css +++ b/client/src/components/Editor/Editor.module.css @@ -5,28 +5,6 @@ flex: 1; } -.languages { - background-color: transparent; - border: none; - padding: 10px 0; - margin-left: 36px; - font-family: inherit; - font-size: inherit; - cursor: inherit; - line-height: inherit; - width: 7rem; - outline: none; - color: white; -} - -.languages__option { - width: 10rem; - border: none; - cursor: pointer; - transition: 0.3s; - background: #3c3836; -} - .editor { display: flex; flex-direction: row; @@ -90,8 +68,8 @@ position: fixed; bottom: 3rem; right: 3rem; - height: 8rem; - width: 8rem; + height: 6rem; + width: 6rem; background-color: #ebdbb2; color: white; border: none; @@ -102,6 +80,6 @@ } .btn__icon { - height: 4rem; - width: 4rem; + height: 3rem; + width: 3rem; } diff --git a/client/src/components/Header/Header.jsx b/client/src/components/Header/Header.jsx index a69803a..fb8d694 100644 --- a/client/src/components/Header/Header.jsx +++ b/client/src/components/Header/Header.jsx @@ -1,12 +1,20 @@ -import React from 'react' -import styles from './Header.module.css' +import React from "react"; +import { SUPPORTED_LANGUAGES } from "../../utils/constants"; +import styles from "./Header.module.css"; +import CustomSelect from "../CustomSelect/CustomSelect"; -const Header = () => { +const Header = ({ isSelectVisible, onLanguageChange }) => { return ( <div className={styles.header}> - <h1><minibin /></h1> + <h1>minibin</h1> + {isSelectVisible && ( + <CustomSelect + options={SUPPORTED_LANGUAGES} + onSelect={onLanguageChange} + /> + )} </div> - ) -} + ); +}; -export default Header
\ No newline at end of file +export default Header; diff --git a/client/src/components/Header/Header.module.css b/client/src/components/Header/Header.module.css index c39f528..f0276e4 100644 --- a/client/src/components/Header/Header.module.css +++ b/client/src/components/Header/Header.module.css @@ -1,9 +1,36 @@ .header { display: flex; - justify-content: center; + justify-content: space-between; + align-items: center; margin: 2rem; } .header h1 { margin: 0; } + +.languages { + background-color: #ebdbb2; + border: none; + border-radius: 10px; + padding: 0.5rem 1rem; + font-family: inherit; + font-size: inherit; + cursor: inherit; + line-height: inherit; + width: 8rem; + outline: none; + color: #282828; + appearance: none; + background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23131313%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E"); + background-repeat: no-repeat; + background-position: right 0.7rem top 50%; + background-size: 0.65rem auto; +} + +.languages__option { + cursor: pointer; + background: #ebdbb2; + color: #282828; +} + diff --git a/client/src/pages/Home/Home.jsx b/client/src/pages/Home/Home.jsx index 32bb815..21cbdb0 100644 --- a/client/src/pages/Home/Home.jsx +++ b/client/src/pages/Home/Home.jsx @@ -6,7 +6,6 @@ import Editor from "../../components/Editor/Editor"; const Home = () => { return ( <div className={styles.home}> - <Header /> <Routes> <Route path="/" element={<Editor />} /> <Route path="/:id" element={<Editor />} /> diff --git a/client/src/utils/constants.js b/client/src/utils/constants.js index 07e50c6..2583f6c 100644 --- a/client/src/utils/constants.js +++ b/client/src/utils/constants.js @@ -1,25 +1,68 @@ export const SERVER_BASE_URL = import.meta.env.VITE_SERVER_BASE_URL; -export const SUPPORTED_LANGUAGES = { - none: "Plain Text", - c: "C", - cpp: "C++", - css: "CSS", - git: "Git", - go: "Golang", - html: "HTML", - java: "Java", - js: "JavaScript", - json: "JSON", - jsx: "JSX", - kotlin: "Kotlin", - lua: "Lua", - md: "Markdown", - py: "Python", - rust: "Rust", - sh: "Shell", - sql: "SQL", - ts: "TypeScript", - tsx: "TSX", - url: "URL", - xml: "XML", -}; +export const SUPPORTED_LANGUAGES = [{ + value: "none", + label: "Plain Text", +}, { + value: "c", + label: "C", +}, { + value: "cpp", + label: "C++", +}, { + value: "css", + label: "CSS", +}, { + value: "git", + label: "Git", +}, { + value: "go", + label: "Golang", +}, { + value: "html", + label: "HTML", +}, { + value: "java", + label: "Java", +}, { + value: "js", + label: "JavaScript", +}, { + value: "json", + label: "JSON", +}, { + value: "jsx", + label: "JSX", +}, { + value: "kotlin", + label: "Kotlin", +}, { + value: "lua", + label: "Lua", +}, { + value: "md", + label: "Markdown", +}, { + value: "py", + label: "Python", +}, { + value: "rust", + label: "Rust", +}, { + value: "sh", + label: "Shell", +}, { + value: "sql", + label: "SQL", +}, { + value: "ts", + label: "TypeScript", +}, { + value: "tsx", + label: "TSX", +}, { + value: "url", + label: "URL", +}, { + value: "xml", + label: "XML", +}];
\ No newline at end of file |