From 8bc88112aa3fbdc17e6088e485482537b0fb56c4 Mon Sep 17 00:00:00 2001 From: SergeantPanda Date: Tue, 20 Jan 2026 17:09:28 -0600 Subject: [PATCH] Enhancement: Improved pill functionality and sizing. --- .../CustomTable/MultiSelectHeaderWrapper.jsx | 95 ++++++++++++++++--- 1 file changed, 80 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/tables/CustomTable/MultiSelectHeaderWrapper.jsx b/frontend/src/components/tables/CustomTable/MultiSelectHeaderWrapper.jsx index 947d03d9..8fca940f 100644 --- a/frontend/src/components/tables/CustomTable/MultiSelectHeaderWrapper.jsx +++ b/frontend/src/components/tables/CustomTable/MultiSelectHeaderWrapper.jsx @@ -1,4 +1,4 @@ -import React, { cloneElement, isValidElement } from 'react'; +import React, { cloneElement, isValidElement, useRef } from 'react'; import { Box, Flex, Pill, Tooltip, MultiSelect } from '@mantine/core'; /** @@ -6,6 +6,8 @@ import { Box, Flex, Pill, Tooltip, MultiSelect } from '@mantine/core'; * Recursively searches through React children to find and enhance MultiSelect */ const MultiSelectHeaderWrapper = ({ children }) => { + const inputRef = useRef(null); + const enhanceMultiSelect = (element) => { if (!isValidElement(element)) { return element; @@ -13,7 +15,7 @@ const MultiSelectHeaderWrapper = ({ children }) => { // Check if this element is a MultiSelect if (element.type === MultiSelect) { - const { value = [], data = [], ...otherProps } = element.props; + const { value = [], data = [], onChange, ...otherProps } = element.props; const selectedValues = Array.isArray(value) ? value : []; if (selectedValues.length === 0) { @@ -22,6 +24,7 @@ const MultiSelectHeaderWrapper = ({ children }) => { ...otherProps, value, data, + onChange, styles: { pill: { display: 'none' } }, }); } @@ -46,8 +49,42 @@ const MultiSelectHeaderWrapper = ({ children }) => { ); + // Handle opening the dropdown when pill is clicked + const handlePillClick = (e) => { + // Check if the click is on the remove button (it has a data-attribute) + if (e.target.closest('[data-disabled]') || e.target.closest('button')) { + return; // Let the remove button handle it + } + e.stopPropagation(); + // Focus and click the input to open the dropdown + if (inputRef.current) { + const input = inputRef.current.querySelector('input'); + if (input) { + input.focus(); + input.click(); + } + } + }; + + // Handle removing a single filter value + const handleRemoveFirst = (e) => { + e?.stopPropagation?.(); + if (onChange && selectedValues.length > 0) { + const newValues = selectedValues.slice(1); + onChange(newValues); + } + }; + + // Handle clearing all filters + const handleClearAll = (e) => { + e?.stopPropagation?.(); + if (onChange) { + onChange([]); + } + }; + return ( - + { position: 'absolute', top: 4, left: 4, - right: 30, + right: 20, zIndex: 1, pointerEvents: 'none', overflow: 'hidden', @@ -63,28 +100,55 @@ const MultiSelectHeaderWrapper = ({ children }) => { > 1 ? '1 1 auto' : '0 1 auto', minWidth: 0, maxWidth: - selectedValues.length > 1 - ? 'calc(100% - 50px)' - : 'calc(100% - 30px)', - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - display: 'block', + selectedValues.length > 1 ? 'calc(100% - 40px)' : '100%', pointerEvents: 'auto', }} > - {firstLabel} + + {firstLabel} + {selectedValues.length > 1 && ( - +{selectedValues.length - 1} + + +{selectedValues.length - 1} + )} @@ -93,6 +157,7 @@ const MultiSelectHeaderWrapper = ({ children }) => { ...otherProps, value, data, + onChange, styles: { pill: { display: 'none' } }, style: { width: '100%', ...otherProps.style }, })}