fix: dropdowns should have a max-height & padding from screen (#8055)

Fixes: #6105 

### Problem

- The dropdown gets clipped when the number of filters increases. 

### Solution

- Added scroll property to the ```DropdownMenu``` 
- Added size middleware to the floating UI hook.
- Provided padding of 20px to the size middleware, so that it maintains
distance from the bottom of the screen.

[Screencast from 2024-10-25
13-47-04.webm](https://github.com/user-attachments/assets/c2315ee2-6092-4c4a-8126-dba7ac3bf49b)

---------

Co-authored-by: martmull <martmull@hotmail.fr>
This commit is contained in:
Harsh Singh 2024-10-28 22:29:57 +05:30 committed by GitHub
parent cabae4c462
commit e648d942a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 4 deletions

View File

@ -4,9 +4,10 @@ import {
FloatingPortal, FloatingPortal,
offset, offset,
Placement, Placement,
size,
useFloating, useFloating,
} from '@floating-ui/react'; } from '@floating-ui/react';
import { MouseEvent, useEffect, useRef } from 'react'; import { MouseEvent, useEffect, useRef, useState } from 'react';
import { Keys } from 'react-hotkeys-hook'; import { Keys } from 'react-hotkeys-hook';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
@ -21,6 +22,7 @@ import { isDefined } from '~/utils/isDefined';
import { useDropdown } from '../hooks/useDropdown'; import { useDropdown } from '../hooks/useDropdown';
import { useInternalHotkeyScopeManagement } from '../hooks/useInternalHotkeyScopeManagement'; import { useInternalHotkeyScopeManagement } from '../hooks/useInternalHotkeyScopeManagement';
import { flushSync } from 'react-dom';
import { DropdownMenu } from './DropdownMenu'; import { DropdownMenu } from './DropdownMenu';
import { DropdownOnToggleEffect } from './DropdownOnToggleEffect'; import { DropdownOnToggleEffect } from './DropdownOnToggleEffect';
@ -63,6 +65,9 @@ export const Dropdown = ({
onOpen, onOpen,
}: DropdownProps) => { }: DropdownProps) => {
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const [maxHeight, setMaxHeight] = useState<string | number | undefined>(
undefined,
);
const { const {
isDropdownOpen, isDropdownOpen,
@ -84,7 +89,16 @@ export const Dropdown = ({
const { refs, floatingStyles, placement } = useFloating({ const { refs, floatingStyles, placement } = useFloating({
placement: dropdownPlacement, placement: dropdownPlacement,
middleware: [flip(), ...offsetMiddlewares], middleware: [
flip(),
size({
padding: 12 + 20, // 12px for padding bottom, 20px for dropdown bottom margin target
apply: ({ availableHeight }) => {
flushSync(() => setMaxHeight(availableHeight));
},
}),
...offsetMiddlewares,
],
whileElementsMounted: autoUpdate, whileElementsMounted: autoUpdate,
strategy: dropdownStrategy, strategy: dropdownStrategy,
}); });
@ -155,7 +169,7 @@ export const Dropdown = ({
width={dropdownMenuWidth ?? dropdownWidth} width={dropdownMenuWidth ?? dropdownWidth}
data-select-disable data-select-disable
ref={refs.setFloating} ref={refs.setFloating}
style={floatingStyles} style={{ ...floatingStyles, maxHeight }}
> >
{dropdownComponents} {dropdownComponents}
</DropdownMenu> </DropdownMenu>
@ -167,7 +181,7 @@ export const Dropdown = ({
width={dropdownMenuWidth ?? dropdownWidth} width={dropdownMenuWidth ?? dropdownWidth}
data-select-disable data-select-disable
ref={refs.setFloating} ref={refs.setFloating}
style={floatingStyles} style={{ ...floatingStyles, maxHeight }}
> >
{dropdownComponents} {dropdownComponents}
</DropdownMenu> </DropdownMenu>

View File

@ -25,6 +25,8 @@ const StyledDropdownMenu = styled.div<{
flex-direction: column; flex-direction: column;
z-index: 30; z-index: 30;
overflow-y: scroll;
overflow-x: hidden;
width: ${({ width = 160 }) => width: ${({ width = 160 }) =>
typeof width === 'number' ? `${width}px` : width}; typeof width === 'number' ? `${width}px` : width};
`; `;