Fleet UI: Dropdown button options don't stay highlighted (#46740)
This commit is contained in:
@@ -127,4 +127,36 @@ describe("DropdownWrapper Component", () => {
|
||||
expect(screen.getByText(buttonText)).toBeInTheDocument();
|
||||
expect(screen.queryByText(/option 2/i)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Regression test for #45853 — react-select tracks the last click as
|
||||
// selectValue and re-focuses it on reopen, leaving the previously-clicked
|
||||
// option visually highlighted. Button variant overrides this by forcing
|
||||
// value to null.
|
||||
test("button variant does not mark a previously-clicked option as selected on reopen", async () => {
|
||||
const buttonText = "Actions";
|
||||
render(
|
||||
<DropdownWrapper
|
||||
options={sampleOptions}
|
||||
onChange={mockOnChange}
|
||||
name="test-dropdown"
|
||||
placeholder={buttonText}
|
||||
variant="button"
|
||||
/>
|
||||
);
|
||||
|
||||
// Open, click Option 2, then reopen
|
||||
await userEvent.click(screen.getByText(buttonText));
|
||||
await userEvent.click(screen.getByText(/option 2/i));
|
||||
await userEvent.click(screen.getByText(buttonText));
|
||||
|
||||
// On reopen, no menu option should carry the selected state.
|
||||
// react-select adds `--is-selected` to the option matching `value`; the
|
||||
// fix forces value to null for button variant so this class never appears.
|
||||
const options = document.querySelectorAll(".react-select__option");
|
||||
expect(options.length).toBeGreaterThan(0);
|
||||
|
||||
options.forEach((option) =>
|
||||
expect(option.className).not.toMatch(/--is-selected/)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -201,16 +201,12 @@ export const generateCustomDropdownStyles = (
|
||||
stroke: COLORS["ui-fleet-black-75-over"],
|
||||
},
|
||||
},
|
||||
...(state.isFocused && {
|
||||
backgroundColor: COLORS["ui-fleet-black-5"],
|
||||
boxShadow: "none",
|
||||
".dropdown-wrapper__placeholder": {
|
||||
color: COLORS["ui-fleet-black-75-down"],
|
||||
},
|
||||
".dropdown-wrapper__indicator path": {
|
||||
stroke: COLORS["ui-fleet-black-75-down"],
|
||||
},
|
||||
}),
|
||||
// Note: state.isFocused is intentionally not used as a highlight
|
||||
// trigger here. react-select's internal input retains focus after
|
||||
// the menu closes (outside click, post-modal-close, etc.), so
|
||||
// styling on it would leave the trigger visually highlighted
|
||||
// indefinitely (#45853). Hover + menuIsOpen cover the meaningful
|
||||
// interactive states for an action button.
|
||||
...(state.menuIsOpen && {
|
||||
backgroundColor: COLORS["ui-fleet-black-5"],
|
||||
".dropdown-wrapper__placeholder": {
|
||||
@@ -459,6 +455,7 @@ const DropdownWrapper = ({
|
||||
}: IDropdownWrapper) => {
|
||||
const wrapperClassNames = classnames(baseClass, className, {
|
||||
[`${baseClass}__table-filter`]: variant === "table-filter",
|
||||
[`${baseClass}__button`]: variant === "button",
|
||||
[`${wrapperClassname}`]: !!wrapperClassname,
|
||||
});
|
||||
|
||||
@@ -477,6 +474,13 @@ const DropdownWrapper = ({
|
||||
|
||||
// Ability to handle value of type string or CustomOptionType
|
||||
const getCurrentValue = () => {
|
||||
// Button variant is a fire-and-forget action menu (selection isn't displayed
|
||||
// via `controlShouldRenderValue`). Forcing null prevents react-select from
|
||||
// tracking the last click as the selected value and re-focusing it on reopen
|
||||
// (#45853).
|
||||
if (variant === "button") {
|
||||
return null;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
return options.find((option) => option.value === value) || null;
|
||||
}
|
||||
|
||||
@@ -20,4 +20,14 @@
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
// Button-variant: background while focused so keyboard tabbing is
|
||||
// visible. Mirrors the menuIsOpen background applied via emotion in
|
||||
// DropdownWrapper.tsx. Inputs always match :focus-visible, so this
|
||||
// also applies on click — that's fine since it matches the open state.
|
||||
&__button {
|
||||
.react-select__control:has(input:focus-visible) {
|
||||
background-color: $ui-fleet-black-5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user