Files
community-rule/app/components/RadioButton/RadioButton.view.tsx
T
2026-01-29 17:59:11 -07:00

78 lines
1.9 KiB
TypeScript

import type { RadioButtonViewProps } from "./RadioButton.types";
export function RadioButtonView({
radioId,
checked,
disabled,
label,
name,
value,
ariaLabel,
className,
combinedBoxStyles,
defaultOutlineClass,
conditionalHoverOutlineClass,
conditionalFocusClass,
backgroundWhenChecked,
dotColor,
labelColor,
onToggle,
onKeyDown,
...props
}: RadioButtonViewProps) {
return (
<label
className={`inline-flex items-center gap-[8px] cursor-pointer select-none ${
disabled ? "opacity-60 cursor-not-allowed" : ""
} ${className}`}
onMouseDown={(e) => e.preventDefault()}
onClick={onToggle}
>
<span
onKeyDown={onKeyDown}
className={`${combinedBoxStyles} ${defaultOutlineClass} ${conditionalHoverOutlineClass} ${conditionalFocusClass} p-[var(--measures-spacing-004)]`}
style={{
backgroundColor: backgroundWhenChecked,
}}
tabIndex={0}
role="radio"
aria-checked={checked}
{...(disabled && { "aria-disabled": true })}
{...(ariaLabel && { "aria-label": ariaLabel })}
{...(label && !ariaLabel && { "aria-labelledby": `${radioId}-label` })}
id={radioId}
{...props}
>
{/* Radio dot */}
<div
className="w-[16px] h-[16px] rounded-full transition-all duration-200"
style={{
backgroundColor: dotColor,
}}
/>
</span>
{label && (
<span
id={`${radioId}-label`}
className="font-inter text-[14px] leading-[18px]"
style={{ color: labelColor }}
>
{label}
</span>
)}
{/* Hidden input for form submission */}
<input
type="radio"
name={name}
value={value}
checked={checked}
onChange={() => {}}
disabled={disabled}
className="sr-only"
tabIndex={-1}
aria-hidden="true"
/>
</label>
);
}