From a26d439c494ad24dbb857196f4430e657838bd8e Mon Sep 17 00:00:00 2001 From: lisalupi <106706307+lisalupi@users.noreply.github.com> Date: Tue, 8 Oct 2024 10:48:46 +0200 Subject: [PATCH] fix(SelectInputV2): auto scroll (#4282) * fix: selectinputv2 auto scroll * fix: remove useEffect * fix: tests --- .changeset/little-suits-drive.md | 5 +++ .../__snapshots__/index.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 1 + .../components/Modal/components/Dialog.tsx | 1 + .../src/components/SelectInputV2/Dropdown.tsx | 30 +++++++++++++- .../__stories__/Modal.stories.tsx | 41 +++++++++++++++++++ .../__stories__/index.stories.tsx | 1 + .../ui/src/components/SelectInputV2/index.tsx | 1 + .../__snapshots__/index.test.tsx.snap | 1 + 9 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 .changeset/little-suits-drive.md create mode 100644 packages/ui/src/components/SelectInputV2/__stories__/Modal.stories.tsx diff --git a/.changeset/little-suits-drive.md b/.changeset/little-suits-drive.md new file mode 100644 index 0000000000..6b7a69d021 --- /dev/null +++ b/.changeset/little-suits-drive.md @@ -0,0 +1,5 @@ +--- +"@ultraviolet/ui": patch +--- + +``: auto scroll when the component is at the bottom of the page diff --git a/packages/form/src/components/SelectInputFieldV2/__tests__/__snapshots__/index.test.tsx.snap b/packages/form/src/components/SelectInputFieldV2/__tests__/__snapshots__/index.test.tsx.snap index 8554ddf92e..db2f4bbccc 100644 --- a/packages/form/src/components/SelectInputFieldV2/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/form/src/components/SelectInputFieldV2/__tests__/__snapshots__/index.test.tsx.snap @@ -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"] { diff --git a/packages/ui/src/components/Modal/__tests__/__snapshots__/index.test.tsx.snap b/packages/ui/src/components/Modal/__tests__/__snapshots__/index.test.tsx.snap index 9e6cbf8c33..1511069b21 100644 --- a/packages/ui/src/components/Modal/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/ui/src/components/Modal/__tests__/__snapshots__/index.test.tsx.snap @@ -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" > 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]}; @@ -668,6 +673,7 @@ export const Dropdown = ({ loadMore, optionalInfoPlacement, isLoading, + size, }: DropdownProps) => { const { setIsDropdownVisible, @@ -677,12 +683,32 @@ export const Dropdown = ({ options, displayedOptions, } = useSelectInput() + const theme = useTheme() const [searchBarActive, setSearchBarActive] = useState(false) const [defaultSearchValue, setDefaultSearch] = useState(null) const ref = useRef(null) const [search, setSearch] = useState('') const [maxWidth, setWidth] = useState() + 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 && diff --git a/packages/ui/src/components/SelectInputV2/__stories__/Modal.stories.tsx b/packages/ui/src/components/SelectInputV2/__stories__/Modal.stories.tsx new file mode 100644 index 0000000000..49d6bda223 --- /dev/null +++ b/packages/ui/src/components/SelectInputV2/__stories__/Modal.stories.tsx @@ -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 = args => ( + Modal} + placement="bottom" + > + + +) + +Modal.args = { + options: dataGrouped, + multiselect: true, + name: 'example', + placeholder: 'Select item', + placeholderSearch: 'Search in list', + searchable: true, + disabled: false, + helper: 'helper', +} +Modal.decorators = [ + StoryComponent => ( +
+ +
+ ), +] + +Modal.parameters = { + docs: { + description: { + story: + 'The component will trigger an automatic scroll when it is located at the bottom of the screen', + }, + }, +} diff --git a/packages/ui/src/components/SelectInputV2/__stories__/index.stories.tsx b/packages/ui/src/components/SelectInputV2/__stories__/index.stories.tsx index 407c8b3432..3838ba4a5f 100644 --- a/packages/ui/src/components/SelectInputV2/__stories__/index.stories.tsx +++ b/packages/ui/src/components/SelectInputV2/__stories__/index.stories.tsx @@ -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' diff --git a/packages/ui/src/components/SelectInputV2/index.tsx b/packages/ui/src/components/SelectInputV2/index.tsx index 59fe3c2419..744eb8f3c9 100644 --- a/packages/ui/src/components/SelectInputV2/index.tsx +++ b/packages/ui/src/components/SelectInputV2/index.tsx @@ -209,6 +209,7 @@ export const SelectInputV2 = ({ loadMore={loadMore} optionalInfoPlacement={optionalInfoPlacement} isLoading={isLoading} + size={size} > {label ? ( diff --git a/packages/ui/src/components/UnitInput/__tests__/__snapshots__/index.test.tsx.snap b/packages/ui/src/components/UnitInput/__tests__/__snapshots__/index.test.tsx.snap index 0c33b00795..8929a1ae14 100644 --- a/packages/ui/src/components/UnitInput/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/ui/src/components/UnitInput/__tests__/__snapshots__/index.test.tsx.snap @@ -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"] {