Skip to content

Commit f9ac43b

Browse files
committed
refactor: cleanup and fix colors
* remove extra theme tokens (onSurfaceDisabled, backdrop replaced with scrim) * remove custom rippleColor from components * fix component colors as per MD guidelines
1 parent 4833a0d commit f9ac43b

87 files changed

Lines changed: 1809 additions & 2561 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

example/src/Examples/FABExample.tsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,6 @@ const FABExample = () => {
9595
onPress={() => {}}
9696
visible={visible}
9797
/>
98-
<FAB
99-
icon="cancel"
100-
label="Disabled FAB"
101-
style={styles.fab}
102-
onPress={() => {}}
103-
visible={visible}
104-
disabled
105-
/>
10698
<FAB
10799
icon="format-letter-case"
108100
label="Mixed case"

src/components/Appbar/AppbarAction.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import * as React from 'react';
2-
import type {
3-
Animated,
4-
ColorValue,
5-
StyleProp,
6-
View,
7-
ViewStyle,
8-
} from 'react-native';
2+
import type { Animated, StyleProp, View, ViewStyle } from 'react-native';
93

104
import type { ThemeProp } from 'src/types';
115

@@ -19,10 +13,6 @@ export type Props = React.ComponentPropsWithoutRef<typeof IconButton> & {
1913
* Custom color for action icon.
2014
*/
2115
color?: string;
22-
/**
23-
* Color of the ripple effect.
24-
*/
25-
rippleColor?: ColorValue;
2616
/**
2717
* Name of the icon to show.
2818
*/
@@ -90,7 +80,6 @@ const AppbarAction = forwardRef<View, Props>(
9080
accessibilityLabel,
9181
isLeading,
9282
theme: themeOverrides,
93-
rippleColor,
9483
...rest
9584
}: Props,
9685
ref
@@ -113,7 +102,6 @@ const AppbarAction = forwardRef<View, Props>(
113102
accessibilityLabel={accessibilityLabel}
114103
animated
115104
ref={ref}
116-
rippleColor={rippleColor}
117105
{...rest}
118106
/>
119107
);

src/components/BottomNavigation/BottomNavigationBar.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -565,12 +565,15 @@ const BottomNavigationBar = <Route extends BaseRoute>({
565565
// We render the active icon and label on top of inactive ones and cross-fade them on change.
566566
// This trick gives the illusion that we are animating between active and inactive colors.
567567
// This is to ensure that we can use native driver, as colors cannot be animated with native driver.
568-
const activeOpacity = focused ? 1 : 0;
569-
const inactiveOpacity = shifting
570-
? active.interpolate({
571-
inputRange: [0, 1],
572-
outputRange: [1, 0],
573-
})
568+
const animatedActiveOpacity = active;
569+
const animatedInactiveOpacity = active.interpolate({
570+
inputRange: [0, 1],
571+
outputRange: [1, 0],
572+
});
573+
574+
const staticActiveOpacity = focused ? 1 : 0;
575+
const staticInactiveOpacity = shifting
576+
? animatedInactiveOpacity
574577
: focused
575578
? 0
576579
: 1;
@@ -662,8 +665,8 @@ const BottomNavigationBar = <Route extends BaseRoute>({
662665
styles.iconWrapper,
663666
{
664667
opacity: isShiftingOrLabeled
665-
? activeOpacity
666-
: activeOpacity,
668+
? animatedActiveOpacity
669+
: staticActiveOpacity,
667670
},
668671
]}
669672
>
@@ -686,8 +689,8 @@ const BottomNavigationBar = <Route extends BaseRoute>({
686689
styles.iconWrapper,
687690
{
688691
opacity: isShiftingOrLabeled
689-
? inactiveOpacity
690-
: inactiveOpacity,
692+
? animatedInactiveOpacity
693+
: staticInactiveOpacity,
691694
},
692695
]}
693696
>
@@ -726,8 +729,8 @@ const BottomNavigationBar = <Route extends BaseRoute>({
726729
styles.labelWrapper,
727730
{
728731
opacity: isShiftingOrLabeled
729-
? activeOpacity
730-
: activeOpacity,
732+
? animatedActiveOpacity
733+
: staticActiveOpacity,
731734
},
732735
]}
733736
>
@@ -759,8 +762,8 @@ const BottomNavigationBar = <Route extends BaseRoute>({
759762
styles.labelWrapper,
760763
{
761764
opacity: isShiftingOrLabeled
762-
? inactiveOpacity
763-
: inactiveOpacity,
765+
? animatedInactiveOpacity
766+
: staticInactiveOpacity,
764767
},
765768
]}
766769
>

src/components/Button/Button.tsx

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as React from 'react';
22
import {
33
AccessibilityRole,
44
Animated,
5-
ColorValue,
65
GestureResponderEvent,
76
Platform,
87
PressableAndroidRippleConfig,
@@ -13,8 +12,6 @@ import {
1312
ViewStyle,
1413
} from 'react-native';
1514

16-
import color from 'color';
17-
1815
import {
1916
ButtonMode,
2017
getButtonColors,
@@ -66,10 +63,6 @@ export type Props = $Omit<React.ComponentProps<typeof Surface>, 'mode'> & {
6663
* Custom button's text color.
6764
*/
6865
textColor?: string;
69-
/**
70-
* Color of the ripple effect.
71-
*/
72-
rippleColor?: ColorValue;
7366
/**
7467
* Whether to show a loading indicator.
7568
*/
@@ -186,7 +179,6 @@ const Button = (
186179
icon,
187180
buttonColor: customButtonColor,
188181
textColor: customTextColor,
189-
rippleColor: customRippleColor,
190182
children,
191183
accessibilityLabel,
192184
accessibilityHint,
@@ -282,26 +274,29 @@ const Button = (
282274
const borderRadius = 5 * roundness;
283275
const iconSize = 18;
284276

285-
const { backgroundColor, borderColor, textColor, borderWidth } =
286-
getButtonColors({
287-
customButtonColor,
288-
customTextColor,
289-
theme,
290-
mode,
291-
disabled,
292-
dark,
293-
});
294-
295-
const rippleColor =
296-
customRippleColor || color(textColor).alpha(0.12).rgb().string();
277+
const {
278+
backgroundColor,
279+
borderColor,
280+
textColor,
281+
textOpacity,
282+
borderWidth,
283+
backgroundOpacity,
284+
} = getButtonColors({
285+
customButtonColor,
286+
customTextColor,
287+
theme,
288+
mode,
289+
disabled,
290+
dark,
291+
});
297292

298293
const touchableStyle = {
299294
...borderRadiusStyles,
300295
borderRadius: borderRadiusStyles.borderRadius ?? borderRadius,
301296
};
302297

303298
const buttonStyle = {
304-
backgroundColor,
299+
backgroundColor: backgroundOpacity < 1 ? 'transparent' : backgroundColor,
305300
borderColor,
306301
borderWidth,
307302
...touchableStyle,
@@ -348,6 +343,19 @@ const Button = (
348343
elevation={elevation}
349344
container
350345
>
346+
{backgroundOpacity < 1 && (
347+
<View
348+
pointerEvents="none"
349+
style={[
350+
StyleSheet.absoluteFill,
351+
{
352+
backgroundColor,
353+
opacity: backgroundOpacity,
354+
borderRadius: touchableStyle.borderRadius,
355+
},
356+
]}
357+
/>
358+
)}
351359
<TouchableRipple
352360
borderless
353361
background={background}
@@ -363,13 +371,12 @@ const Button = (
363371
accessible={accessible}
364372
hitSlop={hitSlop}
365373
disabled={disabled}
366-
rippleColor={rippleColor}
367374
style={getButtonTouchableRippleStyle(touchableStyle, borderWidth)}
368375
testID={testID}
369376
theme={theme}
370377
ref={touchableRef}
371378
>
372-
<View style={[styles.content, contentStyle]}>
379+
<View style={[styles.content, { opacity: textOpacity }, contentStyle]}>
373380
{icon && loading !== true ? (
374381
<View style={iconStyle} testID={`${testID}-icon-container`}>
375382
<Icon

src/components/Button/utils.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { type ViewStyle } from 'react-native';
22

3-
import color from 'color';
4-
53
import { black, white } from '../../styles/themes/baseColors';
4+
import { tokens } from '../../styles/themes/tokens';
65
import type { InternalTheme } from '../../types';
76
import { splitStyles } from '../../utils/splitStyles';
87

8+
const { stateOpacity } = tokens.md.ref;
9+
910
export type ButtonMode =
1011
| 'text'
1112
| 'outlined'
@@ -34,10 +35,6 @@ const isDark = ({
3435
return false;
3536
}
3637

37-
if (backgroundColor !== 'transparent') {
38-
return !color(backgroundColor).isLight();
39-
}
40-
4138
return false;
4239
};
4340

@@ -57,7 +54,7 @@ const getButtonBackgroundColor = ({
5754
if (isMode('outlined') || isMode('text')) {
5855
return 'transparent';
5956
}
60-
return theme.colors.surfaceDisabled;
57+
return theme.colors.onSurface;
6158
}
6259

6360
if (isMode('elevated')) {
@@ -92,7 +89,7 @@ const getButtonTextColor = ({
9289
}
9390

9491
if (disabled) {
95-
return theme.colors.onSurfaceDisabled;
92+
return theme.colors.onSurface;
9693
}
9794

9895
if (typeof dark === 'boolean') {
@@ -120,13 +117,9 @@ const getButtonTextColor = ({
120117
return theme.colors.primary;
121118
};
122119

123-
const getButtonBorderColor = ({ isMode, disabled, theme }: BaseProps) => {
124-
if (disabled && isMode('outlined')) {
125-
return theme.colors.surfaceDisabled;
126-
}
127-
120+
const getButtonBorderColor = ({ isMode, theme }: BaseProps) => {
128121
if (isMode('outlined')) {
129-
return theme.colors.outline;
122+
return theme.colors.outlineVariant;
130123
}
131124

132125
return 'transparent';
@@ -174,15 +167,24 @@ export const getButtonColors = ({
174167
dark,
175168
});
176169

177-
const borderColor = getButtonBorderColor({ isMode, theme, disabled });
170+
const borderColor = getButtonBorderColor({ isMode, theme });
178171

179172
const borderWidth = getButtonBorderWidth({ isMode, theme });
180173

174+
const textOpacity = disabled ? stateOpacity.disabled : stateOpacity.enabled;
175+
176+
const backgroundOpacity =
177+
disabled && !isMode('outlined') && !isMode('text')
178+
? stateOpacity.pressed
179+
: stateOpacity.enabled;
180+
181181
return {
182182
backgroundColor,
183183
borderColor,
184184
textColor,
185+
textOpacity,
185186
borderWidth,
187+
backgroundOpacity,
186188
};
187189
};
188190

src/components/Checkbox/CheckboxAndroid.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ const CheckboxAndroid = ({
9999
const checked = status === 'checked';
100100
const indeterminate = status === 'indeterminate';
101101

102-
const { rippleColor, selectionControlColor } =
102+
const { selectionControlColor, selectionControlOpacity } =
103103
getAndroidSelectionControlColor({
104104
theme,
105105
disabled,
@@ -123,7 +123,6 @@ const CheckboxAndroid = ({
123123
<TouchableRipple
124124
{...rest}
125125
borderless
126-
rippleColor={rippleColor}
127126
onPress={onPress}
128127
disabled={disabled}
129128
accessibilityRole="checkbox"
@@ -133,7 +132,12 @@ const CheckboxAndroid = ({
133132
testID={testID}
134133
theme={theme}
135134
>
136-
<Animated.View style={{ transform: [{ scale: scaleAnim }] }}>
135+
<Animated.View
136+
style={{
137+
transform: [{ scale: scaleAnim }],
138+
opacity: selectionControlOpacity,
139+
}}
140+
>
137141
<MaterialCommunityIcon
138142
allowFontScaling={false}
139143
name={icon}

src/components/Checkbox/CheckboxIOS.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const CheckboxIOS = ({
5353
const checked = status === 'checked';
5454
const indeterminate = status === 'indeterminate';
5555

56-
const { checkedColor, rippleColor } = getSelectionControlIOSColor({
56+
const { checkedColor, checkedColorOpacity } = getSelectionControlIOSColor({
5757
theme,
5858
disabled,
5959
customColor: rest.color,
@@ -66,7 +66,6 @@ const CheckboxIOS = ({
6666
<TouchableRipple
6767
{...rest}
6868
borderless
69-
rippleColor={rippleColor}
7069
onPress={onPress}
7170
disabled={disabled}
7271
accessibilityRole="checkbox"
@@ -76,7 +75,7 @@ const CheckboxIOS = ({
7675
testID={testID}
7776
theme={theme}
7877
>
79-
<View style={{ opacity }}>
78+
<View style={{ opacity: opacity * checkedColorOpacity }}>
8079
<MaterialCommunityIcon
8180
allowFontScaling={false}
8281
name={icon}

0 commit comments

Comments
 (0)