Design

Creating a Reusable RadioGroup Component in React

Author

Pushpendra Singh

Date Published

Curving abstract shapes with an orange and blue gradient


When building modern web applications, reusable components help maintain consistency and reduce repetitive code. In this post, I’ll walk you through creating a reusable and customizable RadioGroup component in React, styled using SCSS.

Overview

The RadioGroup component allows you to render a group of radio buttons with labels and optional sub-labels. It is highly customizable with properties to control the direction, selected value, and more. Here's a breakdown of its features:

Customizable Layout: Supports vertical and horizontal alignment.

Dynamic Options: Generate radio buttons dynamically based on an array of options.

Accessibility: Includes proper aria-label attributes for accessibility.

Optional Sub-Labels: Provides additional information under labels if required.

Code

Below is the complete implementation of the RadioGroup component:

1import React from "react";
2import styles from "./RadioGroup.module.scss";
3
4const RadioGroup = ({ options, name, selectedValue, onChange, direction = 'vertical' }) => {
5 return (
6 <div className={`${styles.radioGroup} ${direction === 'horizontal' ? styles.horizontal : styles.vertical}`}>
7 {options.map(({ id, label, subLabel }) => (
8 <label key={id} className={`${styles.radio} ${subLabel ? styles.hassubLabel : ''}`} htmlFor={`radio-${id}`}>
9 <input
10 id={`radio-${id}`}
11 type="radio"
12 name={name}
13 value={id}
14 checked={selectedValue === id}
15 onChange={(e) => onChange(e.target.value)}
16 aria-label={label}
17 />
18 <i className={styles.checkboxIcon} aria-hidden="true"></i>
19 <div>
20 <p className={styles.label}>{label}</p>
21 {subLabel && (
22 <span className={styles.subLabel}>{subLabel}</span>
23 )}
24 </div>
25 </label>
26 ))}
27 </div>
28 );
29};
30
31export default RadioGroup;
32

Props Description

The RadioGroup component supports the following props to give you full control over its behavior and appearance:

options: An array of objects where each object represents a radio button. Each object should have:

-- id (required): A unique identifier for the radio button.

-- label (required): The display text for the radio button.

-- subLabel (optional): Additional text displayed under the label for more context.

name: A string used to group radio buttons together. This ensures only one radio button can be selected at a time within the group.

selectedValue: The currently selected radio button's id. This determines which radio button is marked as checked.

onChange: A callback function triggered when the user selects a radio button. It receives the id of the selected option as its parameter.
direction:
A string that specifies the layout direction of the radio buttons.

-- 'vertical' (default): Displays the radio buttons in a stacked layout.

-- 'horizontal': Displays the radio buttons side by side.

SCSS for styling

1.radioGroup {
2 display: flex;
3 gap: 12px;
4
5 &.vertical {
6 flex-direction: column;
7 }
8
9 &.horizontal {
10 flex-direction: row;
11 flex-wrap: wrap;
12 }
13}
14
15.radio {
16 display: flex;
17 align-items: center;
18 gap: 8px;
19 cursor: pointer;
20
21 &.hassubLabel {
22 align-items: flex-start;
23 }
24
25 input[type="radio"] {
26 width: 16px;
27 height: 16px;
28 accent-color: rgba(0, 102, 255, 1);
29 margin: 0;
30 padding: 0;
31 display: none;
32 }
33
34 .label {
35 font-size: 12px;
36 font-weight: 500;
37 color: #333;
38 }
39
40 .subLabel {
41 font-size: 10px;
42 color: #666;
43 font-weight: 500;
44 }
45
46 .checkboxIcon {
47 display: flex;
48 align-items: center;
49 justify-content: center;
50 width: 16px;
51 height: 16px;
52 border: 2px solid rgba(143, 145, 148, 1);
53 background-color: #fff;
54 border-radius: 16px;
55 }
56
57 input[type="radio"]:checked+i.checkboxIcon {
58 border-color: rgba(0, 102, 255, 1);
59 &::before {
60 display: block;
61 content: "";
62 width: 8px;
63 height: 8px;
64 background-color: rgba(0, 102, 255, 1);
65 border-radius: 8px;
66 }
67 }
68
69 input[type="radio"]:checked+i+div {
70 * {
71 color: rgba(0, 102, 255, 1);
72 }
73 }
74}
75

Here’s an example of how you can use the RadioGroup component:

1import React, { useState } from "react";
2import RadioGroup from "./RadioGroup";
3
4const options = [
5 { id: "1", label: "Option 1", subLabel: "This is option 1" },
6 { id: "2", label: "Option 2", subLabel: "This is option 2" },
7 { id: "3", label: "Option 3" },
8];
9
10const App = () => {
11 const [selectedValue, setSelectedValue] = useState("1");
12
13 const handleChange = (value) => {
14 setSelectedValue(value);
15 console.log("Selected Value:", value);
16 };
17
18 return (
19 <div>
20 <h1>Radio Group Example</h1>
21 <RadioGroup
22 options={options}
23 name="example"
24 selectedValue={selectedValue}
25 onChange={handleChange}
26 direction="horizontal"
27 />
28 </div>
29 );
30};
31
32export default App;
33

Conclusion

The RadioGroup component provides a flexible way to create radio button groups in your React applications. With customizable styles and layout options, it fits well into any design system. Feel free to tweak and extend this component as per your project needs!