fix: improve filter popover positioning and reliability across all views

This commit is contained in:
Christian Vidal Wolf
2026-04-25 09:14:25 +02:00
parent f0f78a6126
commit a2bb2f2307
7 changed files with 54 additions and 21 deletions
+26 -16
View File
@@ -1,4 +1,4 @@
import React, { useState, useMemo, useEffect, useRef } from 'react';
import React, { useState, useMemo, useEffect, useRef, useCallback } from 'react';
import { createPortal } from 'react-dom';
import { Search, Check, X, Filter } from 'lucide-react';
import { cn } from '../lib/utils';
@@ -43,34 +43,44 @@ export function ColumnFilterPopover({
const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);
const [position, setPosition] = useState({ top: 0, left: 0 });
const updatePosition = useCallback(() => {
if (!triggerId) return;
const trigger = document.getElementById(triggerId);
if (!trigger) return;
const rect = trigger.getBoundingClientRect();
setPosition({
top: rect.bottom + window.scrollY + 4,
left: Math.min(rect.left + window.scrollX, window.innerWidth + window.scrollX - 300)
});
}, [triggerId]);
useEffect(() => {
const container = document.createElement('div');
container.id = 'filter-portal-' + Math.random().toString(36).substr(2, 9);
container.style.position = 'fixed';
container.id = 'filter-portal-' + Math.random().toString(36).substring(2, 9);
container.style.position = 'absolute';
container.style.zIndex = '9999';
container.style.top = '0';
container.style.left = '0';
container.style.width = '100%';
container.style.pointerEvents = 'none';
document.body.appendChild(container);
setPortalContainer(container);
if (triggerId) {
const trigger = document.getElementById(triggerId);
if (trigger) {
const rect = trigger.getBoundingClientRect();
setPosition({
top: rect.bottom + window.scrollY + 4,
left: Math.min(rect.left + window.scrollX, window.innerWidth - 300)
});
}
}
updatePosition();
// Update on scroll and resize
window.addEventListener('scroll', updatePosition, true);
window.addEventListener('resize', updatePosition);
return () => {
window.removeEventListener('scroll', updatePosition, true);
window.removeEventListener('resize', updatePosition);
if (document.body.contains(container)) {
document.body.removeChild(container);
}
};
}, []);
}, [updatePosition]);
const isDraggingRef = React.useRef(false);
const dragStartRef = React.useRef<number | null>(null);
@@ -202,8 +212,8 @@ export function ColumnFilterPopover({
)}
style={{
zIndex: 9999,
top: position.top - window.scrollY,
left: position.left - window.scrollX
top: position.top,
left: position.left
}}
onClick={(e) => e.stopPropagation()}
>