Skip to content

Commit

Permalink
fix(SelectInputV2): auto scroll (#4282)
Browse files Browse the repository at this point in the history
* fix: selectinputv2 auto scroll

* fix: remove useEffect

* fix: tests
  • Loading branch information
lisalupi authored Oct 8, 2024
1 parent cbfa90a commit a26d439
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-suits-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ultraviolet/ui": patch
---

`<SelectInputV2 />`: auto scroll when the component is at the bottom of the page
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ exports[`SelectInputField > should display right value on grouped options 1`] =
color: #3f4250;
box-shadow: 0px 4px 8px 0px #22263829,0px 8px 24px 0px #2226383d;
padding: 0;
margin-bottom: 80px;
}
.emotion-20[data-animated="true"] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ exports[`Modal > renders with disclosure and onClose 1`] = `
data-open="true"
data-testid="test-backdrop"
data-visible="true"
id="backdrop-modal"
>
<dialog
aria-label="modal-test"
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/components/Modal/components/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ export const Dialog = ({
onFocus={stopFocus}
data-animation={animation}
data-visible={isVisible}
id="backdrop-modal"
>
<StyledDialog
css={dialogCss}
Expand Down
30 changes: 28 additions & 2 deletions packages/ui/src/components/SelectInputV2/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTheme } from '@emotion/react'
import styled from '@emotion/styled'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import type {
Expand All @@ -15,7 +16,9 @@ import { Text } from '../Text'
import { DisplayOption } from './DropdownOption'
import { SearchBarDropdown } from './SearchBarDropdown'
import { useSelectInput } from './SelectInputProvider'
import type { DataType, OptionType } from './types'
import { type DataType, INPUT_SIZE_HEIGHT, type OptionType } from './types'

const DROPDOWN_MAX_HEIGHT = 256

export type DropdownProps = {
children: ReactNode
Expand All @@ -28,6 +31,7 @@ export type DropdownProps = {
loadMore?: ReactNode
optionalInfoPlacement: 'left' | 'right'
isLoading?: boolean
size: 'small' | 'medium' | 'large'
}

export type CreateDropdownProps = {
Expand Down Expand Up @@ -59,10 +63,11 @@ const StyledPopup = styled(Popup)`
color: ${({ theme }) => theme.colors.neutral.text};
box-shadow: ${({ theme }) => `${theme.shadows.raised[0]}, ${theme.shadows.raised[1]}`};
padding: ${({ theme }) => theme.space[0]};
margin-bottom: ${({ theme }) => theme.space[10]};
`

const DropdownContainer = styled(Stack)<{ 'data-grouped': boolean }>`
max-height: 256px;
max-height: ${DROPDOWN_MAX_HEIGHT}px;
overflow-y: scroll;
padding: ${({ theme }) => theme.space[0]};
padding-bottom: ${({ theme }) => theme.space[0.5]};
Expand Down Expand Up @@ -668,6 +673,7 @@ export const Dropdown = ({
loadMore,
optionalInfoPlacement,
isLoading,
size,
}: DropdownProps) => {
const {
setIsDropdownVisible,
Expand All @@ -677,12 +683,32 @@ export const Dropdown = ({
options,
displayedOptions,
} = useSelectInput()
const theme = useTheme()
const [searchBarActive, setSearchBarActive] = useState(false)
const [defaultSearchValue, setDefaultSearch] = useState<string | null>(null)
const ref = useRef<HTMLDivElement>(null)
const [search, setSearch] = useState<string>('')
const [maxWidth, setWidth] = useState<string | number>()

useEffect(() => {
if (refSelect.current && isDropdownVisible) {
const position =
refSelect.current.getBoundingClientRect().bottom +
DROPDOWN_MAX_HEIGHT +
INPUT_SIZE_HEIGHT[size] +
parseInt(theme.space['5'], 10)
const overflow = position - window.innerHeight
if (overflow > 0) {
const modalElement = document.getElementById('backdrop-modal')

if (modalElement) {
modalElement.scrollBy({ top: overflow, behavior: 'smooth' })
} else window.scrollBy({ top: overflow, behavior: 'smooth' })
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isDropdownVisible, refSelect, size, ref.current])

const resizeDropdown = useCallback(() => {
if (
refSelect.current &&
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { StoryFn } from '@storybook/react'
import { SelectInputV2 } from '..'
import { Button } from '../../Button'
import { Modal as ModalComponent } from '../../Modal'
import { dataGrouped } from './resources'

export const Modal: StoryFn<typeof SelectInputV2> = args => (
<ModalComponent
disclosure={<Button type="button">Modal</Button>}
placement="bottom"
>
<SelectInputV2 {...args} label="Label" />
</ModalComponent>
)

Modal.args = {
options: dataGrouped,
multiselect: true,
name: 'example',
placeholder: 'Select item',
placeholderSearch: 'Search in list',
searchable: true,
disabled: false,
helper: 'helper',
}
Modal.decorators = [
StoryComponent => (
<div style={{ height: '80px' }}>
<StoryComponent />
</div>
),
]

Modal.parameters = {
docs: {
description: {
story:
'The component will trigger an automatic scroll when it is located at the bottom of the screen',
},
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ export { LoadMore } from './LoadMore.stories'
export { IsLoading } from './IsLoading.stories'
export { SelectAll } from './SelectAll.stories'
export { Controlled } from './Controlled.stories'
export { Modal } from './Modal.stories'
1 change: 1 addition & 0 deletions packages/ui/src/components/SelectInputV2/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export const SelectInputV2 = <IsMulti extends undefined | boolean>({
loadMore={loadMore}
optionalInfoPlacement={optionalInfoPlacement}
isLoading={isLoading}
size={size}
>
<Stack gap={0.5} aria-label={ariaLabel}>
{label ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,7 @@ exports[`UnitInput > renders click 1`] = `
color: #3f4250;
box-shadow: 0px 4px 8px 0px #22263829,0px 8px 24px 0px #2226383d;
padding: 0;
margin-bottom: 80px;
}
.emotion-25[data-animated="true"] {
Expand Down

0 comments on commit a26d439

Please sign in to comment.