Skip to content

Commit 93bcef9

Browse files
authored
Extend comboboxes to allow for arbitrary entries (#2296)
* Add functionality: users can now type new entries into comboboxes * Refactor firewall forms * Improve TS error messages * Refactor comboboxes
1 parent af42e70 commit 93bcef9

File tree

10 files changed

+577
-414
lines changed

10 files changed

+577
-414
lines changed

app/components/form/fields/ComboboxField.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export type ComboboxFieldProps<
2525
name: TName
2626
control: Control<TFieldValues>
2727
onChange?: (value: string | null | undefined) => void
28-
disabled?: boolean
2928
} & ComboboxBaseProps
3029

3130
export function ComboboxField<
@@ -38,22 +37,37 @@ export function ComboboxField<
3837
label = capitalize(name),
3938
required,
4039
onChange,
41-
disabled,
40+
allowArbitraryValues,
41+
placeholder,
42+
// Intent is to not show both a placeholder and a description, while still having good defaults; prefer a description to a placeholder
43+
/*
44+
* If description is provided, use it.
45+
* If not, but a placeholder is provided, the default description should be undefined.
46+
* If no placeholder is provided and arbitrary values are allowed, the default description should be 'Select an option or enter a custom value'.
47+
* If no placeholder is provided and arbitrary values are not allowed, the default description should be 'Select an option'.
48+
*/
49+
description = placeholder
50+
? undefined
51+
: allowArbitraryValues
52+
? 'Select an option or enter a custom value'
53+
: 'Select an option',
4254
...props
4355
}: ComboboxFieldProps<TFieldValues, TName>) {
4456
const { field, fieldState } = useController({ name, control, rules: { required } })
4557
return (
4658
<div className="max-w-lg">
4759
<Combobox
48-
isDisabled={disabled}
4960
label={label}
61+
placeholder={placeholder}
62+
description={description}
5063
required={required}
5164
selected={field.value || null}
5265
hasError={fieldState.error !== undefined}
5366
onChange={(value) => {
5467
field.onChange(value)
5568
onChange?.(value)
5669
}}
70+
allowArbitraryValues={allowArbitraryValues}
5771
{...props}
5872
/>
5973
<ErrorMessage error={fieldState.error} label={label} />

app/components/form/fields/ListboxField.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export type ListboxFieldProps<
3535
onChange?: (value: string | null | undefined) => void
3636
isLoading?: boolean
3737
noItemsPlaceholder?: string
38+
hideOptionalTag?: boolean
3839
}
3940

4041
export function ListboxField<
@@ -54,6 +55,7 @@ export function ListboxField<
5455
onChange,
5556
isLoading,
5657
noItemsPlaceholder,
58+
hideOptionalTag,
5759
}: ListboxFieldProps<TFieldValues, TName>) {
5860
// TODO: recreate this logic
5961
// validate: (v) => (required && !v ? `${name} is required` : undefined),
@@ -80,6 +82,7 @@ export function ListboxField<
8082
hasError={fieldState.error !== undefined}
8183
isLoading={isLoading}
8284
buttonRef={field.ref}
85+
hideOptionalTag={hideOptionalTag}
8386
/>
8487
<ErrorMessage error={fieldState.error} label={label} />
8588
</div>

0 commit comments

Comments
 (0)