Being to create select box

This commit is contained in:
William Oldham 2021-10-25 22:41:42 +01:00
parent 9448b990e3
commit f3a7b0823c
2 changed files with 183 additions and 0 deletions

View file

@ -0,0 +1,112 @@
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i&display=swap');
body {
background-color: #1B1F3B;
font-family: 'Open Sans', Arial, sans-serif;
}
/* select box styling */
.select-box {
display: flex;
width: 200px;
flex-direction: column;
position: relative;
}
.select-box > * {
box-sizing: border-box;
}
.select-box .options-container {
max-height: 0;
width: calc( 100% - 12px);
opacity: 0;
transition: all 0.2s ease-in-out;
overflow: hidden;
border-radius: 5px;
background-color: #272C4F;
order: 1;
position: absolute;
top: 50px;
}
.select-box .selected {
margin-bottom: 8px;
position: relative;
width: 188px;
height: 45px;
border-radius: 5px;
display: flex;
align-items: center;
background-color: #272C4F;
color: white;
order: 0;
}
.selected::after {
/* Font Awesome */
content: "\f078";
font-family: "Font Awesome 5 Free";
font-weight: 900;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
/* BG Img */
/* content: url("img/arrow-down.svg"); */
position: absolute;
right: 15px;
top: 50%;
transition: transform 150ms;
transform: translateY(-50%);
}
.select-box .option .item {
color: #AFB5DD;
}
.select-box .options-container.active {
max-height: 240px;
opacity: 1;
overflow-y: scroll;
}
.select-box .options-container.active + .selected::after {
transform: translateY(-50%) rotateX(180deg);
}
.select-box .options-container::-webkit-scrollbar {
width: 8px;
background: #0d141f;
background: #81878f;
background: #f1f2f3;
border-radius: 0 5px 5px 0;
}
.select-box .options-container::-webkit-scrollbar-thumb {
background: #525861;
background: #81878f;
border-radius: 0 5px 5px 0;
}
.select-box .option,
.selected {
padding: 12px 15px;
cursor: pointer;
}
.select-box .option:hover {
background: #2F345B;
}
.select-box .option:hover .item {
color: white;
}
.select-box label {
cursor: pointer;
}
.select-box .option .radio {
display: none;
}

View file

@ -0,0 +1,71 @@
import { useRef, useState, useEffect } from "react"
import "./SelectBox.css"
function Option({ option, onClick }) {
return (
<div className="option" onClick={onClick}>
<input
type="radio"
className="radio"
id={option.id} />
<label htmlFor={option.id}>
<div className="item">{option.name}</div>
</label>
</div>
)
}
export function SelectBox({ options }) {
if (!Array.isArray(options)) {
throw "Items must be an array!"
}
const [selectedItem, setSelectedItem] = useState(0)
const [active, setActive] = useState(false)
const containerRef = useRef();
const handleClick = e => {
if (containerRef.current.contains(e.target)) {
// inside click
return;
}
// outside click
closeDropdown()
};
const closeDropdown = () => {
setActive(false)
}
useEffect(() => {
// add when mounted
document.addEventListener("mousedown", handleClick);
document.addEventListener("scroll", closeDropdown);
// return function to be called when unmounted
return () => {
document.removeEventListener("mousedown", handleClick);
document.removeEventListener("scroll", closeDropdown)
};
}, []);
const onOptionClick = (option, i) => {
setSelectedItem(i)
closeDropdown()
}
return (
<div className="select-box" ref={containerRef}>
<div className={"options-container" + (active ? " active" : "")}>
{options.map((opt, i) => (
<Option option={opt} key={i} onClick={() => onOptionClick(opt, i)} />
))}
</div>
<div className="selected" onClick={() => setActive(a => !a)}>
{options ? (
<Option option={options[selectedItem]} />
) : null}
</div>
</div>
)
}