Skip to content

Commit

Permalink
Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldudak committed Sep 13, 2024
1 parent ad03599 commit cd69068
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 8 deletions.
42 changes: 41 additions & 1 deletion packages/mui-base/src/Menu/Positioner/MenuPositioner.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('<Menu.Positioner />', () => {
}));

describe('prop: anchor', () => {
it('should be placed near the specified element', async function test() {
it('should be placed near the specified element when a ref is passed', async function test() {
if (/jsdom/.test(window.navigator.userAgent)) {
this.skip();
}
Expand Down Expand Up @@ -83,6 +83,46 @@ describe('<Menu.Positioner />', () => {
);
});

it('should be placed near the specified element when an element is passed', async function test() {
if (/jsdom/.test(window.navigator.userAgent)) {
this.skip();
}

function TestComponent() {
const [anchor, setAnchor] = React.useState<HTMLDivElement | null>(null);
const handleRef = React.useCallback((element: HTMLDivElement | null) => {
setAnchor(element);
}, []);

return (
<div>
<Menu.Root open animated={false}>
<Menu.Positioner side="bottom" alignment="start" anchor={anchor} arrowPadding={0}>
<Menu.Popup>
<Menu.Item>1</Menu.Item>
<Menu.Item>2</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Root>
<div data-testid="anchor" style={{ marginTop: '100px' }} ref={handleRef} />
</div>
);
}

const { getByRole, getByTestId } = await render(<TestComponent />);

const popup = getByRole('menu');
const anchor = getByTestId('anchor');

const anchorPosition = anchor.getBoundingClientRect();

await flushMicrotasks();

expect(popup.style.getPropertyValue('transform')).to.equal(
`translate(${anchorPosition.left}px, ${anchorPosition.bottom}px)`,
);
});

it('should be placed at the specified position', async function test() {
if (/jsdom/.test(window.navigator.userAgent)) {
this.skip();
Expand Down
17 changes: 10 additions & 7 deletions packages/mui-base/src/utils/useAnchorPositioning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
} from '@floating-ui/react';
import { getSide, getAlignment } from '@floating-ui/utils';
import { useEnhancedEffect } from './useEnhancedEffect';
import { useLatestRef } from './useLatestRef';
import { ownerWindow } from './owner';

export type Side = 'top' | 'bottom' | 'left' | 'right';
Expand Down Expand Up @@ -206,16 +205,20 @@ export function useAnchorPositioning(
});

// We can assume that element anchors are stable across renders, and thus can be reactive.
const reactiveAnchorDep = anchor == null || isElement(anchor);
const anchorRef = useLatestRef(anchor);
const [reactiveAnchorDep, setReactiveAnchorDep] =
React.useState(anchor == null) || ('current' in anchor! && isElement(anchor.current));

React.useEffect(() => {
setReactiveAnchorDep(anchor == null || ('current' in anchor! && isElement(anchor.current)));
}, [anchor, setReactiveAnchorDep]);

useEnhancedEffect(() => {
const resolvedAnchor =
typeof anchorRef.current === 'function' ? anchorRef.current() : anchorRef.current;
if (resolvedAnchor && !isElement(resolvedAnchor)) {
const resolvedAnchor = typeof anchor === 'function' ? anchor() : anchor;

if (resolvedAnchor) {
refs.setPositionReference(isRef(resolvedAnchor) ? resolvedAnchor.current : resolvedAnchor);
}
}, [refs, anchorRef, reactiveAnchorDep]);
}, [refs, anchor, reactiveAnchorDep]);

React.useEffect(() => {
if (keepMounted && mounted && elements.domReference && elements.floating) {
Expand Down

0 comments on commit cd69068

Please sign in to comment.