Skip to content

Commit

Permalink
[GEN-2203]: add dropdown direction handling to open upwards when near…
Browse files Browse the repository at this point in the history
… bottom of the viewport (#2190)

This pull request includes enhancements to the `Dropdown` component in
the `frontend/webapp/reuseable-components/dropdown/index.tsx` file,
focusing on improving its functionality and user experience. The most
important changes include adding a feature to open the dropdown upwards
if it is near the bottom of the screen and updating related styles and
logic.

Enhancements to `Dropdown` component:

* Introduced the `openUpwards` state and `handleDirection` function to
determine the direction in which the dropdown should open based on its
position relative to the viewport.
* Passed the `openUpwards` state as a prop to the `DropdownList`
component to control its rendering direction.
* Updated the `AbsoluteContainer` styled component to conditionally
apply the `top` or `bottom` style based on the `$openUpwards` prop.
* Modified the `DropdownList` component to accept the `openUpwards` prop
and pass it to the `AbsoluteContainer` for dynamic positioning.
  • Loading branch information
BenElferink authored Jan 12, 2025
1 parent 1ef26a8 commit 4576883
Showing 1 changed file with 20 additions and 6 deletions.
26 changes: 20 additions & 6 deletions frontend/webapp/reuseable-components/dropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,24 @@ const IconWrapper = styled.div`

export const Dropdown: React.FC<DropdownProps> = ({ options, value, onSelect, onDeselect, title, tooltip, placeholder, isMulti = false, showSearch = false, required = false, errorMessage }) => {
const [isOpen, setIsOpen] = useState(false);
const toggleOpen = () => setIsOpen((prev) => !prev);
const [openUpwards, setOpenUpwards] = useState(false);

const ref = useRef<HTMLDivElement>(null);
useOnClickOutside(ref, () => setIsOpen(false));

const handleDirection = () => {
if (ref.current) {
const rect = ref.current.getBoundingClientRect();
const isNearBottom = rect.bottom + 300 > window.innerHeight;
setOpenUpwards(isNearBottom);
}
};

const toggleOpen = () => {
handleDirection();
setIsOpen((prev) => !prev);
};

const arrLen = Array.isArray(value) ? value.length : 0;

return (
Expand All @@ -92,6 +105,7 @@ export const Dropdown: React.FC<DropdownProps> = ({ options, value, onSelect, on

{isOpen && (
<DropdownList
openUpwards={openUpwards}
options={options}
value={value}
onSelect={(option) => {
Expand Down Expand Up @@ -173,11 +187,10 @@ const DropdownPlaceholder: React.FC<{
);
};

const AbsoluteContainer = styled.div`
const AbsoluteContainer = styled.div<{ $openUpwards: boolean }>`
position: absolute;
top: calc(100% + 8px);
${({ $openUpwards }) => ($openUpwards ? 'bottom' : 'top')}: calc(100% + 8px);
left: 0;
z-index: 1;
display: flex;
flex-direction: column;
overflow-y: auto;
Expand All @@ -197,18 +210,19 @@ const SearchInputContainer = styled.div`
`;

const DropdownList: React.FC<{
openUpwards: boolean;
options: DropdownProps['options'];
value: DropdownProps['value'];
onSelect: DropdownProps['onSelect'];
onDeselect: DropdownProps['onDeselect'];
isMulti: DropdownProps['isMulti'];
showSearch: DropdownProps['showSearch'];
}> = ({ options, value, onSelect, onDeselect, isMulti, showSearch }) => {
}> = ({ openUpwards, options, value, onSelect, onDeselect, isMulti, showSearch }) => {
const [searchText, setSearchText] = useState('');
const filteredOptions = options.filter((option) => option.value.toLowerCase().includes(searchText));

return (
<AbsoluteContainer>
<AbsoluteContainer $openUpwards={openUpwards}>
{showSearch && (
<SearchInputContainer>
<Input placeholder='Search...' icon={SearchIcon} value={searchText} onChange={(e) => setSearchText(e.target.value.toLowerCase())} />
Expand Down

0 comments on commit 4576883

Please sign in to comment.