aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrohan09-raj <rajrohan1914@gmail.com>2024-02-19 20:51:05 +0530
committerBlaster4385 <blaster4385@tablaster.dev>2024-02-21 23:52:45 +0530
commitab1892a7104204659fb14a8c8944c066b35e2f3f (patch)
tree45f67b6d919ef262157d7381d13063195ebd75b5
parentfe108210fa0a3846dbb800cfb07ff8e2fc445efa (diff)
feat: Add a custom select component
- We will use this as default html select component is not very customizable Co-authored-by: Blaster4385 <blaster4385@tablaster.dev>
-rw-r--r--client/src/components/CustomSelect/CustomSelect.jsx42
-rw-r--r--client/src/components/CustomSelect/CustomSelect.module.css32
-rw-r--r--client/src/components/Editor/Editor.jsx88
-rw-r--r--client/src/components/Editor/Editor.module.css30
-rw-r--r--client/src/components/Header/Header.jsx22
-rw-r--r--client/src/components/Header/Header.module.css29
-rw-r--r--client/src/pages/Home/Home.jsx1
-rw-r--r--client/src/utils/constants.js91
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>&#60;minibin /&#62;</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