Skip to content

Commit

Permalink
dev: add docs for multiple selections (#1396)
Browse files Browse the repository at this point in the history
  • Loading branch information
silviuaavram authored Aug 8, 2022
1 parent e4d37fe commit efba7f2
Show file tree
Hide file tree
Showing 5 changed files with 402 additions and 5 deletions.
20 changes: 19 additions & 1 deletion docusaurus/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
import * as React from 'react'

export default function Docs() {
return <div>Downshift Docs for E2E Testing</div>
return (
<div style={{width: '50%', margin: '200px auto'}}>
Downshift Docs for E2E Testing
<ul>
<li>
<a href="./useCombobox">useCombobox</a>
</li>
<li>
<a href="./useSelect">useSelect</a>
</li>
<li>
<a href="./useMultipleCombobox">useMultipleCombobox</a>
</li>
<li>
<a href="./useMultipleSelect">useMultipleSelect</a>
</li>
</ul>
</div>
)
}
206 changes: 206 additions & 0 deletions docusaurus/pages/useMultipleCombobox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import React from 'react'

import {useCombobox, useMultipleSelection} from '../../src'

const colors = ['Black', 'Red', 'Green', 'Blue', 'Orange', 'Purple']
const initialSelectedItems = [colors[0], colors[1]]

function getFilteredItems(selectedItems, inputValue) {
const lowerCasedInputValue = inputValue.toLowerCase()

return colors.filter(
colour =>
!selectedItems.includes(colour) &&
colour.toLowerCase().startsWith(lowerCasedInputValue),
)
}

export default function DropdownMultipleCombobox() {
const [inputValue, setInputValue] = React.useState('')
const [selectedItems, setSelectedItems] = React.useState(initialSelectedItems)
const items = React.useMemo(
() => getFilteredItems(selectedItems, inputValue),
[selectedItems, inputValue],
)

const {getSelectedItemProps, getDropdownProps, removeSelectedItem} =
useMultipleSelection({
selectedItems,
onStateChange({selectedItems: newSelectedItems, type}) {
switch (type) {
case useMultipleSelection.stateChangeTypes
.SelectedItemKeyDownBackspace:
case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownDelete:
case useMultipleSelection.stateChangeTypes.DropdownKeyDownBackspace:
case useMultipleSelection.stateChangeTypes.FunctionRemoveSelectedItem:
setSelectedItems(newSelectedItems)
break
default:
break
}
},
})
const {
isOpen,
getToggleButtonProps,
getLabelProps,
getMenuProps,
getInputProps,
getComboboxProps,
highlightedIndex,
getItemProps,
selectedItem,
clearSelection,
} = useCombobox({
items,
inputValue,
selectedItem: null,
stateReducer(state, actionAndChanges) {
const {changes, type} = actionAndChanges

switch (type) {
case useCombobox.stateChangeTypes.InputKeyDownEnter:
case useCombobox.stateChangeTypes.ItemClick:
case useCombobox.stateChangeTypes.InputBlur:
return {
...changes,
...(changes.selectedItem && {isOpen: true, highlightedIndex: 0}),
}
default:
return changes
}
},
onStateChange({
inputValue: newInputValue,
type,
selectedItem: newSelectedItem,
}) {
switch (type) {
case useCombobox.stateChangeTypes.InputKeyDownEnter:
case useCombobox.stateChangeTypes.ItemClick:
setSelectedItems([...selectedItems, newSelectedItem])

break
case useCombobox.stateChangeTypes.InputChange:
setInputValue(newInputValue)
break
default:
break
}
},
})
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
width: 'fit-content',
justifyContent: 'center',
marginTop: 100,
alignSelf: 'center',
}}
>
<label
style={{
fontWeight: 'bolder',
color: selectedItem ? selectedItem : 'black',
}}
{...getLabelProps()}
>
Choose an element:
</label>
<div
style={{
display: 'inline-flex',
gap: '8px',
alignItems: 'center',
flexWrap: 'wrap',
padding: '6px',
}}
>
{selectedItems.map(function renderSelectedItem(
selectedItemForRender,
index,
) {
return (
<span
style={{
backgroundColor: 'lightgray',
paddingLeft: '4px',
paddingRight: '4px',
borderRadius: '6px',
}}
key={`selected-item-${index}`}
{...getSelectedItemProps({
selectedItem: selectedItemForRender,
index,
})}
>
{selectedItemForRender}
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}
<span
style={{padding: '4px', cursor: 'pointer'}}
onClick={e => {
e.stopPropagation()
removeSelectedItem(null)
}}
>
&#10005;
</span>
</span>
)
})}
<div {...getComboboxProps()}>
<input
style={{padding: '4px'}}
{...getInputProps(getDropdownProps({preventKeyAction: isOpen}))}
data-testid="combobox-input"
/>
<button
style={{padding: '4px 8px'}}
aria-label="toggle menu"
data-testid="combobox-toggle-button"
{...getToggleButtonProps()}
>
{isOpen ? <>&#8593;</> : <>&#8595;</>}
</button>
<button
style={{padding: '4px 8px'}}
aria-label="toggle menu"
data-testid="clear-button"
onClick={clearSelection}
>
&#10007;
</button>
</div>
</div>
<ul
{...getMenuProps()}
style={{
listStyle: 'none',
width: '100%',
padding: '0',
margin: '4px 0 0 0',
}}
>
{isOpen &&
items.map((item, index) => (
<li
style={{
padding: '4px',
backgroundColor: highlightedIndex === index ? '#bde4ff' : null,
}}
key={`${item}${index}`}
{...getItemProps({
item,
index,
'data-testid': `downshift-item-${index}`,
})}
>
{item}
</li>
))}
</ul>
</div>
)
}
165 changes: 165 additions & 0 deletions docusaurus/pages/useMultipleSelect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import React from 'react'

