fix: disallow deselecting dynamic dropdown value (#22931)

This was accomplished by switching from the comboxbox (which has
deselection logic) to a select (which does not).

As a side effect, the dropdowns are wider now, which seems to match
better with other inputs anyway.  And, it seems it uses the `combobox`
role instead of `button` which also seems to make more sense.  Lastly, 
they lose some bolding.
This commit is contained in:
Asher
2026-03-11 17:08:52 -08:00
committed by GitHub
parent d495a4eddb
commit 53304df70d
3 changed files with 25 additions and 41 deletions
@@ -191,7 +191,7 @@ describe("DynamicParameter", () => {
/>, />,
); );
const select = screen.getByRole("button"); const select = screen.getByRole("combobox");
await waitFor(async () => { await waitFor(async () => {
await userEvent.click(select); await userEvent.click(select);
}); });
@@ -211,7 +211,7 @@ describe("DynamicParameter", () => {
/>, />,
); );
const select = screen.getByRole("button"); const select = screen.getByRole("combobox");
await waitFor(async () => { await waitFor(async () => {
await userEvent.click(select); await userEvent.click(select);
}); });
@@ -703,7 +703,7 @@ describe("DynamicParameter", () => {
/>, />,
); );
expect(screen.getByRole("button")).toBeInTheDocument(); expect(screen.getByRole("combobox")).toBeInTheDocument();
}); });
it("handles null/undefined values", () => { it("handles null/undefined values", () => {
@@ -7,14 +7,6 @@ import type {
import { Badge } from "components/Badge/Badge"; import { Badge } from "components/Badge/Badge";
import { Button } from "components/Button/Button"; import { Button } from "components/Button/Button";
import { Checkbox } from "components/Checkbox/Checkbox"; import { Checkbox } from "components/Checkbox/Checkbox";
import {
Combobox,
ComboboxButton,
ComboboxContent,
ComboboxItem,
ComboboxList,
ComboboxTrigger,
} from "components/Combobox/Combobox";
import { ExternalImage } from "components/ExternalImage/ExternalImage"; import { ExternalImage } from "components/ExternalImage/ExternalImage";
import { Input } from "components/Input/Input"; import { Input } from "components/Input/Input";
import { Label } from "components/Label/Label"; import { Label } from "components/Label/Label";
@@ -24,6 +16,13 @@ import {
type Option, type Option,
} from "components/MultiSelectCombobox/MultiSelectCombobox"; } from "components/MultiSelectCombobox/MultiSelectCombobox";
import { RadioGroup, RadioGroupItem } from "components/RadioGroup/RadioGroup"; import { RadioGroup, RadioGroupItem } from "components/RadioGroup/RadioGroup";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "components/Select/Select";
import { Slider } from "components/Slider/Slider"; import { Slider } from "components/Slider/Slider";
import { Stack } from "components/Stack/Stack"; import { Stack } from "components/Stack/Stack";
import { Switch } from "components/Switch/Switch"; import { Switch } from "components/Switch/Switch";
@@ -335,41 +334,25 @@ const ParameterField: FC<ParameterFieldProps> = ({
} }
case "dropdown": { case "dropdown": {
const selectedOption = parameter.options.find(
(opt) => opt.value.value === value,
);
return ( return (
<Combobox <Select
value={value} value={value}
onValueChange={(newValue) => onChange(newValue ?? "")} onValueChange={(newValue) => onChange(newValue ?? "")}
disabled={disabled}
> >
<ComboboxTrigger asChild> <SelectTrigger>
<ComboboxButton <SelectValue
selectedOption={
selectedOption
? {
label: selectedOption.name,
value: selectedOption.value.value,
}
: undefined
}
placeholder={parameter.styling?.placeholder || "Select option"} placeholder={parameter.styling?.placeholder || "Select option"}
disabled={disabled}
/> />
</ComboboxTrigger> </SelectTrigger>
<ComboboxContent> <SelectContent>
<ComboboxList> {parameter.options.map((option) => (
{parameter.options.map((option) => ( <SelectItem key={option.value.value} value={option.value.value}>
<ComboboxItem {option.name}
key={option.value.value} </SelectItem>
value={option.value.value} ))}
> </SelectContent>
{option.name} </Select>
</ComboboxItem>
))}
</ComboboxList>
</ComboboxContent>
</Combobox>
); );
} }
@@ -140,7 +140,8 @@ describe("CreateWorkspacePage", () => {
const instanceTypeField = screen.getByTestId( const instanceTypeField = screen.getByTestId(
"parameter-field-instance_type", "parameter-field-instance_type",
); );
const instanceTypeSelect = within(instanceTypeField).getByRole("button"); const instanceTypeSelect =
within(instanceTypeField).getByRole("combobox");
expect(instanceTypeSelect).toBeInTheDocument(); expect(instanceTypeSelect).toBeInTheDocument();
jest.useFakeTimers(); jest.useFakeTimers();