Skip to content

Commit 15b8bc6

Browse files
authored
Improve device menu auto placement (#1117)
1 parent 40d8a52 commit 15b8bc6

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

.changeset/plenty-turkeys-drum.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@livekit/components-core": patch
3+
"@livekit/components-react": patch
4+
---
5+
6+
Improve device menu auto placement

packages/core/src/helper/floating-menu.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
import { computePosition, flip, offset, shift } from '@floating-ui/dom';
1+
import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom';
22

3-
export async function computeMenuPosition(
3+
export function computeMenuPosition(
44
button: HTMLElement,
55
menu: HTMLElement,
6-
): Promise<{ x: number; y: number }> {
7-
const { x, y } = await computePosition(button, menu, {
8-
placement: 'top',
9-
middleware: [offset(6), flip(), shift({ padding: 5 })],
6+
onUpdate?: (x: number, y: number) => void,
7+
): () => void {
8+
const cleanup = autoUpdate(button, menu, async () => {
9+
const { x, y } = await computePosition(button, menu, {
10+
placement: 'top',
11+
middleware: [offset(6), flip(), shift({ padding: 5 })],
12+
});
13+
14+
onUpdate?.(x, y);
1015
});
11-
return { x, y };
16+
return cleanup;
1217
}
1318

1419
export function wasClickOutside(insideElement: HTMLElement, event: MouseEvent): boolean {

packages/react/src/prefabs/MediaDeviceMenu.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { computeMenuPosition, wasClickOutside } from '@livekit/components-core';
1+
import { computeMenuPosition, wasClickOutside, log } from '@livekit/components-core';
22
import * as React from 'react';
33
import { MediaDeviceSelect } from '../components/controls/MediaDeviceSelect';
4-
import { log } from '@livekit/components-core';
54
import type { LocalAudioTrack, LocalVideoTrack } from 'livekit-client';
65

76
/** @public */
@@ -66,14 +65,18 @@ export function MediaDeviceMenu({
6665
}, [isOpen]);
6766

6867
React.useLayoutEffect(() => {
68+
let cleanup: ReturnType<typeof computeMenuPosition> | undefined;
6969
if (button.current && tooltip.current && (devices || updateRequired)) {
70-
computeMenuPosition(button.current, tooltip.current).then(({ x, y }) => {
70+
cleanup = computeMenuPosition(button.current, tooltip.current, (x, y) => {
7171
if (tooltip.current) {
7272
Object.assign(tooltip.current.style, { left: `${x}px`, top: `${y}px` });
7373
}
7474
});
7575
}
7676
setUpdateRequired(false);
77+
return () => {
78+
cleanup?.();
79+
};
7780
}, [button, tooltip, devices, updateRequired]);
7881

7982
const handleClickOutside = React.useCallback(
@@ -93,12 +96,10 @@ export function MediaDeviceMenu({
9396

9497
React.useEffect(() => {
9598
document.addEventListener<'click'>('click', handleClickOutside);
96-
window.addEventListener<'resize'>('resize', () => setUpdateRequired(true));
9799
return () => {
98100
document.removeEventListener<'click'>('click', handleClickOutside);
99-
window.removeEventListener<'resize'>('resize', () => setUpdateRequired(true));
100101
};
101-
}, [handleClickOutside, setUpdateRequired]);
102+
}, [handleClickOutside]);
102103

103104
return (
104105
<>

0 commit comments

Comments
 (0)