mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-25 22:44:19 +00:00
✨ Add Input and InputWithIcon
This commit is contained in:
parent
f18f0baa93
commit
92a15e089a
7 changed files with 137 additions and 18 deletions
|
@ -3,7 +3,9 @@ import classNames from "classnames"
|
||||||
import Style from "./App.module.css"
|
import Style from "./App.module.css"
|
||||||
import BoxWithHeader from "./components/BoxWithHeader"
|
import BoxWithHeader from "./components/BoxWithHeader"
|
||||||
import Button from "./components/Button"
|
import Button from "./components/Button"
|
||||||
import { faArchive, faArrowRight, faExclamationTriangle, faTrash } from "@fortawesome/free-solid-svg-icons"
|
import { faArchive, faArrowRight, faExclamationTriangle, faSearch, faTrash } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import Input from "./components/Input"
|
||||||
|
import InputWithIcon from "./components/InputWithIcon"
|
||||||
|
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
@ -24,6 +26,12 @@ export default function App() {
|
||||||
<Button color={"Yellow"} icon={faExclamationTriangle}>Giallo</Button>
|
<Button color={"Yellow"} icon={faExclamationTriangle}>Giallo</Button>
|
||||||
<Button color={"Red"} icon={faTrash}>Rosso</Button>
|
<Button color={"Red"} icon={faTrash}>Rosso</Button>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
E già che ci siamo, un Input, con e senza icona:
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Input/> <InputWithIcon icon={faSearch}/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</BoxWithHeader>
|
</BoxWithHeader>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,28 +1,14 @@
|
||||||
import React, { isValidElement } from "react"
|
import React from "react"
|
||||||
import Style from "./Button.module.css"
|
import Style from "./Button.module.css"
|
||||||
import classNames from "classnames"
|
import classNames from "classnames"
|
||||||
import isString from "is-string"
|
import make_icon from "../utils/make_icon"
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
|
||||||
|
|
||||||
|
|
||||||
export default function Button({ children, className, color, icon, ...props }) {
|
export default function Button({ children, className, color, icon, ...props }) {
|
||||||
let iconElement;
|
|
||||||
|
|
||||||
if(isValidElement(icon)) {
|
|
||||||
iconElement = <span className={Style.Icon}>icon</span>;
|
|
||||||
}
|
|
||||||
else if(icon) {
|
|
||||||
iconElement = (
|
|
||||||
<span className={Style.Icon}><FontAwesomeIcon icon={icon}/></span>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iconElement = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className={classNames(Style.Button, Style[`Button${color}`], className)} {...props}>
|
<button className={classNames(Style.Button, Style[`Button${color}`], className)} {...props}>
|
||||||
{children} {iconElement}
|
{children} {make_icon(icon, Style.Icon)}
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
12
code/frontend/src/components/Input.js
Normal file
12
code/frontend/src/components/Input.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import React from "react"
|
||||||
|
import Style from "./Input.module.css"
|
||||||
|
import classNames from "classnames"
|
||||||
|
|
||||||
|
|
||||||
|
export default function Input({ children, className, ...props }) {
|
||||||
|
return (
|
||||||
|
<input className={classNames(Style.Input, className)} {...props}>
|
||||||
|
{children}
|
||||||
|
</input>
|
||||||
|
)
|
||||||
|
}
|
18
code/frontend/src/components/Input.module.css
Normal file
18
code/frontend/src/components/Input.module.css
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
.Input {
|
||||||
|
border-radius: 25px;
|
||||||
|
border-width: 0;
|
||||||
|
|
||||||
|
min-height: 28px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
margin: 2px;
|
||||||
|
|
||||||
|
color: var(--fg-field-off);
|
||||||
|
background-color: var(--bg-field-off);
|
||||||
|
}
|
||||||
|
|
||||||
|
.Input:focus {
|
||||||
|
outline: 0; /* TODO: Questo è sconsigliato dalle linee guida sull'accessibilità! */
|
||||||
|
|
||||||
|
color: var(--fg-field-on);
|
||||||
|
background-color: var(--bg-field-on);
|
||||||
|
}
|
37
code/frontend/src/components/InputWithIcon.js
Normal file
37
code/frontend/src/components/InputWithIcon.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import React, {useState} from "react"
|
||||||
|
import Style from "./InputWithIcon.module.css"
|
||||||
|
import classNames from "classnames"
|
||||||
|
import make_icon from "../utils/make_icon"
|
||||||
|
|
||||||
|
|
||||||
|
export default function InputWithIcon({ icon, className, style, onFocus, onBlur, ...props }) {
|
||||||
|
const [isFocused, setFocused] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames(Style.InputWithIcon, isFocused ? Style.Focused : null, className)} style={style}>
|
||||||
|
<div className={classNames(Style.IconPart)}>
|
||||||
|
{make_icon(icon)}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
className={classNames(Style.InputPart)}
|
||||||
|
onFocus={
|
||||||
|
event => {
|
||||||
|
setFocused(true)
|
||||||
|
if(onFocus) {
|
||||||
|
onFocus(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onBlur={
|
||||||
|
event => {
|
||||||
|
setFocused(false)
|
||||||
|
if(onBlur) {
|
||||||
|
onBlur(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
41
code/frontend/src/components/InputWithIcon.module.css
Normal file
41
code/frontend/src/components/InputWithIcon.module.css
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
.InputWithIcon {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
color: var(--fg-field-off);
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.InputWithIcon.Focused {
|
||||||
|
color: var(--fg-field-on);
|
||||||
|
}
|
||||||
|
|
||||||
|
.InputWithIcon .IconPart {
|
||||||
|
border-radius: 25px 0 0 25px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
|
||||||
|
background-color: var(--bg-field-off);
|
||||||
|
}
|
||||||
|
|
||||||
|
.InputWithIcon.Focused .IconPart {
|
||||||
|
background-color: var(--bg-field-on);
|
||||||
|
}
|
||||||
|
|
||||||
|
.InputWithIcon .InputPart {
|
||||||
|
border-radius: 0 25px 25px 0;
|
||||||
|
padding: 2px;
|
||||||
|
|
||||||
|
background-color: var(--bg-field-off);
|
||||||
|
border-width: 0;
|
||||||
|
|
||||||
|
outline: 0; /* TODO: Questo è sconsigliato dalle linee guida sull'accessibilità! */
|
||||||
|
|
||||||
|
/* Repeat the color, as it is overridden by <input> */
|
||||||
|
color: var(--fg-field-off);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.InputWithIcon.Focused .InputPart {
|
||||||
|
background-color: var(--bg-field-on);
|
||||||
|
color: var(--fg-field-on);
|
||||||
|
}
|
17
code/frontend/src/utils/make_icon.js
Normal file
17
code/frontend/src/utils/make_icon.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import React, { isValidElement } from "react"
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
|
|
||||||
|
|
||||||
|
export default function make_icon(icon, className) {
|
||||||
|
if(isValidElement(icon)) {
|
||||||
|
return <span className={className}>icon</span>;
|
||||||
|
}
|
||||||
|
else if(icon) {
|
||||||
|
return (
|
||||||
|
<span className={className}><FontAwesomeIcon icon={icon}/></span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue