Skip to content

Commit b590b9b

Browse files
Improve combobox implementations in preparation for v9 (#2303)
- Make placeholder text more consistent: "Select *a* pool", etc. - Switch a few comboboxes back to listboxes - Remove default image selected in instance-create form - Update tests --------- Co-authored-by: David Crespo <david-crespo@users.noreply.github.com>
1 parent 1a22b73 commit b590b9b

20 files changed

+89
-70
lines changed

app/components/AttachEphemeralIpModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const AttachEphemeralIpModal = ({ onDismiss }: { onDismiss: () => void })
5050
label="IP pool"
5151
placeholder={
5252
siloPools?.items && siloPools.items.length > 0
53-
? 'Select pool'
53+
? 'Select a pool'
5454
: 'No pools available'
5555
}
5656
items={

app/components/AttachFloatingIpModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export const AttachFloatingIpModal = ({
7171
control={form.control}
7272
name="floatingIp"
7373
label="Floating IP"
74-
placeholder="Select floating IP"
74+
placeholder="Select a floating IP"
7575
items={floatingIps.map((ip) => ({
7676
value: ip.id,
7777
label: <FloatingIpLabel fip={ip} />,

app/components/form/fields/ListboxField.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export type ListboxFieldProps<
3434
items: ListboxItem[]
3535
onChange?: (value: string | null | undefined) => void
3636
isLoading?: boolean
37+
noItemsPlaceholder?: string
3738
}
3839

3940
export function ListboxField<
@@ -52,6 +53,7 @@ export function ListboxField<
5253
control,
5354
onChange,
5455
isLoading,
56+
noItemsPlaceholder,
5557
}: ListboxFieldProps<TFieldValues, TName>) {
5658
// TODO: recreate this logic
5759
// validate: (v) => (required && !v ? `${name} is required` : undefined),
@@ -64,6 +66,7 @@ export function ListboxField<
6466
tooltipText={tooltipText}
6567
required={required}
6668
placeholder={placeholder}
69+
noItemsPlaceholder={noItemsPlaceholder}
6770
selected={field.value || null}
6871
items={items}
6972
onChange={(value) => {

app/components/form/fields/SubnetListbox.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import { useApiQuery } from '@oxide/api'
1111

1212
import { useProjectSelector } from '~/hooks'
1313

14-
import { ComboboxField, type ComboboxFieldProps } from './ComboboxField'
14+
import { ListboxField, type ListboxFieldProps } from './ListboxField'
1515

1616
type SubnetListboxProps<
1717
TFieldValues extends FieldValues,
1818
TName extends FieldPath<TFieldValues>,
19-
> = Omit<ComboboxFieldProps<TFieldValues, TName>, 'items'> & {
19+
> = Omit<ListboxFieldProps<TFieldValues, TName>, 'items'> & {
2020
vpcNameField: FieldPath<TFieldValues>
2121
}
2222

@@ -47,11 +47,13 @@ export function SubnetListbox<
4747
).data?.items || []
4848

4949
return (
50-
<ComboboxField
50+
<ListboxField
5151
{...fieldProps}
5252
items={subnets.map(({ name }) => ({ value: name, label: name }))}
5353
disabled={!vpcExists}
5454
control={control}
55+
placeholder="Select a subnet"
56+
noItemsPlaceholder={vpcName ? 'No subnets found' : 'Select a VPC to see subnets'}
5557
/>
5658
)
5759
}

app/forms/floating-ip-create.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export function CreateFloatingIpSideModalForm() {
111111
items={(allPools?.items || []).map((p) => toListboxItem(p))}
112112
label="IP pool"
113113
control={form.control}
114-
placeholder="Select pool"
114+
placeholder="Select a pool"
115115
/>
116116
</AccordionItem>
117117
</Accordion.Root>

app/forms/instance-create.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import {
3737
import { AccordionItem } from '~/components/AccordionItem'
3838
import { DocsPopover } from '~/components/DocsPopover'
3939
import { CheckboxField } from '~/components/form/fields/CheckboxField'
40-
import { ComboboxField } from '~/components/form/fields/ComboboxField'
4140
import { DescriptionField } from '~/components/form/fields/DescriptionField'
4241
import { DiskSizeField } from '~/components/form/fields/DiskSizeField'
4342
import {
@@ -46,6 +45,7 @@ import {
4645
} from '~/components/form/fields/DisksTableField'
4746
import { FileField } from '~/components/form/fields/FileField'
4847
import { BootDiskImageSelectField as ImageSelectField } from '~/components/form/fields/ImageSelectField'
48+
import { ListboxField } from '~/components/form/fields/ListboxField'
4949
import { NameField } from '~/components/form/fields/NameField'
5050
import { NetworkInterfaceField } from '~/components/form/fields/NetworkInterfaceField'
5151
import { NumberField } from '~/components/form/fields/NumberField'
@@ -221,9 +221,6 @@ export function CreateInstanceForm() {
221221
const defaultValues: InstanceCreateInput = {
222222
...baseDefaultValues,
223223
bootDiskSourceType: defaultSource,
224-
siloImageSource: siloImages?.[0]?.id || '',
225-
projectImageSource: projectImages?.[0]?.id || '',
226-
diskSource: disks?.[0]?.value || '',
227224
sshPublicKeys: allKeys,
228225
bootDiskSize: nearest10(defaultImage?.size / GiB),
229226
externalIps: [{ type: 'ephemeral', pool: defaultPool }],
@@ -550,7 +547,7 @@ export function CreateInstanceForm() {
550547
/>
551548
</div>
552549
) : (
553-
<ComboboxField
550+
<ListboxField
554551
label="Disk"
555552
name="diskSource"
556553
description="Existing disks that are not attached to an instance"
@@ -732,7 +729,7 @@ const AdvancedAccordion = ({
732729
<Listbox
733730
name="pools"
734731
label="IP pool for ephemeral IP"
735-
placeholder={defaultPool ? `${defaultPool} (default)` : 'Select pool'}
732+
placeholder={defaultPool ? `${defaultPool} (default)` : 'Select a pool'}
736733
selected={`${siloPools.find((pool) => pool.name === selectedPool)?.name}`}
737734
items={
738735
siloPools.map((pool) => ({
@@ -837,7 +834,7 @@ const AdvancedAccordion = ({
837834
)
838835
}}
839836
required
840-
placeholder="Select floating IP"
837+
placeholder="Select a floating IP"
841838
selected={selectedFloatingIp?.name || ''}
842839
/>
843840
</form>

app/forms/network-interface-create.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { useMemo } from 'react'
99

1010
import { useApiQuery, type ApiError, type InstanceNetworkInterfaceCreate } from '@oxide/api'
1111

12-
import { ComboboxField } from '~/components/form/fields/ComboboxField'
1312
import { DescriptionField } from '~/components/form/fields/DescriptionField'
13+
import { ListboxField } from '~/components/form/fields/ListboxField'
1414
import { NameField } from '~/components/form/fields/NameField'
1515
import { SubnetListbox } from '~/components/form/fields/SubnetListbox'
1616
import { TextField } from '~/components/form/fields/TextField'
@@ -65,12 +65,13 @@ export function CreateNetworkInterfaceForm({
6565
<DescriptionField name="description" control={form.control} />
6666
<FormDivider />
6767

68-
<ComboboxField
68+
<ListboxField
6969
name="vpcName"
7070
label="VPC"
7171
items={vpcs.map(({ name }) => ({ label: name, value: name }))}
7272
required
7373
control={form.control}
74+
placeholder="Select a VPC"
7475
/>
7576
<SubnetListbox
7677
name="subnetName"

app/forms/snapshot-create.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export function CreateSnapshotSideModalForm() {
7676
<ComboboxField
7777
label="Disk"
7878
name="disk"
79+
placeholder="Select a disk"
7980
items={diskItems}
8081
required
8182
control={form.control}

app/pages/project/floating-ips/FloatingIpsPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ const AttachFloatingIpModal = ({
290290
form.setValue('instanceId', e)
291291
}}
292292
required
293-
placeholder="Select instance"
293+
placeholder="Select an instance"
294294
selected={form.watch('instanceId')}
295295
/>
296296
</form>

app/pages/system/SiloImagesPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ const PromoteImageModal = ({ onDismiss }: { onDismiss: () => void }) => {
169169
<Modal.Section>
170170
<form autoComplete="off" onSubmit={handleSubmit(onSubmit)} className="space-y-4">
171171
<ComboboxField
172-
placeholder="Filter images by project"
172+
placeholder="Select a project"
173173
name="project"
174174
label="Project"
175175
items={projectItems}

0 commit comments

Comments
 (0)