diff --git a/packages/pluggableWidgets/datagrid-dropdown-filter-web/CHANGELOG.md b/packages/pluggableWidgets/datagrid-dropdown-filter-web/CHANGELOG.md index a13e3c4090..5fd6af7d82 100644 --- a/packages/pluggableWidgets/datagrid-dropdown-filter-web/CHANGELOG.md +++ b/packages/pluggableWidgets/datagrid-dropdown-filter-web/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Fixed + +- Stabilized the dropdown anchor ref to prevent render loops and incorrect menu positioning. + ## [3.6.0] - 2025-10-01 ### Changed diff --git a/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withLinkedRefStore.tsx b/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withLinkedRefStore.tsx index e6f8ecb55e..965e3d5d26 100644 --- a/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withLinkedRefStore.tsx +++ b/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withLinkedRefStore.tsx @@ -92,6 +92,7 @@ function useGate(props: WidgetProps): DerivedPropsGate { useEffect(() => { gp.setProps(mapProps(props)); }); + return gp.gate; } diff --git a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-darwin.png b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-darwin.png index 24e484d7a7..f9e0b93ff5 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-darwin.png and b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-darwin.png differ diff --git a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-linux.png b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-linux.png index 422b4914be..f9e0b93ff5 100644 Binary files a/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-linux.png and b/packages/pluggableWidgets/datagrid-web/e2e/filtering/DataGridFilteringIntegration.spec.js-snapshots/datagridFilteringIntegration-chromium-linux.png differ diff --git a/packages/pluggableWidgets/gallery-web/e2e/Gallery.spec.js-snapshots/galleryDropdownFilter-chromium-linux.png b/packages/pluggableWidgets/gallery-web/e2e/Gallery.spec.js-snapshots/galleryDropdownFilter-chromium-linux.png index 7ef5ba68d8..25fc5c15fc 100644 Binary files a/packages/pluggableWidgets/gallery-web/e2e/Gallery.spec.js-snapshots/galleryDropdownFilter-chromium-linux.png and b/packages/pluggableWidgets/gallery-web/e2e/Gallery.spec.js-snapshots/galleryDropdownFilter-chromium-linux.png differ diff --git a/packages/shared/widget-plugin-dropdown-filter/src/controls/select/Select.tsx b/packages/shared/widget-plugin-dropdown-filter/src/controls/select/Select.tsx index c84c3751d7..b9600138e1 100644 --- a/packages/shared/widget-plugin-dropdown-filter/src/controls/select/Select.tsx +++ b/packages/shared/widget-plugin-dropdown-filter/src/controls/select/Select.tsx @@ -1,12 +1,13 @@ import cn from "classnames"; import { useSelect, UseSelectProps } from "downshift"; import { observer } from "mobx-react-lite"; -import { CSSProperties, FocusEventHandler, ReactElement, UIEventHandler } from "react"; +import { CSSProperties, FocusEventHandler, ReactElement, Ref, UIEventHandler } from "react"; import { OptionWithState } from "../../typings/OptionWithState"; import { ClearButton } from "../base/ClearButton"; import { OptionsWrapper } from "../base/OptionsWrapper"; import { useFloatingMenu } from "../hooks/useFloatingMenu"; import { Arrow, classes } from "../picker-primitives"; +import { useMergedRefs } from "../../utils/useMergedRefs"; interface SelectProps { value: string; @@ -33,18 +34,19 @@ export const Select = observer(function Select(props: SelectProps): ReactElement const showClear = clearable && !isEmpty; const { refs, floatingStyles } = useFloatingMenu(isOpen); - + const { ref: downshiftRef, ...buttonProps } = getToggleButtonProps({ + "aria-label": props.ariaLabel || "filter", + onFocus: props.onFocus + }) as ReturnType & { ref?: Ref }; + const setReference = useMergedRefs(refs.setReference, downshiftRef); return (
{props.value} diff --git a/packages/shared/widget-plugin-dropdown-filter/src/utils/useMergedRefs.ts b/packages/shared/widget-plugin-dropdown-filter/src/utils/useMergedRefs.ts new file mode 100644 index 0000000000..c634ff6eba --- /dev/null +++ b/packages/shared/widget-plugin-dropdown-filter/src/utils/useMergedRefs.ts @@ -0,0 +1,20 @@ +import { Ref, useCallback, useRef } from "react"; + +export function useMergedRefs(...refs: Array | null | undefined>): (node: T | null) => void { + const refsRef = useRef(refs); + refsRef.current = refs; + + return useCallback((node: T | null) => { + for (const ref of refsRef.current) { + if (!ref) { + continue; + } + + if (typeof ref === "function") { + ref(node); + } else { + ref.current = node; + } + } + }, []); +}