Merge pull request #1 from MuhammadKhalilzadeh/textfields

Text fields, still some inconsistencies are remaining
This commit is contained in:
Mohammad Khalilzadeh authored and GitHub committed 2024-05-07 20:42:58 +03:30
commit d15d947efe
13 files changed
+997 -136

No files matched your search

+651 -36
View File
File diff suppressed because it is too large. Load diff
+5
View File
@@ -10,7 +10,12 @@
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mui/material": "^5.15.16",
"react": "^18.2.0",
"@fontsource/roboto": "^5.0.13",
"@mui/icons-material": "^5.15.16",
"react-dom": "^18.2.0"
},
"devDependencies": {
+6 -25
View File
@@ -1,35 +1,16 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import { useState } from "react";
import PlayGround from "./screens/PlayGround/PlayGround";
function App() {
const [count, setCount] = useState(0)
const [count, setCount] = useState(0);
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
<PlayGround />
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.jsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
);
}
export default App
export default App;
@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.00004 5.33333V8M8.00004 10.6667H8.00671M14.6667 8C14.6667 11.6819 11.6819 14.6667 8.00004 14.6667C4.31814 14.6667 1.33337 11.6819 1.33337 8C1.33337 4.3181 4.31814 1.33333 8.00004 1.33333C11.6819 1.33333 14.6667 4.3181 14.6667 8Z" stroke="#F04438" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 434 B

