Skip to content

Commit 9165581

Browse files
committed
feat(checkbox): reimplement checkbox
1 parent 6dcc3f6 commit 9165581

7 files changed

Lines changed: 1779 additions & 929 deletions

File tree

src/components/Checkbox/Checkbox.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import { Checkbox } from '.';
1919
isChecked={on}
2020
isDisabled={false}
2121
isInteractive={true}
22-
checkedIcon={null}
2322
onChange={toggle}
23+
size="small"
2424
getStyles={(props, theme) => ({
2525
checkboxStyle: {},
2626
checkboxFocusBackgroundColor: '',
2727
})}
28-
position="right"
28+
labelPosition="right" // or left
2929
label="Label"
3030
/>
3131
)}
Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,38 @@
1-
import { ViewStyle } from 'react-native';
1+
import { TextStyle, ViewStyle } from 'react-native';
22

3-
import { Theme } from '../../theme/ThemeInterface';
4-
import { CheckboxShape } from './Checkbox';
3+
import { ControlSize, Theme } from '../../theme/ThemeInterface';
4+
import { CheckboxLabelPosition, CheckboxShape } from './Checkbox';
55

66
export interface ShapeStyle {
77
circle: ViewStyle;
88
square: ViewStyle;
99
}
1010

1111
export interface CheckboxVariables {
12-
base: ViewStyle;
1312
disabled: ViewStyle;
1413
checked: ViewStyle;
1514
checkedFocus: ViewStyle;
1615
uncheckedFocus: ViewStyle;
1716
shape: ShapeStyle;
1817
}
1918

20-
export const getCheckboxVariables = (theme: Theme): CheckboxVariables => {
21-
return {
22-
base: {
23-
backgroundColor: theme.colors.background.content,
24-
borderColor: theme.colors.border.default,
25-
borderWidth: 1,
26-
height: 32,
27-
width: 32,
28-
},
29-
checked: {
30-
backgroundColor: theme.colors.background.primaryDefault,
31-
borderColor: 'transparent',
32-
},
33-
checkedFocus: {
34-
backgroundColor: theme.colors.background.primaryDark,
35-
},
36-
disabled: {
37-
backgroundColor: theme.colors.background.greyDark,
38-
borderColor: theme.colors.border.default,
39-
},
40-
shape: {
41-
circle: {
42-
borderRadius: 999,
43-
},
44-
square: {
45-
borderRadius: theme.controlBorderRadius.small,
46-
},
47-
},
48-
uncheckedFocus: {
49-
backgroundColor: theme.colors.background.greyLight,
50-
},
51-
};
52-
};
53-
5419
export interface CheckboxStylesProps {
5520
isChecked: boolean;
5621
isDisabled: boolean;
5722
shape: CheckboxShape;
23+
labelPosition: CheckboxLabelPosition;
24+
hasLabel: boolean;
25+
checkColor: string;
26+
size: ControlSize;
5827
}
5928

6029
export interface CheckboxStyles {
30+
touchableStyle: ViewStyle;
31+
outerWrapperStyle: ViewStyle;
6132
checkboxStyle: ViewStyle;
62-
checkboxFocusBackgroundColor?: string;
33+
textStyle: TextStyle;
34+
iconColor: string;
35+
checkboxFocusBackgroundColor: string;
6336
}
6437

