Add radio button groups

This commit is contained in:
Stephan
2023-03-13 20:31:08 +01:00
parent 4cbaa49e4a
commit d63b77cca4
5 changed files with 99 additions and 17 deletions
+30 -15
View File
@@ -1,23 +1,38 @@
import styles from "./RadioButton.module.scss";
import { useState } from "react";
import { useContext, useState } from "react";
import { RadioButtonGroupContext } from "../group/RadioButtonGroup";
interface RadioButtonProps {
disabled?: boolean;
value?: string;
onClick: React.HTMLAttributes<HTMLInputElement>["onChange"];
label: string;
checked?: boolean;
disabled?: boolean;
value: string;
onClick?: React.HTMLAttributes<HTMLInputElement>["onChange"];
label: string;
checked?: boolean;
}
const RadioButton: React.FC<RadioButtonProps> = ({ onClick, checked, disabled, label, value }) => {
return (
<>
<label className={styles.containerLabel}>
<input className={styles.radioButton} type="radio" value={value} checked={checked} disabled={disabled} onClick={onClick} />
{label}
</label>
</>
)
}
const parentGroupContext = useContext(RadioButtonGroupContext);
const localOnClick: React.FormEventHandler<HTMLInputElement> = (event) => {
onClick?.(event);
parentGroupContext?.[2](value);
}
return (
<>
<label className={styles.containerLabel}>
<input
className={styles.radioButton}
type="radio"
value={value}
checked={parentGroupContext ? parentGroupContext[0] === value : checked}
disabled={parentGroupContext?.[1] ?? disabled}
onClick={localOnClick}
/>
{label}
</label>
</>
);
};
export default RadioButton;
@@ -0,0 +1,38 @@
import React, { useState } from "react";
type RadioButtonGroupContextType = [value: string | undefined, disabled: boolean, dispatch: (value: string) => unknown];
export const RadioButtonGroupContext = React.createContext<RadioButtonGroupContextType>(null!);
interface RadioButtonGroupProps {
disabled?: boolean;
value?: string; // For controlled groups
defaultValue?: string; // For uncontrolled group
onSelection?: (value: string) => unknown;
children: React.ReactNode;
}
const RadioButtonGroup: React.FC<RadioButtonGroupProps> = ({
defaultValue,
disabled,
onSelection,
value,
children,
}) => {
const [controlledValue, setControlledValue] = useState(defaultValue);
const dispatcher = (value: string) => {
setControlledValue(value);
onSelection?.(value);
};
return (
<div>
<RadioButtonGroupContext.Provider value={[value ?? controlledValue, disabled ?? false, dispatcher]}>
{children}
</RadioButtonGroupContext.Provider>
</div>
);
};
export default RadioButtonGroup;
+6 -2
View File
@@ -4,7 +4,11 @@ import { ComponentStory, ComponentMeta } from "@storybook/react";
import RadioButton from "../components/radio/button/RadioButton";
export default { title: "Radio button", component: RadioButton } as ComponentMeta<typeof RadioButton>;
export default {
title: "Radio button",
component: RadioButton,
argTypes: { onClick: { action: "click" } },
} as ComponentMeta<typeof RadioButton>;
const Template: ComponentStory<typeof RadioButton> = (args) => <RadioButton {...args} />;
@@ -14,5 +18,5 @@ DefaultInput.args = {
value: "test",
label: "test",
checked: false,
disabled: false
disabled: false,
};
+25
View File
@@ -0,0 +1,25 @@
import React from "react";
import { ComponentStory, ComponentMeta } from "@storybook/react";
import RadioButtonGroup from "../components/radio/group/RadioButtonGroup";
import RadioButton from "../components/radio/button/RadioButton";
export default {
title: "Radio button group",
component: RadioButtonGroup,
argTypes: { onSelection: { action: "select" }, value: {type: "string"} },
} as ComponentMeta<typeof RadioButtonGroup>;
const Template: ComponentStory<typeof RadioButtonGroup> = (args) => <RadioButtonGroup {...args}>
<RadioButton value="one" label="First option" />
<RadioButton value="two" label="Second option" />
</RadioButtonGroup>;
export const DefaultInput = Template.bind({});
DefaultInput.args = {
value: undefined,
defaultValue: "two",
disabled: false,
}