import {useSelect, useMultipleSelection} from '../../src'

const colors = ['Black', 'Red', 'Green', 'Blue', 'Orange', 'Purple']
const initialSelectedItems = [colors[0], colors[1]]

function getFilteredItems(selectedItems) {
return colors.filter(colour => !selectedItems.includes(colour))
}

export default function DropdownMultipleSelect() {
const {
getSelectedItemProps,
getDropdownProps,
addSelectedItem,
removeSelectedItem,
selectedItems,
} = useMultipleSelection({initialSelectedItems})
const items = getFilteredItems(selectedItems)
const {
isOpen,
selectedItem,
getToggleButtonProps,
getLabelProps,
getMenuProps,
highlightedIndex,
getItemProps,
} = useSelect({
selectedItem: null,
defaultHighlightedIndex: 0, // after selection, highlight the first item.
items,
stateReducer: (state, actionAndChanges) => {
const {changes, type} = actionAndChanges
switch (type) {
case useSelect.stateChangeTypes.MenuKeyDownEnter:
case useSelect.stateChangeTypes.MenuKeyDownSpaceButton:
case useSelect.stateChangeTypes.ItemClick:
return {
...changes,
isOpen: true, // keep the menu open after selection.
}
default:
return changes
}
},
onStateChange: ({type, selectedItem: newSelectedItem}) => {
switch (type) {
case useSelect.stateChangeTypes.MenuKeyDownEnter:
case useSelect.stateChangeTypes.MenuKeyDownSpaceButton:
case useSelect.stateChangeTypes.ItemClick:
if (newSelectedItem) {
addSelectedItem(newSelectedItem)
}
break
default:
break
}
},
})

return (
<div
style={{
display: 'flex',
flexDirection: 'column',
width: 'fit-content',
justifyContent: 'center',
marginTop: 100,
alignSelf: 'center',
}}
>
<div>
<label
style={{
fontWeight: 'bolder',
color: selectedItem ? selectedItem : 'black',
}}
{...getLabelProps()}
>
Choose an element:
</label>
<div
style={{
display: 'inline-flex',
gap: '8px',
alignItems: 'center',
flexWrap: 'wrap',
padding: '6px',
}}
>
{selectedItems.map(function renderSelectedItem(
selectedItemForRender,
index,
) {
return (
<span
style={{
backgroundColor: 'lightgray',
paddingLeft: '4px',
paddingRight: '4px',
borderRadius: '6px',
}}
className="bg-gray-100 rounded-md px-1 focus:bg-red-400"
key={`selected-item-${index}`}
{...getSelectedItemProps({
selectedItem: selectedItemForRender,
index,
})}
>
{selectedItemForRender}
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}
<span
style={{padding: '4px', cursor: 'pointer'}}
onClick={e => {
e.stopPropagation()
removeSelectedItem(selectedItemForRender)
}}
>
&#10005;
</span>
</span>
)
})}
<button
style={{padding: '4px'}}
type="button"
{...getToggleButtonProps(
getDropdownProps({preventKeyAction: isOpen}),
)}
>
Pick some colors {isOpen ? <>&#8593;</> : <>&#8595;</>}
</button>
</div>
</div>
<ul
{...getMenuProps()}
style={{
listStyle: 'none',
width: '100%',
padding: '0',
margin: '4px 0 0 0',
}}
>
{isOpen &&
items.map((item, index) => (
<li
style={{
padding: '4px',
backgroundColor: highlightedIndex === index ? '#bde4ff' : null,
}}
key={`${item}${index}`}
{...getItemProps({
item,
index,
'data-testid': `downshift-item-${index}`,
})}
>
{item}
</li>
))}
</ul>
</div>
)
}
Loading

0 comments on commit efba7f2

Please sign in to comment.