fix: Icons on dropdown are inconsistent when search/selecting (#7875)

* fix: improve metadata mapping for dropdown options

* fix: refactor dropdown component to streamline selected icon rendering
This commit is contained in:
Deon Sanchez 2025-05-02 08:45:04 -06:00 committed by GitHub
commit 6ec73c5d92
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -156,17 +156,21 @@ export default function Dropdown({
// Update filteredOptions with the search results
setFilteredOptions(filtered);
// Update filteredMetadata to match the filtered options
// Create a new metadata array that directly maps to filtered options
if (optionsMetaData) {
const newMetadata = filtered
.filter((option) => validOptions.includes(option)) // Only map metadata for valid options
.map((option) => {
const originalIndex = validOptions.indexOf(option);
return optionsMetaData[originalIndex];
});
// Create a map of option -> metadata for quick lookup
const metadataMap: Record<string, any> = {};
validOptions.forEach((option, index) => {
if (optionsMetaData[index]) {
metadataMap[option] = optionsMetaData[index];
}
});
// Map each filtered option to its metadata (or undefined for custom values)
const newMetadata = filtered.map((option) => metadataMap[option]);
setFilteredMetadata(newMetadata);
} else {
setFilteredMetadata(optionsMetaData);
setFilteredMetadata(undefined);
}
};
@ -188,9 +192,9 @@ export default function Dropdown({
};
const formatTooltipContent = (option: string, index: number) => {
if (!optionsMetaData?.[index]) return option;
if (!filteredMetadata?.[index]) return option;
const metadata = optionsMetaData[index];
const metadata = filteredMetadata[index];
const metadataEntries = Object.entries(metadata)
.filter(([key, value]) => value !== null && key !== "icon")
.map(([key, value]) => {
@ -223,8 +227,24 @@ export default function Dropdown({
// If there are custom values, preserve them when resetting filtered options
if (customValuesInFiltered.length > 0 && combobox) {
setFilteredOptions([...validOptions, ...customValuesInFiltered]);
// Reset filteredMetadata to match the new filteredOptions
if (optionsMetaData) {
const metadataMap: Record<string, any> = {};
validOptions.forEach((option, index) => {
if (optionsMetaData[index]) {
metadataMap[option] = optionsMetaData[index];
}
});
const newMetadata = [...validOptions, ...customValuesInFiltered].map(
(option) => metadataMap[option],
);
setFilteredMetadata(newMetadata);
}
} else {
setFilteredOptions(validOptions);
setFilteredMetadata(optionsMetaData);
}
}
if (!combobox && value && !validOptions.includes(value)) {
@ -259,6 +279,21 @@ export default function Dropdown({
</Button>
);
const renderSelectedIcon = () => {
const selectedIndex = filteredOptions.findIndex(
(option) => option === value,
);
const iconMetadata =
selectedIndex >= 0 ? filteredMetadata?.[selectedIndex]?.icon : undefined;
return iconMetadata ? (
<ForwardedIconComponent
name={iconMetadata}
className="h-4 w-4 flex-shrink-0"
/>
) : null;
};
const renderTriggerButton = () => (
<div className="flex w-full flex-col">
<PopoverTrigger asChild>
@ -286,18 +321,7 @@ export default function Dropdown({
className="flex w-full items-center gap-2 overflow-hidden"
data-testid={`value-dropdown-${id}`}
>
{optionsMetaData?.[
filteredOptions.findIndex((option) => option === value)
]?.icon && (
<ForwardedIconComponent
name={
optionsMetaData?.[
filteredOptions.findIndex((option) => option === value)
]?.icon
}
className="h-4 w-4 flex-shrink-0"
/>
)}
{value && <>{renderSelectedIcon()}</>}
<span className="truncate">
{disabled ? (
RECEIVING_INPUT_VALUE