Skip to content

Commit

Permalink
fix(Select): fix scrolling for Select (#1547)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ilya N. Zykin committed Sep 4, 2020
1 parent be87b8c commit ee893f5
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 10 deletions.
6 changes: 5 additions & 1 deletion packages/picasso/src/ScrollMenu/ScrollMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import { StandardProps } from '@toptal/picasso-shared'
import Menu from '../Menu'
import styles from './styles'

type FocusEventType = (event: React.FocusEvent<HTMLInputElement>) => void

export interface Props extends StandardProps {
selectedIndex?: number | null
onBlur?: FocusEventType
}

enum Direction {
Expand All @@ -37,6 +40,7 @@ const getMoveDirection = (

const ScrollMenu: FunctionComponent<Props> = ({
selectedIndex,
onBlur,
classes,
children,
style
Expand Down Expand Up @@ -95,7 +99,7 @@ const ScrollMenu: FunctionComponent<Props> = ({

return (
<Menu className={classes.menu} style={style}>
<div ref={menuRef} className={classes.scrollView}>
<div ref={menuRef} className={classes.scrollView} onBlur={onBlur}>
{renderChildren}
</div>
</Menu>
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/ScrollMenu/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default ({ palette, screens }: Theme) =>
scrollView: {
maxHeight: '14.75rem', // 6.5 lines of menu to show
overflowY: 'auto',
outline: 'none',

[screens('small', 'medium')]: {
maxHeight: '14.75rem' // 6.5 lines of menu to show
Expand Down
24 changes: 20 additions & 4 deletions packages/picasso/src/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ import { DropdownArrows16 } from '../Icon'
import { isSubstring, disableUnsupportedProps } from '../utils'
import { FeatureOptions } from '../utils/disable-unsupported-props'
import { Option } from './types'
import useSelect, { EMPTY_INPUT_VALUE, ItemProps } from './useSelect'
import useSelect, {
EMPTY_INPUT_VALUE,
ItemProps,
FocusEventType
} from './useSelect'
import styles from './styles'
import { documentable, forwardRef } from '../utils/forward-ref'

Expand Down Expand Up @@ -142,6 +146,7 @@ type OptionsProps = Pick<
inputValue: string
setHighlightedIndex: (index: number | null) => void
getItemProps: (index: number, option: Option) => ItemProps
onBlur?: FocusEventType
onItemSelect: (event: React.MouseEvent, option: Option) => void
}

Expand Down Expand Up @@ -281,6 +286,7 @@ const removeDuplicatedOptions = (options: Option[]) =>
const innerIndex = options.findIndex(
innerOption => innerOption.value === option.value
)

return innerIndex === index
})

Expand Down Expand Up @@ -308,6 +314,7 @@ const renderOptions = ({
setHighlightedIndex,
onItemSelect,
getItemProps,
onBlur,
value,
multiple,
size,
Expand All @@ -327,6 +334,7 @@ const renderOptions = ({
const optionComponents = options.map((option, currentIndex) => {
const { close, onMouseDown } = getItemProps(currentIndex, option)
const selection = getSelection(options, value)

return (
<SelectOption
key={option.key || option.value}
Expand All @@ -350,7 +358,9 @@ const renderOptions = ({
})

return (
<ScrollMenu selectedIndex={highlightedIndex}>{optionComponents}</ScrollMenu>
<ScrollMenu onBlur={onBlur} selectedIndex={highlightedIndex}>
{optionComponents}
</ScrollMenu>
)
}

Expand Down Expand Up @@ -432,11 +442,13 @@ export const Select = documentable(
)

const prevValue = useRef(value)

if (prevValue.current !== value) {
const select = getSelection(
removeDuplicatedOptions([...allOptions, ...selectedOptions]),
value
)

setInputValue(select.display(getDisplayValue!))
prevValue.current = value
}
Expand Down Expand Up @@ -489,6 +501,7 @@ export const Select = documentable(
if (isInSelectedValues) {
return value!.filter(value => value !== option.value)
}

return [...value, String(option.value)]
}
const handleSelect = useCallback(
Expand Down Expand Up @@ -624,11 +637,13 @@ export const Select = documentable(
</NativeSelect>
)

const rootProps = getRootProps()

const selectComponent = (
<>
<div
/* eslint-disable-next-line react/jsx-props-no-spreading */
{...getRootProps()}
{...rootProps}
className={classes.inputWrapper}
>
{!enableAutofill && !native && name && (
Expand Down Expand Up @@ -688,8 +703,9 @@ export const Select = documentable(
renderOption,
highlightedIndex,
setHighlightedIndex,
onItemSelect: handleSelect,
getItemProps,
onItemSelect: handleSelect,
onBlur: rootProps.onBlur,
value,
getDisplayValue,
multiple,
Expand Down
18 changes: 13 additions & 5 deletions packages/picasso/src/Select/useSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const normalizeArrowKey = (event: KeyboardEvent<HTMLInputElement>) => {
if (keyCode >= 37 && keyCode <= 40 && key.indexOf('Arrow') !== 0) {
return `Arrow${key}`
}

return key
}

Expand Down Expand Up @@ -68,6 +69,8 @@ const getNextWrappingIndex = (
return newIndex
}

export type FocusEventType = (event: React.FocusEvent<HTMLInputElement>) => void

interface Props {
value: string
options?: Option[]
Expand All @@ -80,8 +83,8 @@ interface Props {
event: KeyboardEvent<HTMLInputElement>,
inputValue: string
) => void
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void
onBlur?: FocusEventType
onFocus?: FocusEventType
}

type GetInputProps = ({
Expand All @@ -92,10 +95,10 @@ type GetInputProps = ({
HTMLAttributes<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>
>

type GetRootProps = () => {
onFocus: (event: React.FocusEvent<HTMLInputElement>) => void
export type GetRootProps = () => {
onFocus: FocusEventType
onClick: (event: React.MouseEvent<HTMLInputElement>) => void
onBlur: (event: React.FocusEvent<HTMLInputElement>) => void
onBlur: FocusEventType
}

interface UseSelectOutput {
Expand Down Expand Up @@ -169,6 +172,7 @@ const useSelect = ({
}

const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
if (event.relatedTarget) return
setOpen(false)
onBlur(event)
}
Expand All @@ -191,6 +195,10 @@ const useSelect = ({
onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => {
const key = normalizeArrowKey(event)

if (key === 'Tab') {
event.currentTarget.blur()
}

if (key === 'ArrowUp') {
event.preventDefault()

Expand Down

0 comments on commit ee893f5

Please sign in to comment.