From d63b77cca4975dfb552d594df451a8eb4dd47d97 Mon Sep 17 00:00:00 2001 From: Stephan <57194608+stephan418@users.noreply.github.com> Date: Mon, 13 Mar 2023 20:31:08 +0100 Subject: [PATCH] Add radio button groups --- src/components/radio/button/RadioButton.tsx | 45 ++++++++++++------- .../radio/group/RadioButtonGroup.module.scss | 0 .../radio/group/RadioButtonGroup.tsx | 38 ++++++++++++++++ src/stories/RadioButton.stories.tsx | 8 +++- src/stories/RadioButtonGroup.stories.tsx | 25 +++++++++++ 5 files changed, 99 insertions(+), 17 deletions(-) create mode 100644 src/components/radio/group/RadioButtonGroup.module.scss create mode 100644 src/components/radio/group/RadioButtonGroup.tsx create mode 100644 src/stories/RadioButtonGroup.stories.tsx diff --git a/src/components/radio/button/RadioButton.tsx b/src/components/radio/button/RadioButton.tsx index d0ccc73..6e7c4a7 100644 --- a/src/components/radio/button/RadioButton.tsx +++ b/src/components/radio/button/RadioButton.tsx @@ -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["onChange"]; - label: string; - checked?: boolean; + disabled?: boolean; + value: string; + onClick?: React.HTMLAttributes["onChange"]; + label: string; + checked?: boolean; } const RadioButton: React.FC = ({ onClick, checked, disabled, label, value }) => { - return ( - <> - - - ) -} + const parentGroupContext = useContext(RadioButtonGroupContext); + + const localOnClick: React.FormEventHandler = (event) => { + onClick?.(event); + parentGroupContext?.[2](value); + } + + return ( + <> + + + ); +}; export default RadioButton; diff --git a/src/components/radio/group/RadioButtonGroup.module.scss b/src/components/radio/group/RadioButtonGroup.module.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/components/radio/group/RadioButtonGroup.tsx b/src/components/radio/group/RadioButtonGroup.tsx new file mode 100644 index 0000000..a2e084d --- /dev/null +++ b/src/components/radio/group/RadioButtonGroup.tsx @@ -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(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 = ({ + defaultValue, + disabled, + onSelection, + value, + children, +}) => { + const [controlledValue, setControlledValue] = useState(defaultValue); + + const dispatcher = (value: string) => { + setControlledValue(value); + onSelection?.(value); + }; + + return ( +
+ + {children} + +
+ ); +}; + +export default RadioButtonGroup; diff --git a/src/stories/RadioButton.stories.tsx b/src/stories/RadioButton.stories.tsx index 9aca443..7555bd0 100644 --- a/src/stories/RadioButton.stories.tsx +++ b/src/stories/RadioButton.stories.tsx @@ -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; +export default { + title: "Radio button", + component: RadioButton, + argTypes: { onClick: { action: "click" } }, +} as ComponentMeta; const Template: ComponentStory = (args) => ; @@ -14,5 +18,5 @@ DefaultInput.args = { value: "test", label: "test", checked: false, - disabled: false + disabled: false, }; diff --git a/src/stories/RadioButtonGroup.stories.tsx b/src/stories/RadioButtonGroup.stories.tsx new file mode 100644 index 0000000..6de9179 --- /dev/null +++ b/src/stories/RadioButtonGroup.stories.tsx @@ -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; + +const Template: ComponentStory = (args) => + + +; + +export const DefaultInput = Template.bind({}); + +DefaultInput.args = { + value: undefined, + defaultValue: "two", + disabled: false, +}