mirror of
https://github.com/detleph/components.git
synced 2026-09-04 08:36:03 +02:00
Add radio button groups
This commit is contained in:
@@ -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;
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
Reference in New Issue
Block a user