Files
app/src/admin/ui/Select.tsx
BOHA c1bfabb033 fix(ui): Select dropdown caps menu height + shows empty-value option label
The kit Select now passes displayEmpty:true (so a selected value="" option like an "All" filter renders its label instead of a blank control) and MenuProps.PaperProps maxHeight:320 (so long option lists scroll inside the popover instead of listing every record). Both apply via slotProps.select and are overridable per call site. Verified app-wide: no call site regresses (audit of all 74 usages).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:34:19 +02:00

58 lines
1.6 KiB
TypeScript

import MuiTextField, { type TextFieldProps } from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";
export interface SelectOption {
value: string;
label: string;
}
type SelectProps = Omit<TextFieldProps, "onChange" | "select" | "value"> & {
value: string;
onChange: (value: string) => void;
options?: SelectOption[];
};
/** Dropdown styled like the kit TextField; composes inside <Field>. */
export default function Select({
value,
onChange,
options,
children,
slotProps,
...props
}: SelectProps) {
return (
<MuiTextField
select
size="small"
variant="outlined"
fullWidth
value={value}
onChange={(e) => onChange(e.target.value)}
{...props}
slotProps={{
...slotProps,
select: {
// Render the selected option's label even when its value is "" — e.g.
// an "All" filter option. Without displayEmpty MUI shows the control
// blank for an empty-string value despite it being selected.
displayEmpty: true,
// Cap the menu height so long option lists scroll inside the popover
// instead of growing to fit every record (and running off-screen).
MenuProps: { PaperProps: { sx: { maxHeight: 320 } } },
// Let callers override either default (e.g. a custom renderValue).
...((slotProps as { select?: object } | undefined)?.select ?? {}),
},
}}
>
{options
? options.map((o) => (
<MenuItem key={o.value} value={o.value}>
{o.label}
</MenuItem>
))
: children}
</MuiTextField>
);
}