From 29d5994d6aef9947b7ca81fb41c376832f5319bb Mon Sep 17 00:00:00 2001 From: Christian Vidal Wolf Date: Fri, 24 Apr 2026 14:06:32 +0200 Subject: [PATCH] fix: ensure filter popovers appear above pinned columns - Add zIndex prop to ColumnFilterPopover and TextFilterPopover - Pass higher zIndex to popovers when column is pinned (zIndex + 100) - Filter popovers now display correctly over sticky columns --- src/components/ColumnFilterPopover.tsx | 7 ++- src/components/PricingView.tsx | 76 +++++++++++++++----------- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/components/ColumnFilterPopover.tsx b/src/components/ColumnFilterPopover.tsx index 72189b2..439c6df 100644 --- a/src/components/ColumnFilterPopover.tsx +++ b/src/components/ColumnFilterPopover.tsx @@ -19,6 +19,7 @@ interface ColumnFilterPopoverProps { onClose: () => void; title?: string; className?: string; + zIndex?: number; } export function ColumnFilterPopover({ @@ -29,7 +30,8 @@ export function ColumnFilterPopover({ onClear, onClose, title, - className + className, + zIndex = 50 }: ColumnFilterPopoverProps) { const [search, setSearch] = useState(''); const [activeTab, setActiveTab] = useState<'values' | 'condition'>('values'); @@ -157,9 +159,10 @@ export function ColumnFilterPopover({ return (
e.stopPropagation()} >
- {openFilter === `prc_${col.index}` && ( - setDynamicColFilters(prev => { - const current = prev[col.index] || []; - return current.includes(val) - ? { ...prev, [col.index]: current.filter(v => v !== val) } - : { ...prev, [col.index]: [...current, val] }; - })} - onSelectAll={vals => setDynamicColFilters(prev => ({ ...prev, [col.index]: vals }))} - onClear={() => { setDynamicColFilters(prev => { const next = { ...prev }; delete next[col.index]; return next; }); setOpenFilter(null); }} - onClose={() => setOpenFilter(null)} - /> - )} +{openFilter === `prc_${col.index}` && ( + setDynamicColFilters(prev => { + const current = prev[col.index] || []; + return current.includes(val) + ? { ...prev, [col.index]: current.filter(v => v !== val) } + : { ...prev, [col.index]: [...current, val] }; + })} + onSelectAll={vals => setDynamicColFilters(prev => ({ ...prev, [col.index]: vals }))} + onClear={() => { setDynamicColFilters(prev => { const next = { ...prev }; delete next[col.index]; return next; }); setOpenFilter(null); }} + onClose={() => setOpenFilter(null)} + zIndex={isPinned(colKey) ? (getStickyRank(colKey) ?? 0) + 100 : 50} + /> + )} { e.stopPropagation(); handleResizeStart(e, colKey, width); }} /> ); @@ -1367,6 +1373,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, onSelectAll={vals => setUnitsOuterFilter(vals)} onClear={() => { setUnitsOuterFilter([]); setOpenFilter(null); }} onClose={() => setOpenFilter(null)} + zIndex={isPinned('unitsOuter') ? (getStickyRank('unitsOuter') ?? 0) + 100 : 50} /> )} { e.stopPropagation(); handleResizeStart(e, 'unitsOuter', columnWidths.unitsOuter); }} /> @@ -1398,6 +1405,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, onSelectAll={vals => setOuterWFilter(vals)} onClear={() => { setOuterWFilter([]); setOpenFilter(null); }} onClose={() => setOpenFilter(null)} + zIndex={isPinned('outerW') ? (getStickyRank('outerW') ?? 0) + 100 : 50} /> )} { e.stopPropagation(); handleResizeStart(e, 'outerW', columnWidths.outerW); }} /> @@ -1429,6 +1437,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, onSelectAll={vals => setOuterLFilter(vals)} onClear={() => { setOuterLFilter([]); setOpenFilter(null); }} onClose={() => setOpenFilter(null)} + zIndex={isPinned('outerL') ? (getStickyRank('outerL') ?? 0) + 100 : 50} /> )} { e.stopPropagation(); handleResizeStart(e, 'outerL', columnWidths.outerL); }} /> @@ -1460,6 +1469,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, onSelectAll={vals => setOuterHFilter(vals)} onClear={() => { setOuterHFilter([]); setOpenFilter(null); }} onClose={() => setOpenFilter(null)} + zIndex={isPinned('outerH') ? (getStickyRank('outerH') ?? 0) + 100 : 50} /> )} { e.stopPropagation(); handleResizeStart(e, 'outerH', columnWidths.outerH); }} /> @@ -1490,21 +1500,22 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, - {openFilter === `con_${col.index}` && ( - setDynamicColFilters(prev => { - const current = prev[col.index] || []; - return current.includes(val) - ? { ...prev, [col.index]: current.filter(v => v !== val) } - : { ...prev, [col.index]: [...current, val] }; - })} - onSelectAll={vals => setDynamicColFilters(prev => ({ ...prev, [col.index]: vals }))} - onClear={() => { setDynamicColFilters(prev => { const next = { ...prev }; delete next[col.index]; return next; }); setOpenFilter(null); }} - onClose={() => setOpenFilter(null)} - /> - )} +{openFilter === `con_${col.index}` && ( + setDynamicColFilters(prev => { + const current = prev[col.index] || []; + return current.includes(val) + ? { ...prev, [col.index]: current.filter(v => v !== val) } + : { ...prev, [col.index]: [...current, val] }; + })} + onSelectAll={vals => setDynamicColFilters(prev => ({ ...prev, [col.index]: vals }))} + onClear={() => { setDynamicColFilters(prev => { const next = { ...prev }; delete next[col.index]; return next; }); setOpenFilter(null); }} + onClose={() => setOpenFilter(null)} + zIndex={isPinned(colKey) ? (getStickyRank(colKey) ?? 0) + 100 : 50} + /> + )} { e.stopPropagation(); handleResizeStart(e, colKey, width); }} /> ); @@ -1928,10 +1939,11 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, } // ── Text filter popover ─────────────────────────────────────────────────────── -function TextFilterPopover({ value, onChange, onClose }: { +function TextFilterPopover({ value, onChange, onClose, zIndex = 50 }: { value: { terms: string[]; op: 'and' | 'or' }; onChange: (v: { terms: string[]; op: 'and' | 'or' }) => void; onClose: () => void; + zIndex?: number; }) { const addTerm = () => { if (value.terms.length < 5) { @@ -1956,7 +1968,7 @@ function TextFilterPopover({ value, onChange, onClose }: { }; return ( -
e.stopPropagation()}> +
e.stopPropagation()}>