Skip to content

Commit

Permalink
fix: OBS-729 | Filters: Fix alignment on nested dropdown (#10140)
Browse files Browse the repository at this point in the history
  • Loading branch information
sumitappt authored Mar 27, 2024
1 parent 95a444a commit 85c54f5
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 32 deletions.
10 changes: 7 additions & 3 deletions datahub-web-react/src/app/search/filters/MoreFilterOption.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { RightOutlined } from '@ant-design/icons';
import { Dropdown } from 'antd';
import styled from 'styled-components';
import React from 'react';
import React, { useRef } from 'react';
import { FacetFilterInput, FacetMetadata } from '../../../types.generated';
import { capitalizeFirstLetterOnly } from '../../shared/textUtil';
import OptionsDropdownMenu from './OptionsDropdownMenu';
import useSearchFilterDropdown from './useSearchFilterDropdown';
import { IconWrapper } from './SearchFilterView';
import { getFilterDropdownIcon } from './utils';
import { getFilterDropdownIcon, useElementDimensions } from './utils';
import { MoreFilterOptionLabel } from './styledComponents';

const IconNameWrapper = styled.span`
Expand All @@ -22,6 +22,9 @@ interface Props {
}

export default function MoreFilterOption({ filter, activeFilters, onChangeFilters }: Props) {
const labelRef = useRef<HTMLDivElement>(null);
const { width, height } = useElementDimensions(labelRef);

const {
isMenuOpen,
updateIsMenuOpen,
Expand All @@ -46,17 +49,18 @@ export default function MoreFilterOption({ filter, activeFilters, onChangeFilter
onOpenChange={(open) => updateIsMenuOpen(open)}
dropdownRender={(menu) => (
<OptionsDropdownMenu
style={{ left: width, position: 'absolute', top: -height }}
menu={menu}
updateFilters={updateFilters}
searchQuery={searchQuery}
updateSearchQuery={updateSearchQuery}
isLoading={areFiltersLoading}
searchPlaceholder={filter.displayName || ''}
alignRight
/>
)}
>
<MoreFilterOptionLabel
ref={labelRef}
onClick={() => updateIsMenuOpen(!isMenuOpen)}
isActive={!!numActiveFilters}
isOpen={isMenuOpen}
Expand Down
18 changes: 5 additions & 13 deletions datahub-web-react/src/app/search/filters/OptionsDropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LoadingOutlined } from '@ant-design/icons';
import { Button } from 'antd';
import React from 'react';
import React, { CSSProperties } from 'react';
import styled from 'styled-components/macro';
import { useEntityRegistry } from '../../useEntityRegistry';
import { SearchBar } from '../SearchBar';
Expand All @@ -14,21 +14,13 @@ const StyledButton = styled(Button)`
border-radius: 0;
`;

export const DropdownMenu = styled.div<{ alignRight?: boolean }>`
export const DropdownMenu = styled.div`
background-color: white;
border-radius: 5px;
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
overflow: hidden;
min-width: 200px;
${(props) =>
props.alignRight &&
`
position: absolute;
left: 205px;
top: -34px;
`}
.ant-dropdown-menu-title-content {
background-color: white;
&:hover {
Expand Down Expand Up @@ -59,8 +51,8 @@ interface Props {
isLoading: boolean;
searchQuery: string;
updateSearchQuery: (query: string) => void;
alignRight?: boolean;
searchPlaceholder?: string;
style?: CSSProperties;
}

export default function OptionsDropdownMenu({
Expand All @@ -69,15 +61,15 @@ export default function OptionsDropdownMenu({
isLoading,
searchQuery,
updateSearchQuery,
alignRight,
searchPlaceholder,
style,
}: Props) {
const entityRegistry = useEntityRegistry();

useEnterKeyListener({ querySelectorToExecuteClick: '#updateFiltersButton' });

return (
<DropdownMenu alignRight={alignRight} data-testid="filter-dropdown">
<DropdownMenu data-testid="filter-dropdown" style={style}>
<ScrollableContent>
<SearchBar
initialQuery={searchQuery}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useState } from 'react';
import React, { useRef, useState } from 'react';
import styled from 'styled-components';
import { RightOutlined } from '@ant-design/icons';
import { Dropdown } from 'antd';
import { MoreFilterOptionLabel } from '../../styledComponents';
import BooleanSearchFilterMenu from './BooleanMoreFilterMenu';
import FilterOption from '../../FilterOption';
import { useElementDimensions } from '../../utils';

const IconNameWrapper = styled.span`
display: flex;
Expand All @@ -27,6 +28,8 @@ interface Props {
export default function BooleanMoreFilter({ icon, title, option, count, initialSelected, onUpdate }: Props) {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [isSelected, setIsSelected] = useState<boolean>(initialSelected);
const labelRef = useRef<HTMLDivElement>(null);
const { width, height } = useElementDimensions(labelRef);

function updateSelected() {
onUpdate(isSelected);
Expand Down Expand Up @@ -56,10 +59,15 @@ export default function BooleanMoreFilter({ icon, title, option, count, initialS
open={isMenuOpen}
onOpenChange={(open) => setIsMenuOpen(open)}
dropdownRender={(menuOption) => (
<BooleanSearchFilterMenu menuOption={menuOption} onUpdate={updateSelected} alignRight />
<BooleanSearchFilterMenu
menuOption={menuOption}
onUpdate={updateSelected}
style={{ left: width, position: 'absolute', top: -height }}
/>
)}
>
<MoreFilterOptionLabel
ref={labelRef}
onClick={() => setIsMenuOpen(!isMenuOpen)}
isOpen={isMenuOpen}
isActive={isSelected}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { CSSProperties } from 'react';
import { Button } from 'antd';
import styled from 'styled-components/macro';

Expand All @@ -10,21 +10,13 @@ const StyledButton = styled(Button)`
border-radius: 0;
`;

export const DropdownMenu = styled.div<{ alignRight?: boolean }>`
export const DropdownMenu = styled.div`
background-color: white;
border-radius: 5px;
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
overflow: hidden;
min-width: 200px;
${(props) =>
props.alignRight &&
`
position: absolute;
left: 205px;
top: -34px;
`}
.ant-dropdown-menu-title-content {
background-color: white;
&:hover {
Expand All @@ -41,12 +33,12 @@ const ScrollableContent = styled.div`
interface Props {
menuOption: React.ReactNode;
onUpdate: () => void;
alignRight?: boolean;
style?: CSSProperties;
}

export default function BooleanMoreFilterMenu({ menuOption, onUpdate, alignRight }: Props) {
export default function BooleanMoreFilterMenu({ menuOption, onUpdate, style }: Props) {
return (
<DropdownMenu alignRight={alignRight} data-testid="boolean-filter-dropdown">
<DropdownMenu data-testid="boolean-filter-dropdown" style={style}>
<ScrollableContent>
{React.cloneElement(menuOption as React.ReactElement, { style: { boxShadow: 'none' } })}
</ScrollableContent>
Expand Down
26 changes: 25 additions & 1 deletion datahub-web-react/src/app/search/filters/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
TagOutlined,
UserOutlined,
} from '@ant-design/icons';
import React from 'react';
import React, { useLayoutEffect, useState } from 'react';
import styled from 'styled-components';
import {
AggregationMetadata,
Expand Down Expand Up @@ -346,3 +346,27 @@ export function getParentEntities(entity: Entity): Entity[] | null {
}
return null;
}

/**
* Utility function to get the dimensions of a DOM element.
* @param {React.MutableRefObject<HTMLElement | null>} ref - Reference to the DOM element.
* @returns {Object} - Object containing width and height of the element.
*/
export function useElementDimensions(ref) {
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });

useLayoutEffect(() => {
const updateDimensions = () => {
if (ref.current) {
setDimensions({
width: ref.current.offsetWidth,
height: ref.current.offsetHeight,
});
}
};

updateDimensions();
}, [ref]);

return dimensions;
}

0 comments on commit 85c54f5

Please sign in to comment.