/
IconButtonToggleGroup.tsx
102 lines (90 loc) · 3.07 KB
/
IconButtonToggleGroup.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import * as React from 'react';
import styled from '@emotion/styled';
import {spacing, borderRadius} from '@workday/canvas-kit-react-core';
import IconButton, {IconButtonProps, iconButtonIdentifier} from './IconButton';
export interface IconButtonToggleGroupProps {
/**
* The IconButton children of the IconButtonToggleGroup (must be at least two).
*/
children: React.ReactElement<IconButtonProps>[];
/**
* The value or index of the IconButton that the IconButtonToggleGroup should be toggled on to. If a string is provided, the IconButton with the corresponding value will be selected. If a number is provided, the IconButton with the corresponding index will be selected.
* @default 0
*/
value?: string | number;
/**
* If true, render the IconButtonToggleGroup from right to left.
* @default false
*/
isRTL?: boolean;
/**
* The function called when a button in the IconButtonToggleGroup is selected. If the selected button has a value, that value will be passed to the callback function; otherwise, the index of the button will be passed.
*/
onChange?: (value: string | number) => void;
}
const Container = styled('div')({
[`.${iconButtonIdentifier}`]: {
borderRadius: borderRadius.zero,
borderWidth: '1px',
marginLeft: '-1px',
'&:first-child': {
borderTopLeftRadius: spacing.xxxs,
borderBottomLeftRadius: spacing.xxxs,
marginLeft: 0,
},
'&:last-child': {
borderTopRightRadius: spacing.xxxs,
borderBottomRightRadius: spacing.xxxs,
},
'&:focus': {
borderRadius: spacing.xxxs,
zIndex: 1,
animation: 'none', // reset focusRing animation
transition: 'all 120ms, border-radius 1ms',
},
},
});
export default class IconButtonToggleGroup extends React.Component<IconButtonToggleGroupProps> {
static defaultProps = {
value: 0,
};
render(): React.ReactNode {
const children = this.props.isRTL ? [...this.props.children].reverse() : this.props.children;
return <Container>{React.Children.map(children, this.renderChild)}</Container>;
}
private renderChild = (
child: React.ReactElement<IconButtonProps>,
index: number
): React.ReactNode => {
if (typeof child.type === typeof IconButton) {
const childProps = child.props;
const toggled =
typeof this.props.value === 'number'
? index === this.props.value
: childProps.value === this.props.value;
return React.cloneElement(child, {
toggled,
variant: IconButton.Variant.SquareFilled,
onClick: this.onButtonClick.bind(this, childProps.onClick, index),
});
}
return child;
};
private onButtonClick = (
existingOnClick: (e: React.SyntheticEvent) => void | undefined,
index: number,
event: React.MouseEvent<HTMLButtonElement>
): void => {
if (existingOnClick) {
existingOnClick(event);
}
const target = event.currentTarget;
if (target && this.props.onChange) {
if (target.value) {
this.props.onChange(target.value);
} else {
this.props.onChange(index);
}
}
};
}