hyperhive/frontend/packages/swarm-ui/src/ui/select-field/SelectField.tsx
iris ba873926fa swarm-ui: shared form-field kit (TextField, SelectField, Button)
Closes #3448.

New ui/ primitives: FormField (shared label+control wrapper),
TextField, SelectField, Button — each with a min-height touch target
(2.75em ~= 44px, WCAG 2.5.5) per mara's #3447 ask, and a max-width
instead of a fixed width so the control caps on desktop without
overflowing a narrow/touch viewport.

CreateAgentPage's name field + submit button now come from the kit
instead of page-scoped CSS; ComponentsPage gets a section for each new
primitive with an editable sample.
2026-08-18 20:29:11 +02:00

46 lines
1.2 KiB
TypeScript

// <SelectField> — a labelled `<select>`, `TextField`'s sibling for the
// "pick one of these" shape (the hive-choice dropdown the create-agent
// form needs is the motivating caller). Options are plain
// value/label pairs, not `ComponentChildren` — every real caller so far
// has flat string options, and generic children would need a second
// primitive (`SelectField.Option`) for zero real benefit today.
import { FormField } from '../form-field/FormField.js';
export interface SelectOption {
value: string;
label: string;
}
export function SelectField({
id,
label,
value,
onChange,
options,
required,
}: {
id: string;
label: string;
value: string;
onChange: (value: string) => void;
options: SelectOption[];
required?: boolean;
}) {
return (
<FormField label={label} htmlFor={id}>
<select
id={id}
class="ui-form-control"
value={value}
required={required}
onChange={(e) => onChange((e.target as HTMLSelectElement).value)}
>
{options.map((o) => (
<option key={o.value} value={o.value}>
{o.label}
</option>
))}
</select>
</FormField>
);
}