Skip to content

Commit

Permalink
Combobox final
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Romanski committed Oct 25, 2021
1 parent f9ac089 commit b863ad7
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 4 deletions.
59 changes: 59 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -6,6 +6,7 @@
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"downshift": "^6.1.7",
"paginatejson": "^1.0.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
Expand Down
194 changes: 190 additions & 4 deletions src/episodes/Combobox/Combobox.js
@@ -1,11 +1,197 @@
import React from 'react';
import React, {useState} from 'react';
import {useCombobox, useMultipleSelection} from 'downshift'
import styled from 'styled-components';

const Wrapper = styled.div`
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
padding-top: 200px;
align-items: flex-start;
`;

const StyledCombobox = styled.div`
width: 300px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
position: relative;
`;

const StyledOptions = styled.ul`
width: 100%;
border: 3px solid black;
border-top: none;
margin: 0;
padding: 0;
list-style: none;
li {
display: block;
width: 100%;
padding: 15px 10px;
}
li:hover {
background-color: #f7ec9e !important;
}
`;

const StyledInputWrapper = styled.div`
width: 100%;
position: relative;
border: 3px solid black;
padding: 2px;
min-height: 50px;
&:focus {
outline: none;
}
input {
width: 100%;
height: 100%;
border: none;
&:focus {
outline: none;
}
}
`;

const SelectedItem = styled.span`
display: inline-block;
background-color: #F9E852;
padding: 2px 4px;
margin: 2px;
button {
border: none;
background-color: transparent;
}
`;

const DropdownToggle = styled.button`
font-size: 25px;
position: absolute;
right: 5px;
top: 0;
height: 100%;
cursor: pointer;
background-color: transparent;
border: none;
`;

const items = ['Fava', 'Basia', 'Józef', 'Tola', 'Lotka'];

const Combobox = () => {
const [inputValue, setInputValue] = useState('')
const {
getSelectedItemProps,
getDropdownProps,
addSelectedItem,
removeSelectedItem,
selectedItems,
} = useMultipleSelection({initialSelectedItems: []})
const getFilteredItems = () =>
items.filter(
item =>
selectedItems.indexOf(item) < 0 &&
item.toLowerCase().startsWith(inputValue.toLowerCase()),
)
const {
isOpen,
getToggleButtonProps,
getMenuProps,
getInputProps,
getComboboxProps,
highlightedIndex,
getItemProps,
} = useCombobox({
inputValue,
defaultHighlightedIndex: 0,
selectedItem: null,
items: getFilteredItems(),
stateReducer: (state, actionAndChanges) => {
const {changes, type} = actionAndChanges
switch (type) {
case useCombobox.stateChangeTypes.InputKeyDownEnter:
case useCombobox.stateChangeTypes.ItemClick:
return {
...changes,
isOpen: true,
}
}
return changes
},
onStateChange: ({inputValue, type, selectedItem}) => {
switch (type) {
case useCombobox.stateChangeTypes.InputChange:
setInputValue(inputValue)
break
case useCombobox.stateChangeTypes.InputKeyDownEnter:
case useCombobox.stateChangeTypes.ItemClick:
case useCombobox.stateChangeTypes.InputBlur:
if (selectedItem) {
setInputValue('')
addSelectedItem(selectedItem)
}
break
default:
break
}
},
})

return (
<div>
Combobox
</div>
<Wrapper>
<StyledCombobox>
<StyledInputWrapper {...getComboboxProps()}>
{selectedItems.map((selectedItem, index) => (
<SelectedItem
key={`selected-item-${index}`}
{...getSelectedItemProps({selectedItem, index})}
>
{selectedItem}
<button
onClick={e => {
e.stopPropagation()
removeSelectedItem(selectedItem)
}}
>
&#10005;
</button>
</SelectedItem>
))}
<input
{...getInputProps(
getDropdownProps({preventKeyAction: isOpen}),
)}
/>
<DropdownToggle {...getToggleButtonProps()} aria-label={'toggle menu'}>
&#9660;
</DropdownToggle>
</StyledInputWrapper>
<StyledOptions {...getMenuProps()}>
{isOpen &&
getFilteredItems(items).map((item, index) => (
<li
style={
highlightedIndex === index
? {backgroundColor: '#bde4ff'}
: {}
}
key={`${item}${index}`}
{...getItemProps({item, index})}
>
{item}
</li>
))}
</StyledOptions>
</StyledCombobox>
</Wrapper>
)
};

Expand Down

0 comments on commit b863ad7

Please sign in to comment.