Files
plane/apps/web/core/components/estimates/radio-select.tsx
chuan 8ebde8aa05
Some checks failed
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Admin Docker Image (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Codespell / Check for spelling errors (push) Has been cancelled
Sync Repositories / sync_changes (push) Has been cancelled
Initial commit: Plane
Synced from upstream: 8853637e981ed7d8a6cff32bd98e7afe20f54362
2025-11-07 00:00:52 +08:00

84 lines
2.6 KiB
TypeScript

import React from "react";
// helpers
import { cn } from "@plane/utils";
type RadioInputProps = {
name?: string;
label?: string | React.ReactNode;
wrapperClassName?: string;
fieldClassName?: string;
buttonClassName?: string;
labelClassName?: string;
ariaLabel?: string;
options: { label: string | React.ReactNode; value: string; disabled?: boolean }[];
vertical?: boolean;
selected: string;
onChange: (value: string) => void;
className?: string;
};
export const RadioInput = ({
name = "radio-input",
label: inputLabel,
labelClassName: inputLabelClassName = "",
wrapperClassName: inputWrapperClassName = "",
fieldClassName: inputFieldClassName = "",
buttonClassName: inputButtonClassName = "",
options,
vertical,
selected,
ariaLabel,
onChange,
className,
}: RadioInputProps) => {
const wrapperClass = vertical ? "flex flex-col gap-1" : "flex gap-2";
const setSelected = (value: string) => {
onChange(value);
};
let aria = ariaLabel ? ariaLabel.toLowerCase().replace(" ", "-") : "";
if (!aria && typeof inputLabel === "string") {
aria = inputLabel.toLowerCase().replace(" ", "-");
} else {
aria = "radio-input";
}
return (
<div className={className}>
{inputLabel && <div className={cn(`mb-2`, inputLabelClassName)}>{inputLabel}</div>}
<div className={cn(`${wrapperClass}`, inputWrapperClassName)}>
{options.map(({ value, label, disabled }, index) => (
<div
key={index}
onClick={() => !disabled && setSelected(value)}
className={cn(
"flex items-center gap-2 text-base",
disabled ? `bg-custom-background-200 border-custom-border-200 cursor-not-allowed` : ``,
inputFieldClassName
)}
>
<input
id={`${name}_${index}`}
name={name}
className={cn(
`group flex flex-shrink-0 size-5 items-center justify-center rounded-full border border-custom-border-400 bg-custom-background-500 cursor-pointer`,
selected === value ? `bg-custom-primary-200 border-custom-primary-100 ` : ``,
disabled ? `bg-custom-background-200 border-custom-border-200 cursor-not-allowed` : ``,
inputButtonClassName
)}
type="radio"
value={value}
disabled={disabled}
checked={selected === value}
/>
<label htmlFor={`${name}_${index}`} className="cursor-pointer w-full">
{label}
</label>
</div>
))}
</div>
</div>
);
};