Enhancement: Improved pill functionality and sizing.

This commit is contained in:
SergeantPanda 2026-01-20 17:09:28 -06:00
parent 0984ec9834
commit 8bc88112aa

View file

@ -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 }) => {
</div>
);
// 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 (
<Box style={{ width: '100%', position: 'relative' }}>
<Box ref={inputRef} style={{ width: '100%', position: 'relative' }}>
<Tooltip label={tooltipContent} position="top" withArrow>
<Flex
gap={4}
@ -55,7 +92,7 @@ const MultiSelectHeaderWrapper = ({ children }) => {
position: 'absolute',
top: 4,
left: 4,
right: 30,
right: 20,
zIndex: 1,
pointerEvents: 'none',
overflow: 'hidden',
@ -63,28 +100,55 @@ const MultiSelectHeaderWrapper = ({ children }) => {
>
<Pill
size="xs"
withRemoveButton
onRemove={handleRemoveFirst}
onClick={handlePillClick}
removeButtonProps={{
onClick: handleRemoveFirst,
style: { cursor: 'pointer' },
}}
style={{
flex: '1 1 auto',
flex: selectedValues.length > 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}
<span
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{firstLabel}
</span>
</Pill>
{selectedValues.length > 1 && (
<Pill
size="xs"
style={{ flexShrink: 0, pointerEvents: 'auto' }}
withRemoveButton
onRemove={handleClearAll}
onClick={handlePillClick}
removeButtonProps={{
onClick: handleClearAll,
style: { cursor: 'pointer' },
}}
style={{
flexShrink: 0,
pointerEvents: 'auto',
}}
>
+{selectedValues.length - 1}
<span
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
+{selectedValues.length - 1}
</span>
</Pill>
)}
</Flex>
@ -93,6 +157,7 @@ const MultiSelectHeaderWrapper = ({ children }) => {
...otherProps,
value,
data,
onChange,
styles: { pill: { display: 'none' } },
style: { width: '100%', ...otherProps.style },
})}