fix: add-filter button uses ref + state for positioning

Store button position in state on click, then pass to the portal
popover via style. Eliminates getElementById race condition where
the portal hadn't rendered yet when trying to set DOM styles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Gjermund Høsøien Wiggen
2026-06-09 22:23:56 +02:00
parent dd747946ea
commit ed5d96a74b

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { Suspense, useCallback, useEffect, useMemo, useState } from "react"; import { Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom"; import { createPortal } from "react-dom";
import { useRouter, useSearchParams } from "next/navigation"; import { useRouter, useSearchParams } from "next/navigation";
import { import {
@@ -237,9 +237,11 @@ function TicketWorkbenchContent() {
const [saveViewOpen, setSaveViewOpen] = useState(false); const [saveViewOpen, setSaveViewOpen] = useState(false);
const [saveViewName, setSaveViewName] = useState(""); const [saveViewName, setSaveViewName] = useState("");
const [addFilterOpen, setAddFilterOpen] = useState(false); const [addFilterOpen, setAddFilterOpen] = useState(false);
const [addFilterField, setAddFilterField] = useState<string | null>(null); // which field type is selected const [addFilterField, setAddFilterField] = useState<string | null>(null);
const [addFilterOperator, setAddFilterOperator] = useState("is"); const [addFilterOperator, setAddFilterOperator] = useState("is");
const [addFilterValue, setAddFilterValue] = useState(""); const [addFilterValue, setAddFilterValue] = useState("");
const [filterPopoverPos, setFilterPopoverPos] = useState({ left: 0, top: 0 });
const addFilterBtnRef = useRef<HTMLButtonElement>(null);
const [dialogOpen, setDialogOpen] = useState(false); const [dialogOpen, setDialogOpen] = useState(false);
const [newSubject, setNewSubject] = useState(""); const [newSubject, setNewSubject] = useState("");
@@ -840,13 +842,12 @@ function TicketWorkbenchContent() {
))} ))}
<div> <div>
<button <button
ref={addFilterBtnRef}
type="button" type="button"
onClick={(event) => { onClick={() => {
const rect = event.currentTarget.getBoundingClientRect(); if (addFilterBtnRef.current) {
const popover = document.getElementById("add-filter-popover"); const rect = addFilterBtnRef.current.getBoundingClientRect();
if (popover) { setFilterPopoverPos({ left: rect.left, top: rect.bottom + 4 });
popover.style.left = `${rect.left}px`;
popover.style.top = `${rect.bottom + 4}px`;
} }
setAddFilterOpen((prev) => !prev); setAddFilterOpen((prev) => !prev);
}} }}
@@ -1408,8 +1409,8 @@ function TicketWorkbenchContent() {
}} }}
/> />
<div <div
id="add-filter-popover"
className="fixed z-[9999] w-52 rounded-md border border-border bg-popover p-1 shadow-lg" className="fixed z-[9999] w-52 rounded-md border border-border bg-popover p-1 shadow-lg"
style={{ left: filterPopoverPos.left, top: filterPopoverPos.top }}
> >
{!addFilterField ? ( {!addFilterField ? (
<> <>