Overview
DropSelect is the reusable select-field wrapper used in RLink forms. It provides:
- a shared label layout
- required indicator support
- consistent select chrome
- a slot for your
<option>elements
Source
The component is implemented incomponents/ui/DropSelect.tsx.
Props
| Prop | Type | Required | Notes |
|---|---|---|---|
children | React.ReactNode | Yes | Usually one or more <option> elements |
selectName | string | Yes | Applied to the underlying select |
selectId | string | Yes | Used for the field id / label association |
onChange | (e: React.ChangeEvent) => void | Yes | Controlled change handler |
label | string | No | Optional field label |
value | string | No | Controlled selected value |
className | string | No | Additional classes |
required | boolean | No | Shows * beside the label |
Basic usage
Controlled behavior
DropSelect should be used as a controlled field.
That means:
valuecomes from component or form stateonChangeupdates that state- the selected option is driven by the current state value
When to use it
UseDropSelect for:
- module pickers
- status filters
- type/category selection
- any single-choice field using native
<select>
Best practices
- Always include an empty placeholder option when the field is optional or should force a deliberate choice
- Keep option values stable and machine-friendly
- Use a clear
selectIdthat matches the label’s purpose - Use
requiredonly when the form truly depends on a selection
Edge cases
Missing placeholder option
If you omit a blank option, the browser may preselect the first real value, which can lead to accidental submissions.Large option lists
For very large or searchable lists, a native select may become hard to use. Consider a richer combobox pattern instead of stretchingDropSelect beyond its purpose.
Value mismatch
Ifvalue does not match any <option>, the select can show an unexpected state. Keep option values and persisted values aligned.
Disabled states
DropSelect.tsx does not currently expose a disabled prop. If forms need disabled dropdowns consistently, extend the component instead of scattering one-off wrappers across the app.
Related docs
TextInput
Reusable validated text field
FileUpload
Upload images through the shared uploader
Authorization
Common source of module and role dropdowns
Styling guide
Broader design system patterns