6538
export type GetCheckboxStyles = (
@@ -68,20 +41,57 @@ export type GetCheckboxStyles = (
6841
) => CheckboxStyles;
6942

7043
export const getCheckboxStyles: GetCheckboxStyles = (
71-
{ isChecked, isDisabled, shape },
44+
{ isChecked, isDisabled, shape, hasLabel, labelPosition, checkColor, size },
7245
theme,
7346
) => {
74-
const checkboxVariables = getCheckboxVariables(theme);
47+
const sizeValue = theme.controlHeights[size];
7548

7649
return {
7750
checkboxFocusBackgroundColor: isChecked
78-
? checkboxVariables.checkedFocus.backgroundColor
79-
: checkboxVariables.uncheckedFocus.backgroundColor,
51+
? theme.colors.background.primaryDark
52+
: theme.colors.background.greyLight,
53+
8054
checkboxStyle: {
81-
...checkboxVariables.base,
82-
...(isChecked ? checkboxVariables.checked : {}),
83-
...(isDisabled ? checkboxVariables.disabled : {}),
84-
...checkboxVariables.shape[shape],
55+
alignItems: 'center',
56+
backgroundColor: theme.colors.background.content,
57+
borderColor: theme.colors.border.default,
58+
borderWidth: 1,
59+
height: sizeValue,
60+
justifyContent: 'center',
61+
width: sizeValue,
62+
...(hasLabel
63+
? labelPosition === 'right'
64+
? { marginRight: 8 }
65+
: { marginLeft: 8 }
66+
: {}),
67+
...(isChecked
68+
? {
69+
backgroundColor: theme.colors.background.primaryDefault,
70+
borderColor: 'transparent',
71+
}
72+
: {}),
73+
...(isDisabled
74+
? {
75+
backgroundColor: theme.colors.background.greyDark,
76+
borderColor: theme.colors.border.default,
77+
}
78+
: {}),
79+
...{
80+
circle: {
81+
borderRadius: 999,
82+
},
83+
square: {
84+
borderRadius: theme.controlBorderRadius.small,
85+
},
86+
}[shape],
87+
},
88+
iconColor: checkColor || theme.colors.text.white,
89+
90+
outerWrapperStyle: {
91+
alignItems: 'center',
92+
flexDirection: 'row',
8593
},
94+
textStyle: {},
95+
touchableStyle: {},
8696
};
8797
};

src/components/Checkbox/Checkbox.tsx

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,53 +8,76 @@ import {
88
import { DeepPartial } from 'ts-essentials';
99

1010
import { Icon } from '../../icons';
11-
import { useTheme } from '../../theme';
11+
import { ControlSize, useTheme } from '../../theme';
1212
import { mergeStyles, ReplaceReturnType } from '../../utils/mergeStyles';
13+
import { Text } from '../Typography';
1314
import {
1415
CheckboxStyles,
1516
GetCheckboxStyles,
1617
getCheckboxStyles,
1718
} from './Checkbox.styles';
1819

1920
export type CheckboxShape = 'circle' | 'square';
21+
export type CheckboxLabelPosition = 'left' | 'right';
2022

2123
export interface CheckboxProps extends AccessibilityProps {
2224
isChecked?: boolean;
2325
isDisabled?: boolean;
2426
/** Sometimes we just want the display of the checkbox */
2527
isInteractive?: boolean;
26-
checkedIcon?: React.ReactNode;
2728
/** @default square */
2829
shape?: CheckboxShape;
2930
onChange?: (e: GestureResponderEvent) => void | undefined;
3031
getStyles?: ReplaceReturnType<GetCheckboxStyles, DeepPartial<CheckboxStyles>>;
3132
testID?: string;
33+
checkColor?: string;
34+
label?: string;
35+
size?: ControlSize;
36+
labelPosition?: 'left' | 'right';
3237
}
3338

3439
export const Checkbox = (props: CheckboxProps) => {
3540
const {
3641
isChecked = false,
3742
isDisabled = false,
3843
isInteractive = true,
39-
checkedIcon,
4044
onChange = () => null,
4145
shape = 'square',
46+
labelPosition = 'right',
47+
size = 'small',
48+
label,
49+
checkColor,
4250
getStyles,
4351
testID,
4452
...accessibilityProps
4553
} = props;
4654

4755
const theme = useTheme();
4856

49-
const { checkboxStyle, checkboxFocusBackgroundColor } = mergeStyles(
50-
getCheckboxStyles,
51-
getStyles,
52-
)({ isChecked, isDisabled, shape }, theme);
57+
const {
58+
touchableStyle,
59+
outerWrapperStyle,
60+
checkboxStyle,
61+
textStyle,
62+
iconColor,
63+
checkboxFocusBackgroundColor,
64+
} = mergeStyles(getCheckboxStyles, getStyles)(
65+
{
66+
checkColor,
67+
hasLabel: !!label,
68+
isChecked,
69+
isDisabled,
70+
labelPosition,
71+
shape,
72+
size,
73+
},
74+
theme,
75+
);
5376

5477
return (
5578
<TouchableHighlight
56-
accessible
57-
style={checkboxStyle}
79+
accessible={isInteractive}
80+
style={touchableStyle}
5881
underlayColor={checkboxFocusBackgroundColor}
5982
{...(isInteractive
6083
? {
@@ -67,19 +90,18 @@ export const Checkbox = (props: CheckboxProps) => {
6790
testID={testID}
6891
{...accessibilityProps}
6992
>
70-
<View
71-
style={{
72-
alignItems: 'center',
73-
display: 'flex',
74-
height: '100%',
75-
justifyContent: 'center',
76-
}}
77-
>
78-
{isChecked
79-
? checkedIcon || (
80-
<Icon name="check" size={20} color={theme.colors.text.white} />
81-
)
82-
: null}
93+
<View style={outerWrapperStyle}>
94+
{labelPosition === 'left' && (
95+
<Text getStyles={() => ({ textStyle })}>{label}</Text>
96+
)}
97+
98+
<View style={checkboxStyle}>
99+
{isChecked ? <Icon name="check" size={20} color={iconColor} /> : null}
100+
</View>
101+
102+
{labelPosition === 'right' && (
103+
<Text getStyles={() => ({ textStyle })}>{label}</Text>
104+
)}
83105
</View>
84106
</TouchableHighlight>
85107
);

src/components/Checkbox/LabeledCheckbox.tsx

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/components/Checkbox/index.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
export {
2-
LabeledCheckbox as Checkbox,
3-
LabeledCheckboxProps as CheckboxProps,
4-
} from './LabeledCheckbox';
1+
export { Checkbox, CheckboxProps } from './Checkbox';

src/theme/ThemeInterface.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ export interface ControlSizes {
142142
large: number;
143143
}
144144

145+
export type ControlSize = keyof ControlSizes;
146+
145147
export interface FillColorProps {
146148
backgroundColor: string;
147149
color: string;

0 commit comments

Comments
 (0)