Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/components/ui/input/InputChoicebox.tsx
T

67 lines
2.6 KiB
TypeScript

import { RadioCardGroup } from "~/ui/components/RadioCardGroup";
import { Label } from "../label";
import { cn } from "~/lib/utils";
interface Props {
name?: string;
title?: string;
value?: string;
defaultValue?: string;
onChange?: (value: string) => void;
options: { name: string | React.ReactNode; value: string; description?: string }[];
required?: boolean;
columns?: 1 | 2 | 3 | 4;
disabled?: boolean;
style?: React.CSSProperties;
}
// Subframe migration (strangler shim):
// Single-choice picker rendered with the Subframe design-system `RadioCardGroup` behind the
// original `InputChoicebox` API. Public props are unchanged; call sites are not touched.
// - `value`/`defaultValue`/`onChange` keep controlled + uncontrolled behaviour (Radix RadioGroup).
// - Form submission still goes through the hidden <input name=...> (RadioGroup buttons are not
// submitted natively), preserving the prior contract exactly.
// - `columns` maps to a CSS grid on the group; default (no columns) keeps the legacy 2-up grid
// when there are exactly two options, otherwise a single column.
export default function InputChoicebox({ name, title, value, defaultValue, onChange, options, required, columns, disabled, style }: Props) {
return (
<div>
{name && <input type="hidden" name={name} value={value} readOnly hidden />}
{title && (
<Label className="mb-1 block text-xs">
{title} {required && <span className="text-red-600">*</span>}
</Label>
)}
<RadioCardGroup
defaultValue={defaultValue}
value={value}
onValueChange={onChange ? (value) => onChange(value) : undefined}
disabled={disabled}
className={cn(
"grid w-full",
columns === 1
? "grid-cols-1"
: columns === 2
? "grid-cols-2"
: columns === 3
? "sm:grid-cols-3"
: columns === 4
? "sm:grid-cols-4"
: options.length === 2
? "grid-cols-2"
: "grid-cols-1"
)}
>
{options.map((option) => (
<RadioCardGroup.RadioCard value={option.value} key={option.value} disabled={disabled} style={style} className="max-w-none">
<div className="flex flex-col items-start gap-1">
<span className="text-sm font-medium">{option.name}</span>
{option.description && <span className="text-muted-foreground text-xs">{option.description}</span>}
</div>
</RadioCardGroup.RadioCard>
))}
</RadioCardGroup>
</div>
);
}