@@ -0,0 +1,21 @@
import React from "react";
import "./descriptionTextField.css";
import { TextField } from "@mui/material";
function DescriptionTextField({ hintText, hasError }) {
return (
<div className="description-field-holder">
<div className="text-field-title">Website</div>
<TextField
error={hasError}
className="description-field-area"
multiline
rows={4}
placeholder="Enter a description..."
helperText={hintText}
/>
</div>
);
}
export default DescriptionTextField;
@@ -0,0 +1,32 @@
:root {
--color-title-1: #344054;
--font-family-1: "Roboto", "Helvetica", "Arial", sans-serif;
--text-field-margin-0: 10px 20px;
}
.description-field-holder {
margin: var(--text-field-margin-0);
margin-top: 20px;
}
.text-field-title {
color: var(--color-title-1);
font-weight: bold;
font-family: var(--font-family-1);
margin-bottom: 10px;
}
.description-field-area {
font-size: 13px;
border-radius: 8px;
}
.description-field-label {
margin-top: 10px;
font-family: var(--font-family);
font-size: 11px;
}
.with-error {
color: red;
}
@@ -0,0 +1,55 @@
import React, { useState } from "react";
import "./emailTextField.css";
import { InputAdornment, TextField } from "@mui/material";
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
function EmailTextField({
id,
label,
variant,
placeholder,
icon,
helperText,
error,
}) {
const [showIcon, setShowIcon] = useState(false);
// State to control mouse hover effect
const handleMouseEnter = () => setShowIcon(true);
const handleMouseLeave = () => setShowIcon(false);
return (
<>
<div className="email-text-field-title">Email</div>
<div className="email-text-field">
<TextField
error={error}
className="email-text-field-input"
id={id}
label={label}
variant={variant}
placeholder={placeholder}
InputProps={{
endAdornment: (
<InputAdornment position="end">
{error && showIcon && (
<ErrorOutlineIcon style={{ fill: "red" }} />
)}
{error && !showIcon && (
<ErrorOutlineIcon style={{ fill: "red" }} />
)}
{!error && showIcon && <HelpOutlineIcon />}
</InputAdornment>
),
}}
helperText={helperText}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
/>
</div>
</>
);
}
export default EmailTextField;
@@ -0,0 +1,15 @@
#outlined-basic {
width: 320px;
font-size: 13px;
}
.email-text-field {
position: relative;
margin: 10px 20px;
}
.email-text-field-title {
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
margin: 0 20px;
margin-top: 30px;
}
@@ -0,0 +1,54 @@
import React, { useState } from "react";
import "./websiteTextField.css";
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
function WebsiteTextField({
showHelp = true,
hasCopyButton = false,
hintText,
}) {
const [copied, setCopied] = useState(false);
const handleCopy = () => {
setCopied(true);
setTimeout(() => setCopied(false), 1000);
};
return (
<>
<div className="website-textfield-title">Website</div>
<div className="website-textfield">
<label className="website-label" htmlFor="website">
http://
</label>
<input
type="url"
name="website-url"
id="website-url"
className="website-url"
/>
{showHelp && (
<div
className={
`website-icon-holder ` + !hasCopyButton
? "with-no-copy-button"
: ""
}
>
<HelpOutlineIcon style={{ fill: "var(--icon-color)" }} />
</div>
)}
{hasCopyButton && (
<div className="copy-to-clipboard-button" onClick={handleCopy}>
<ContentCopyIcon className="copy-icon" />
<span>{copied ? " Copied " : " Copy "}</span>
</div>
)}
</div>
<label className="website-textfield-hint">{hintText}</label>
</>
);
}
export default WebsiteTextField;
@@ -0,0 +1,84 @@
:root {
--border-color: #d0d5dd;
--label-font-color: #475467;
--icon-color: #98a2b3;
--text-field-margin-0: 10px 20px;
--text-field-margin-1: 10px 20px 5px;
--font-family: "Roboto", "Helvetica", "Arial", sans-serif;
}
.website-textfield-title {
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
margin: 0 20px;
margin-top: 30px;
}
.website-textfield {
font-family: var(--font-family);
display: flex;
align-items: center;
position: relative;
margin: var(--text-field-margin-1);
}
.website-textfield-hint {
margin: var(--text-field-margin-0);
font-family: var(--font-family);
font-size: 11px;
}
.website-label {
height: 33px;
padding: 5px 20px 5px 10px;
border: solid 1px var(--border-color);
border-right: none;
border-radius: 8px 0 0 8px;
font-size: 13px;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
color: var(--label-font-color);
}
.website-url {
width: 248px;
height: 33px;
padding: 5px 15px;
border: solid 1px var(--border-color);
}
.website-icon-holder {
width: 40px;
height: 33px;
padding: 5px;
border: solid 1px var(--border-color);
border-left: none;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.copy-to-clipboard-button {
height: 33px;
padding: 5px 20px 5px 10px;
border: solid 1px var(--border-color);
border-left: none;
border-radius: 0 8px 8px 0;
font-size: 13px;
text-align: center;
display: flex;
justify-content: space-evenly;
align-items: center;
color: var(--label-font-color);
cursor: pointer;
}
.copy-icon {
margin-right: 10px;
}
.with-no-copy-button {
display: none;
}
-68
View File
@@ -1,68 +0,0 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
+11 -7
View File
@@ -1,10 +1,14 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
ReactDOM.createRoot(document.getElementById('root')).render(
import "@fontsource/roboto/300.css";
import "@fontsource/roboto/400.css";
import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
</React.StrictMode>
);
@@ -0,0 +1,60 @@
import React from "react";
import EmailTextField from "../../components/TextFields/Email/EmailTextField";
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
import WebsiteTextField from "../../components/TextFields/Website/WebsiteTextField";
import DescriptionTextField from "../../components/TextFields/Description/DescriptionTextField";
// This Component is just for the development and test
// purposes and just to see what my components look like while development
// and will be removed in the end
function PlayGround() {
return (
<div>
{/* Default state of Email Text Fields */}
<EmailTextField
error={false}
placeholder="olivia@untitledui.com"
id="outlined-basic"
helperText="This is a hint text to help user."
/>
{/* Email Text Field when validation error occures */}
<EmailTextField
error={true}
placeholder="olivia@untitledui.com"
id="outlined-basic"
icon={<ErrorOutlineIcon style={{ fill: "red" }} />}
helperText="This is an error message"
/>
{/* Email Text Field while mouse hover */}
<EmailTextField
error={false}
placeholder="olivia@untitledui.com"
id="outlined-basic"
icon={<HelpOutlineIcon />}
helperText="This is a hint text to help user."
/>
<br />
<hr />
{/* Now, illustration of the Website text fields */}
<br />
<WebsiteTextField hintText="This is a hint text to help user." />
<WebsiteTextField
hasCopyButton={true}
hintText="This is a hint text to help user."
/>
<br />
<br />
<hr />
{/* Now, illustration of the Description text fields */}
<br />
<DescriptionTextField hintText="This is a hint text to help user." />
<DescriptionTextField
hasError={true}
hintText="This is a hint text to help user."
/>
</div>
);
}
export default PlayGround;