Skip to content

Commit a5577c6

Browse files
authored
v5.2.4 (#613)
* Refactor ButtonGroup * v5.2.4
1 parent 9f7ed93 commit a5577c6

File tree

4 files changed

+58
-50
lines changed

4 files changed

+58
-50
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@netdata/netdata-ui",
3-
"version": "5.2.3",
3+
"version": "5.2.4",
44
"description": "netdata UI kit",
55
"main": "dist/index.js",
66
"module": "dist/es6/index.js",

src/components/button/buttonGroup.js

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import React, { Children, isValidElement, cloneElement, useCallback } from "react"
1+
import React, { Children, isValidElement, cloneElement } from "react"
22
import Flex from "@/components/templates/flex"
33
import { Button } from "./button"
44

5+
const noop = () => {}
6+
57
const getButtonGroupProps = (itemIndex, itemsLength) => {
68
const groupFirst = itemIndex == 0
79
const groupLast = itemIndex == itemsLength - 1
@@ -30,20 +32,34 @@ const Content = ({ children }) => {
3032
)
3133
}
3234

33-
const RadioButtons = ({ items, checked, buttonProps = {}, onChange }) => {
35+
const RadioButtons = ({ items, value, isMulti, buttonProps = {}, onChange }) => {
3436
return (
3537
<>
36-
{items.map(({ label, value, title }, index) => {
38+
{items.map((item, index) => {
3739
const buttonGroupProps = getButtonGroupProps(index, items.length)
38-
const isChecked = checked === value || (Array.isArray(checked) && checked.includes(value))
40+
const isSelected =
41+
value === item.value || (Array.isArray(value) && value.includes(item.value))
42+
43+
const onClick = () => {
44+
if (isMulti) {
45+
const newValue = Array.isArray(value)
46+
? value.includes(item.value)
47+
? value.filter(v => v !== item.value)
48+
: [...value, item.value]
49+
: [item.value]
50+
onChange(newValue)
51+
} else {
52+
onChange(item.value)
53+
}
54+
}
3955

4056
return (
4157
<Button
42-
key={value}
43-
label={label}
44-
onClick={() => onChange(value)}
45-
{...(title ? { title } : {})}
46-
{...(!isChecked ? { flavour: "hollow" } : {})}
58+
key={item.value}
59+
label={item.label}
60+
onClick={onClick}
61+
{...(item.title ? { title: item.title } : {})}
62+
{...(!isSelected ? { flavour: "hollow" } : {})}
4763
{...buttonGroupProps}
4864
{...buttonProps}
4965
/>
@@ -53,10 +69,24 @@ const RadioButtons = ({ items, checked, buttonProps = {}, onChange }) => {
5369
)
5470
}
5571

56-
export const ButtonGroup = ({ items, checked, onChange, children, buttonProps, ...props }) => (
72+
export const ButtonGroup = ({
73+
items,
74+
value,
75+
isMulti,
76+
onChange = noop,
77+
children,
78+
buttonProps,
79+
...props
80+
}) => (
5781
<Flex alignItems="center" {...props}>
5882
{items?.length ? (
59-
<RadioButtons items={items} checked={checked} onChange={onChange} buttonProps={buttonProps} />
83+
<RadioButtons
84+
items={items}
85+
value={value}
86+
isMulti={isMulti}
87+
onChange={onChange}
88+
buttonProps={buttonProps}
89+
/>
6090
) : (
6191
<Content>{children}</Content>
6292
)}
Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,17 @@
1-
import React, { useCallback, useState } from "react"
1+
import React, { useState } from "react"
22
import { ButtonGroup } from "."
33

44
export const RadioButtonGroup = args => {
5-
const [checked, setChecked] = useState(args.checked)
5+
const [value, setValue] = useState(args.value)
66

7-
return (
8-
<ButtonGroup
9-
items={args.items.map(item => ({ ...item }))}
10-
checked={checked}
11-
buttonProps={args}
12-
onChange={setChecked}
13-
/>
14-
)
7+
return <ButtonGroup items={args.items} value={value} buttonProps={args} onChange={setValue} />
158
}
169

1710
export const MultiButtonGroup = args => {
18-
const [checked, setChecked] = useState([args.checked])
19-
20-
const onChange = useCallback(
21-
value => {
22-
setChecked(prev => {
23-
if (prev.includes(value)) return prev.filter(v => v !== value)
24-
return [...prev, value]
25-
})
26-
},
27-
[setChecked]
28-
)
11+
const [value, setValue] = useState([args.value])
2912

3013
return (
31-
<ButtonGroup
32-
items={args.items.map(item => ({ ...item }))}
33-
checked={checked}
34-
buttonProps={args}
35-
onChange={onChange}
36-
/>
14+
<ButtonGroup items={args.items} value={value} isMulti buttonProps={args} onChange={setValue} />
3715
)
3816
}
3917

@@ -42,14 +20,14 @@ export default {
4220
tags: ["autodocs"],
4321
args: {
4422
items: [
45-
{ label: "One", value: 1 },
46-
{ label: "Two", value: 2 },
47-
{ label: "Three", value: 3 },
23+
{ label: "One", value: "1" },
24+
{ label: "Two", value: "2" },
25+
{ label: "Three", value: "3" },
4826
],
49-
checked: 1,
27+
value: "1",
5028
buttonProps: {},
5129
},
5230
argTypes: {
53-
checked: { control: "text" },
31+
value: { control: "text" },
5432
},
5533
}

src/components/button/buttonGroup.test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ describe("ButtonGroup", () => {
3030
{ label: "Option 3", value: "opt3" },
3131
]
3232

33-
renderWithProviders(<ButtonGroup items={items} checked="opt1" onChange={() => {}} />)
33+
renderWithProviders(<ButtonGroup items={items} value="opt1" onChange={() => {}} />)
3434

3535
expect(screen.getByText("Option 1")).toBeInTheDocument()
3636
expect(screen.getByText("Option 2")).toBeInTheDocument()
@@ -90,7 +90,7 @@ describe("ButtonGroup", () => {
9090
{ label: "Option 2", value: "opt2" },
9191
]
9292

93-
renderWithProviders(<ButtonGroup items={items} checked="opt1" onChange={handleChange} />)
93+
renderWithProviders(<ButtonGroup items={items} value="opt1" onChange={handleChange} />)
9494

9595
await user().click(screen.getByText("Option 2"))
9696
expect(handleChange).toHaveBeenCalledWith("opt2")
@@ -103,7 +103,7 @@ describe("ButtonGroup", () => {
103103
]
104104

105105
const { container } = renderWithProviders(
106-
<ButtonGroup items={items} checked="checked" onChange={() => {}} />
106+
<ButtonGroup items={items} value="checked" onChange={() => {}} />
107107
)
108108

109109
const buttons = container.querySelectorAll("button")
@@ -119,7 +119,7 @@ describe("ButtonGroup", () => {
119119
renderWithProviders(
120120
<ButtonGroup
121121
items={items}
122-
checked="btn1"
122+
value="btn1"
123123
onChange={() => {}}
124124
buttonProps={{ disabled: true }}
125125
/>
@@ -137,7 +137,7 @@ describe("ButtonGroup", () => {
137137
{ label: "Cancel", value: "cancel" },
138138
]
139139

140-
renderWithProviders(<ButtonGroup items={items} checked="save" onChange={() => {}} />)
140+
renderWithProviders(<ButtonGroup items={items} value="save" onChange={() => {}} />)
141141

142142
expect(screen.getByTitle("Save the document")).toBeInTheDocument()
143143
})
@@ -192,7 +192,7 @@ describe("ButtonGroup", () => {
192192

193193
it("handles empty items array", () => {
194194
const { container } = renderWithProviders(
195-
<ButtonGroup items={[]} checked={null} onChange={() => {}} />
195+
<ButtonGroup items={[]} value={null} onChange={() => {}} />
196196
)
197197

198198
expect(container.firstChild).toBeInTheDocument()

0 commit comments

Comments
 (0)