Select
Select.tsx
import React, { useState } from 'react';
import styles from './Select.module.css';
type SelectOption = {
label: string;
value: string;
}
type SelectProps = {
options: SelectOption[];
selectedValue?: string;
onChange: (value: string) => void;
}
const Select = (props: SelectProps) => {
const { options, selectedValue, onChange } = props;
const [isOpen, setIsOpen] = useState<boolean>(false);
const [selectedOption, setSelectedOption] = useState<SelectOption | null>(null);
const handleOptionClick = (option: SelectOption) => {
setSelectedOption(option);
onChange(option.value);
setIsOpen(false);
}
const handleSelectClick = () => {
setIsOpen(prevState => !prevState);
}
return (
<div className={styles.selectContainer}>
<div className={styles.select} onClick={handleSelectClick}>
<div className={styles.selectedValue}>{selectedOption?.label || selectedValue || 'Select an option'}</div>
<div className={styles.arrow}>{isOpen ? '▲' : '▼'}</div>
</div>
{isOpen && (
<ul className={styles.options}>
{options.map(option => (
<li
key={option.value}
className={option.value === selectedValue ? styles.selectedOption : styles.option}
onClick={() => handleOptionClick(option)}
>
{option.label}
</li>
))}
</ul>
)}
</div>
);
}
export default Select;
Select.module.css
.selectContainer {
position: relative;
}
.select {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px;
border: 1px solid #ccc;
cursor: pointer;
}
.selectedValue {
flex-grow: 1;
}
.arrow {
margin-left: 8px;
font-size: 0.8rem;
}
.options {
position: absolute;
top: 100%;
left: 0;
width: 100%;
max-height: 200px;
overflow-y: auto;
border: 1px solid #ccc;
border-top: none;
background-color: #fff;
list-style: none;
padding: 0;
margin: 0;
}
.option {
padding: 8px;
cursor: pointer;
}
.selectedOption {
background-color: #ccc;
}