Skip to content

Commit

Permalink
w.i.p. Create Base Components and implemented searchable options
Browse files Browse the repository at this point in the history
  • Loading branch information
melihsahtulek committed Jun 22, 2023
1 parent 7a651e7 commit d9c348e
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 14 deletions.
38 changes: 37 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
import MultiSelect from '@/components/MultiSelect';

function App() {
return <MultiSelect />;
return (
<MultiSelect
options={[
{
label: 'Portugal',
value: 'PT'
},
{
label: 'China',
value: 'CN'
},
{
label: 'Thailand',
value: 'TH'
},
{
label: 'Russia',
value: 'RU'
},
{
label: 'Peru',
value: 'PE'
},
{
label: 'South Korea',
value: 'KR'
},
{
label: 'Canada',
value: 'CA'
}
]}
searchable={false}
multiSelect={false}
disabled={false}
/>
);
}

export default App;
103 changes: 97 additions & 6 deletions src/components/MultiSelect/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,115 @@
import { createContext, useState } from 'react';
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
import styles from '@/components/MultiSelect/multi-select.module.css';

export const MultiSelectContext = createContext({});
export const MultiSelectContext = createContext<any>(null);

function SelectButton() {
return <input type="text" className={styles.select_button} />;
const { setSearchValue, selectedItems, setSelectedItems } = useContext(MultiSelectContext);
const [inputFocus, setInputFocus] = useState(false);

return (
<label
htmlFor="search_inp"
className={styles.select_btn_container}
style={{
borderColor: inputFocus ? 'var(--blue)' : 'var(--gray-300)'
}}>
<div className={styles.selected_items}>
{selectedItems?.map((item: Option, index: number) => (
<span key={index} className={styles.selected_item} onClick={() => {}}>
{item.label}
</span>
))}
</div>
<input
id="search_inp"
type="text"
autoFocus={true}
onFocus={() => {
setInputFocus(true);
}}
onBlur={() => {
setInputFocus(false);
}}
onChange={(e) => {
setSearchValue(e.currentTarget.value.trim());
}}
className={styles.select_input}
/>
</label>
);
}

function SelectBody() {
return <div>Body</div>;
const { optionList, setOptionList, filtered, selectedItems, setSelectedItems } =
useContext(MultiSelectContext);

console.log('filtered body', filtered);
if (filtered.length === 0) {
return <div>Bitti</div>;
}

return (
<div className={styles.select_body}>
{filtered?.map((item: Option, index: number) => (
<div
className={styles.select_body_item}
key={index}
onClick={() => {
setSelectedItems([...selectedItems, item]);
const itemIndex = filtered.findIndex((elem: Option) => elem.value === item.value);
if (itemIndex > -1) {
console.log('if', itemIndex);
const copyArr = [...filtered];
copyArr.splice(itemIndex, 1);
setOptionList(copyArr);
}
}}>
{item.label}
</div>
))}
</div>
);
}

export default function MultiSelect() {
type Option = {
label: string;
value: string;
};

type MultiSelectProps = {
options: Option[];
searchable?: boolean;
multiSelect?: boolean;
disabled?: boolean;
};

export default function MultiSelect({ options }: MultiSelectProps) {
const [selectIsOpen, setSelectIsOpen] = useState<boolean>(false);
const [optionList, setOptionList] = useState<Option[]>(options);

const [searchValue, setSearchValue] = useState<string>('');
const [selectedItems, setSelectedItems] = useState<Option[]>([]);

const filtered = useMemo(() => {
if (!searchValue) {
return optionList;
}
return optionList.filter((item: Option) => item.label.includes(searchValue));
}, [searchValue, optionList]);

return (
<MultiSelectContext.Provider
value={{
selectIsOpen,
setSelectIsOpen
setSelectIsOpen,
optionList,
setOptionList,
searchValue,
setSearchValue,
filtered,
selectedItems,
setSelectedItems
}}>
<div className={styles.container}>
<SelectButton />
Expand Down
86 changes: 81 additions & 5 deletions src/components/MultiSelect/multi-select.module.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,89 @@
.select_button {
:root {
--white: #ffffff;
--gray-50: #f9fafb;
--gray-100: #f3f4f6;
--gray-200: #e5e7eb;
--gray-300: #d1d5db;
--gray-900: #030712;
--blue: #1d4ed8;
}

.container {
display: flex;
flex-direction: column;
position: relative;
}

.select_btn_container {
display: flex;
width: 100%;
height: 2.5rem;
border: 1px solid red;
border: 1px solid transparent;
font-weight: 500;
border-radius: 3px;
font-size: 1rem;
padding: 5px;
gap: 5px;
}

.container {
.select_input {
font-family: inherit;
/* padding: 0 0.5rem; */
flex: 1;
outline: none;
font-weight: 500;
font-size: inherit;
}

.selected_items {
display: flex;
flex-direction: column;
padding: 2.5rem;
gap: 5px;
}

.selected_item {
background-color: var(--gray-100);
border: 1px solid var(--gray-900);
color: var(--gray-900);
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 5px;
font-size: 0.85rem;
font-weight: 600;
line-height: 1;
}

.select_body {
position: absolute;
width: 100%;
top: 2.5rem;
margin-top: 0.5rem;
border: 1px solid var(--gray-300);
border-radius: 3px;
overflow: auto;
max-height: 30vh;
}

.select_body_item {
font-weight: 500;
padding: 10px;
}

.select_body_item:nth-child(even) {
background-color: var(--gray-50);
}

.select_body_item:nth-child(odd) {
background-color: var(--white);
}

.select_body_item:hover {
cursor: pointer;
background-color: var(--gray-100);
}

.active_item {
background-color: var(--blue);
color: var(--white);
}
5 changes: 3 additions & 2 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600&display=swap");
@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600&display=swap');

*,
*::before,
Expand All @@ -10,7 +10,7 @@
}

html {
font-family: "Quicksand", sans-serif;
font-family: 'Quicksand', sans-serif;
font-size: 17px;
min-height: 100%;
}
Expand All @@ -21,4 +21,5 @@ body {
font-family: inherit;
font-size: inherit;
line-height: 1.15;
padding: 2.5rem;
}

0 comments on commit d9c348e

Please sign in to comment.