chore(site): add preset combobox to dynamic parameters page (#19100)

## Description

This PR updates the `CreateWorkspacePageViewExperimental` page to use
the `Combobox` React component for preset selection. This aligns it with
the implementation used in the standard `CreateWorkspacePageView`,
ensuring consistency in UI behavior and component usage across both
pages.

<img width="2084" height="792" alt="Screenshot 2025-07-30 at 13 58 23"
src="https://github.com/user-attachments/assets/b8e4ed37-9c59-499f-b4e3-7aaca847eaa1"
/>

Related to `CreateWorkspacePageView` changes:
https://github.com/coder/coder/pull/19063
This commit is contained in:
Susana Ferreira
2025-07-30 18:02:59 +01:00
committed by GitHub
parent 998fbdfbb3
commit 96e32d60a2
@@ -5,16 +5,10 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Avatar } from "components/Avatar/Avatar";
import { Badge } from "components/Badge/Badge";
import { Button } from "components/Button/Button";
import { Combobox } from "components/Combobox/Combobox";
import { Input } from "components/Input/Input";
import { Label } from "components/Label/Label";
import { Link } from "components/Link/Link";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "components/Select/Select";
import { Spinner } from "components/Spinner/Spinner";
import { Switch } from "components/Switch/Switch";
import {
@@ -186,30 +180,31 @@ export const CreateWorkspacePageViewExperimental: FC<
}, [form.submitCount, form.errors]);
const [presetOptions, setPresetOptions] = useState([
{ label: "None", value: "None" },
{ displayName: "None", value: "undefined", icon: "", description: "" },
]);
useEffect(() => {
setPresetOptions([
{ label: "None", value: "None" },
...presets.map((preset) => ({
label: preset.Default ? `${preset.Name} (Default)` : preset.Name,
value: preset.ID,
})),
]);
}, [presets]);
const [selectedPresetIndex, setSelectedPresetIndex] = useState(0);
// Set default preset when presets are loaded
// Build options and keep default label/value in sync
useEffect(() => {
const defaultPreset = presets.find((preset) => preset.Default);
const options = [
{ displayName: "None", value: "undefined", icon: "", description: "" },
...presets.map((preset) => ({
displayName: preset.Default ? `${preset.Name} (Default)` : preset.Name,
value: preset.ID,
icon: preset.Icon,
description: preset.Description,
})),
];
setPresetOptions(options);
const defaultPreset = presets.find((p) => p.Default);
if (defaultPreset) {
// +1 because "None" is at index 0
const defaultIndex =
presets.findIndex((preset) => preset.ID === defaultPreset.ID) + 1;
setSelectedPresetIndex(defaultIndex);
const idx = presets.indexOf(defaultPreset) + 1; // +1 for "None"
setSelectedPresetIndex(idx);
form.setFieldValue("template_version_preset_id", defaultPreset.ID);
} else {
setSelectedPresetIndex(0); // Explicitly set to "None"
form.setFieldValue("template_version_preset_id", undefined);
}
}, [presets]);
}, [presets, form.setFieldValue]);
const [presetParameterNames, setPresetParameterNames] = useState<string[]>(
[],
@@ -572,11 +567,15 @@ export const CreateWorkspacePageViewExperimental: FC<
</div>
<div className="flex flex-col gap-4">
<div className="max-w-lg">
<Select
value={presetOptions[selectedPresetIndex]?.value}
onValueChange={(option) => {
<Combobox
value={
presetOptions[selectedPresetIndex]?.displayName || ""
}
options={presetOptions}
placeholder="Select a preset"
onSelect={(value) => {
const index = presetOptions.findIndex(
(preset) => preset.value === option,
(preset) => preset.value === value,
);
if (index === -1) {
return;
@@ -584,21 +583,14 @@ export const CreateWorkspacePageViewExperimental: FC<
setSelectedPresetIndex(index);
form.setFieldValue(
"template_version_preset_id",
index === 0 ? undefined : option,
// "undefined" string is equivalent to using None option
// Combobox requires a value in order to correctly highlight the None option
presetOptions[index].value === "undefined"
? undefined
: presetOptions[index].value,
);
}}
>
<SelectTrigger>
<SelectValue placeholder={"Select a preset"} />
</SelectTrigger>
<SelectContent>
{presetOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
/>
</div>
{/* Only show the preset parameter visibility toggle if preset parameters are actually being modified, otherwise it is ineffectual */}
{presetParameterNames.length > 0 && (