Second pass on component refactor

This commit is contained in:
adilallo
2026-01-29 17:35:51 -07:00
parent 7b9101824a
commit b5735bb2ad
26 changed files with 778 additions and 491 deletions
@@ -0,0 +1,48 @@
"use client";
import { memo, useCallback, useId } from "react";
import { RadioGroupView } from "./RadioGroup.view";
import type { RadioGroupProps } from "./RadioGroup.types";
const RadioGroupContainer = ({
name,
value,
onChange,
mode = "standard",
state = "default",
disabled = false,
options = [],
className = "",
...props
}: RadioGroupProps) => {
// Generate unique ID for accessibility if not provided
const generatedId = useId();
const groupId = name || `radio-group-${generatedId}`;
const handleChange = useCallback(
(optionValue: string) => {
if (!disabled && onChange) {
onChange({ value: optionValue });
}
},
[disabled, onChange],
);
return (
<RadioGroupView
groupId={groupId}
value={value}
mode={mode}
state={state}
disabled={disabled}
options={options}
className={className}
ariaLabel={props["aria-label"]}
onOptionChange={handleChange}
/>
);
};
RadioGroupContainer.displayName = "RadioGroup";
export default memo(RadioGroupContainer);
@@ -0,0 +1,29 @@
export interface RadioOption {
value: string;
label: string;
ariaLabel?: string;
}
export interface RadioGroupProps {
name?: string;
value?: string;
onChange?: (_data: { value: string }) => void;
mode?: "standard" | "inverse";
state?: "default" | "hover" | "focus";
disabled?: boolean;
options?: RadioOption[];
className?: string;
"aria-label"?: string;
}
export interface RadioGroupViewProps {
groupId: string;
value?: string;
mode: "standard" | "inverse";
state: "default" | "hover" | "focus";
disabled: boolean;
options: RadioOption[];
className: string;
ariaLabel?: string;
onOptionChange: (optionValue: string) => void;
}
@@ -0,0 +1,45 @@
import RadioButton from "../RadioButton";
import type { RadioGroupViewProps } from "./RadioGroup.types";
export function RadioGroupView({
groupId,
value,
mode,
state,
disabled,
options,
className,
ariaLabel,
onOptionChange,
}: RadioGroupViewProps) {
return (
<div
className={`space-y-[8px] ${className}`}
role="radiogroup"
aria-label={ariaLabel}
>
{options.map((option) => {
const isSelected = value === option.value;
return (
<RadioButton
key={option.value}
checked={isSelected}
mode={mode}
state={state}
disabled={disabled}
label={option.label}
name={groupId}
value={option.value}
ariaLabel={option.ariaLabel}
onChange={({ checked }) => {
if (checked) {
onOptionChange(option.value);
}
}}
/>
);
})}
</div>
);
}
+2
View File
@@ -0,0 +1,2 @@
export { default } from "./RadioGroup.container";
export type { RadioGroupProps, RadioOption } from "./RadioGroup.types";