diff --git a/example/src/Examples/ChipExample.tsx b/example/src/Examples/ChipExample.tsx
index 20f0393153..d8a0c66d5e 100644
--- a/example/src/Examples/ChipExample.tsx
+++ b/example/src/Examples/ChipExample.tsx
@@ -249,10 +249,10 @@ const ChipExample = () => {
-
-
- {isV3 && (
- <>
+
+ {isV3 && (
+
+
{}}
@@ -265,7 +265,7 @@ const ChipExample = () => {
}
style={[styles.chip, styles.customBorderRadius]}
>
- Compact with custom border radius
+ Compact with custom border radius (outlined)
{
}
style={[styles.chip, styles.customBorderRadius]}
>
- Compact with custom border radius
+ Compact with custom border radius (flat)
- >
- )}
- {}}
- onLongPress={() =>
- setSnackbarProperties({ visible: true, text: '' })
- }
- style={styles.chip}
- >
- With onLongPress
-
- {}}
- style={[
- styles.chip,
- {
- backgroundColor: color(customColor).alpha(0.2).rgb().string(),
- },
- ]}
- selectedColor={customColor}
- >
- Flat selected chip with custom color
-
- {}}
- style={styles.chip}
- selectedColor={customColor}
- >
- Flat unselected chip with custom color
-
+
+
+ )}
+
+
+ {}}
+ style={[
+ styles.chip,
+ {
+ backgroundColor: color(customColor)
+ .alpha(0.2)
+ .rgb()
+ .string(),
+ },
+ ]}
+ >
+ Flat selected chip with custom background color
+
+ {}}
+ style={[
+ styles.chip,
+ {
+ backgroundColor: color(customColor)
+ .alpha(0.2)
+ .rgb()
+ .string(),
+ },
+ ]}
+ >
+ Flat unselected chip with custom background color
+
+ {}}
+ style={[
+ styles.chip,
+ {
+ backgroundColor: color(customColor)
+ .alpha(0.2)
+ .rgb()
+ .string(),
+ },
+ ]}
+ >
+ Flat disabled chip with custom background color
+
+
+
+
+
+ {}}
+ style={[styles.chip]}
+ selectedColor={customColor}
+ >
+ Flat selected chip with custom selected color
+
+ {}}
+ style={styles.chip}
+ selectedColor={customColor}
+ >
+ Flat unselected chip with custom selected color
+
+ {}}
+ style={[styles.chip]}
+ selectedColor={customColor}
+ >
+ Flat selected chip with custom selected color (no check)
+
+ {}}
+ style={styles.chip}
+ selectedColor={customColor}
+ >
+ Flat unselected chip with custom selected color (no check)
+
+ {}}
+ style={styles.chip}
+ selectedColor={customColor}
+ >
+ Flat disabled unselected chip with custom selected color
+
+ {}}
+ style={[
+ styles.chip,
+ {
+ backgroundColor: color(customColor)
+ .alpha(0.2)
+ .rgb()
+ .string(),
+ },
+ ]}
+ selectedColor={customColor}
+ >
+ Outlined selected chip with custom color
+
+ {}}
+ style={styles.chip}
+ selectedColor={customColor}
+ >
+ Outlined unselected chip with custom color
+
+
+
+
+
+ {}}
+ style={[styles.chip]}
+ selectedColor="rgba(255, 255, 255, 1)"
+ selectedBackgroundColor="rgba(0, 0, 0, 1)"
+ >
+ Flat selected chip with custom selected color & background color
+
+ {}}
+ style={[styles.chip]}
+ selectedColor="rgba(255, 255, 255, 1)"
+ selectedBackgroundColor="rgba(0, 0, 0, 1)"
+ >
+ Flat disabled chip with custom selected & background color
+
+ {}}
+ style={styles.chip}
+ textStyle={styles.tiny}
+ >
+ With custom size
+
+ {}}
+ style={styles.chip}
+ textStyle={styles.tiny}
+ >
+ With custom text
+
+ {}}
+ onClose={() =>
+ setSnackbarProperties({
+ visible: true,
+ text: 'Custom icon close button pressed',
+ })
+ }
+ closeIcon="arrow-down"
+ style={styles.chip}
+ closeIconAccessibilityLabel="Custom Close icon accessibility label"
+ >
+ With custom close icon
+
+ {}}
+ onLongPress={() =>
+ setSnackbarProperties({ visible: true, text: '' })
+ }
+ style={styles.chip}
+ >
+ With onLongPress
+
+
+
+
+
+ {}}
+ onClose={() =>
+ setSnackbarProperties({
+ visible: true,
+ text: 'Close button pressed',
+ })
+ }
+ style={styles.bigTextFlex}
+ textStyle={styles.bigTextStyle}
+ ellipsizeMode="middle"
+ >
+ With a very big text: React Native Paper is a high-quality,
+ standard-compliant Material Design library that has you covered
+ in all major use-cases.
+
+
{}}
- style={[
- styles.chip,
- {
- backgroundColor: color(customColor).alpha(0.2).rgb().string(),
- },
- ]}
- selectedColor={customColor}
- >
- Outlined selected chip with custom color
-
- {}}
- style={styles.chip}
- selectedColor={customColor}
- >
- Outlined unselected chip with custom color
-
- {}}
- style={styles.chip}
- textStyle={styles.tiny}
- >
- With custom size
-
- {}}
- onClose={() =>
- setSnackbarProperties({
- visible: true,
- text: 'Close button pressed',
- })
- }
- style={styles.bigTextFlex}
- textStyle={styles.bigTextStyle}
- ellipsizeMode="middle"
- >
- With a very big text: React Native Paper is a high-quality,
- standard-compliant Material Design library that has you covered in
- all major use-cases.
-
- {}}
- onClose={() =>
- setSnackbarProperties({
- visible: true,
- text: 'Custom icon close button pressed',
- })
- }
- closeIcon="arrow-down"
- style={styles.chip}
- closeIconAccessibilityLabel="Custom Close icon accessibility label"
+ style={styles.fullWidthChip}
>
- With custom close icon
+ Full width chip
- {}}
- style={styles.chip}
- textStyle={styles.tiny}
- >
- With custom text
-
-
- {}} style={styles.fullWidthChip}>
- Full width chip
-
+
, 'mode'> & {
selected?: boolean;
/**
* Whether to style the chip color as selected.
- * Note: With theme version 3 `selectedColor` doesn't apply to the `icon`.
+ * Note: With theme version 3 `selectedColor` doesn't apply to the `icon`. Only text color is affected.
* If you want specify custom color for the `icon`, render your own `Icon` component.
*/
selectedColor?: string;
+ /**
+ * Background color for the selected chip.
+ */
+ selectedBackgroundColor?: string;
/**
* @supported Available in v5.x with theme version 3
* Whether to display overlay on selected chip
@@ -139,6 +143,29 @@ export type Props = $Omit, 'mode'> & {
hitSlop?: TouchableRippleProps['hitSlop'];
/**
* @optional
+ * Theme object containing styling properties. The following theme properties are used:
+ *
+ * **V3 Theme:**
+ *
+ * - `colors.onSurfaceDisabled` - Text and icon color when disabled
+ * - `colors.onSurfaceVariant` - Text/icon color for outlined mode, disabled border color, overlay mixing
+ * - `colors.outline` - Border color for outlined mode (when not disabled/selected)
+ * - `colors.surface` - Background color for outlined mode
+ * - `colors.secondaryContainer` - Background color for flat mode
+ * - `colors.onSecondaryContainer` - Text/icon color for flat mode, overlay mixing
+ * - `colors.primary` - Icon color when not disabled (for custom icons)
+ *
+ * **V2 Theme:**
+ *
+ * - `colors.disabled` - Text and icon color when disabled
+ * - `colors.text` - Base text and icon color (with alpha applied)
+ * - `colors.surface` - Background color for outlined mode
+ * **Common:**
+ * - `roundness` - Used to calculate default border radius (V3: roundness * 2, V2: roundness * 4)
+ * - `animation.scale` - Used for elevation animation timing
+ * - `fonts.labelLarge` (V3) / `fonts.regular` (V2) - Text typography
+ * - `dark` - Determines color calculations for V2 theme
+ * - `isV3` - Determines which theme version logic to apply
*/
theme?: ThemeProp;
/**
@@ -201,6 +228,7 @@ const Chip = ({
theme: themeOverrides,
testID = 'chip',
selectedColor,
+ selectedBackgroundColor: customSelectedBackgroundColor,
rippleColor: customRippleColor,
showSelectedOverlay = false,
showSelectedCheck = true,
@@ -259,22 +287,18 @@ const Chip = ({
borderRadius = defaultBorderRadius,
} = (StyleSheet.flatten(style) || {}) as ViewStyle;
- const {
- borderColor,
- textColor,
- iconColor,
- rippleColor,
- selectedBackgroundColor,
- backgroundColor,
- } = getChipColors({
- isOutlined,
- theme,
- selectedColor,
- showSelectedOverlay,
- customBackgroundColor,
- disabled,
- customRippleColor,
- });
+ const { borderColor, textColor, iconColor, rippleColor, backgroundColor } =
+ getChipColors({
+ isOutlined,
+ theme,
+ selectedColor,
+ showSelectedOverlay,
+ customBackgroundColor,
+ disabled,
+ customRippleColor,
+ selected,
+ customSelectedBackgroundColor,
+ });
const accessibilityState: AccessibilityState = {
selected,
@@ -306,7 +330,7 @@ const Chip = ({
elevation: elevationStyle,
},
{
- backgroundColor: selected ? selectedBackgroundColor : backgroundColor,
+ backgroundColor,
borderColor,
borderRadius,
},
diff --git a/src/components/Chip/helpers.tsx b/src/components/Chip/helpers.tsx
index 47d0993c86..879d8ebc7c 100644
--- a/src/components/Chip/helpers.tsx
+++ b/src/components/Chip/helpers.tsx
@@ -13,6 +13,7 @@ type BaseProps = {
theme: InternalTheme;
isOutlined: boolean;
disabled?: boolean;
+ selected?: boolean;
};
const getBorderColor = ({
@@ -21,6 +22,7 @@ const getBorderColor = ({
disabled,
selectedColor,
backgroundColor,
+ selected,
}: BaseProps & { backgroundColor: string; selectedColor?: string }) => {
const isSelectedColor = selectedColor !== undefined;
@@ -34,7 +36,7 @@ const getBorderColor = ({
return color(theme.colors.onSurfaceVariant).alpha(0.12).rgb().string();
}
- if (isSelectedColor) {
+ if (isSelectedColor && selected) {
return color(selectedColor).alpha(0.29).rgb().string();
}
@@ -42,7 +44,7 @@ const getBorderColor = ({
}
if (isOutlined) {
- if (isSelectedColor) {
+ if (isSelectedColor && selected) {
return color(selectedColor).alpha(0.29).rgb().string();
}
@@ -61,6 +63,7 @@ const getTextColor = ({
isOutlined,
disabled,
selectedColor,
+ selected,
}: BaseProps & {
selectedColor?: string;
}) => {
@@ -70,7 +73,7 @@ const getTextColor = ({
return theme.colors.onSurfaceDisabled;
}
- if (isSelectedColor) {
+ if (isSelectedColor && selected) {
return selectedColor;
}
@@ -85,7 +88,7 @@ const getTextColor = ({
return theme.colors.disabled;
}
- if (isSelectedColor) {
+ if (isSelectedColor && selected) {
return color(selectedColor).alpha(0.87).rgb().string();
}
@@ -119,6 +122,7 @@ const getBackgroundColor = ({
theme,
isOutlined,
disabled,
+ selected,
customBackgroundColor,
}: BaseProps & {
customBackgroundColor?: ColorValue;
@@ -136,26 +140,37 @@ const getBackgroundColor = ({
}
}
- return getDefaultBackgroundColor({ theme, isOutlined });
+ return getDefaultBackgroundColor({ theme, isOutlined, selected });
};
const getSelectedBackgroundColor = ({
theme,
isOutlined,
disabled,
+ selected,
customBackgroundColor,
showSelectedOverlay,
+ customSelectedBackgroundColor,
}: BaseProps & {
customBackgroundColor?: ColorValue;
showSelectedOverlay?: boolean;
+ customSelectedBackgroundColor?: ColorValue;
}) => {
+ // If customSelectedBackgroundColor is provided, use it as-is without processing
+ if (typeof customSelectedBackgroundColor === 'string') {
+ return customSelectedBackgroundColor;
+ }
+
+ // Get the base background color (which may be custom or theme-based)
const backgroundColor = getBackgroundColor({
theme,
disabled,
isOutlined,
customBackgroundColor,
+ selected,
});
+ // Process the background color to get the selected background color
if (theme.isV3) {
if (isOutlined) {
if (showSelectedOverlay) {
@@ -202,6 +217,7 @@ const getIconColor = ({
isOutlined,
disabled,
selectedColor,
+ selected,
}: BaseProps & {
selectedColor?: string;
}) => {
@@ -211,7 +227,7 @@ const getIconColor = ({
return theme.colors.onSurfaceDisabled;
}
- if (isSelectedColor) {
+ if (isSelectedColor && selected) {
return selectedColor;
}
@@ -226,7 +242,7 @@ const getIconColor = ({
return theme.colors.disabled;
}
- if (isSelectedColor) {
+ if (isSelectedColor && selected) {
return color(selectedColor).alpha(0.54).rgb().string();
}
@@ -237,6 +253,7 @@ const getRippleColor = ({
theme,
isOutlined,
disabled,
+ selected,
selectedColor,
selectedBackgroundColor,
customRippleColor,
@@ -255,17 +272,18 @@ const getRippleColor = ({
disabled,
selectedColor,
isOutlined,
+ selected,
});
if (theme.isV3) {
- if (isSelectedColor) {
+ if (isSelectedColor && selected) {
return color(selectedColor).alpha(0.12).rgb().string();
}
return color(textColor).alpha(0.12).rgb().string();
}
- if (isSelectedColor) {
+ if (isSelectedColor && selected) {
return color(selectedColor).fade(0.5).rgb().string();
}
@@ -280,14 +298,18 @@ export const getChipColors = ({
customBackgroundColor,
disabled,
customRippleColor,
+ selected = false,
+ customSelectedBackgroundColor,
}: BaseProps & {
customBackgroundColor?: ColorValue;
disabled?: boolean;
showSelectedOverlay?: boolean;
selectedColor?: string;
customRippleColor?: ColorValue;
+ selected?: boolean;
+ customSelectedBackgroundColor?: ColorValue;
}) => {
- const baseChipColorProps = { theme, isOutlined, disabled };
+ const baseChipColorProps = { theme, isOutlined, disabled, selected };
const backgroundColor = getBackgroundColor({
...baseChipColorProps,
@@ -298,6 +320,7 @@ export const getChipColors = ({
...baseChipColorProps,
customBackgroundColor,
showSelectedOverlay,
+ customSelectedBackgroundColor,
});
return {
@@ -320,7 +343,6 @@ export const getChipColors = ({
selectedBackgroundColor,
customRippleColor,
}),
- backgroundColor,
- selectedBackgroundColor,
+ backgroundColor: selected ? selectedBackgroundColor : backgroundColor,
};
};
diff --git a/src/components/__tests__/Chip.test.tsx b/src/components/__tests__/Chip.test.tsx
index ca3055e35b..5000fb5cc3 100644
--- a/src/components/__tests__/Chip.test.tsx
+++ b/src/components/__tests__/Chip.test.tsx
@@ -152,29 +152,57 @@ describe('getChipColors - text color', () => {
});
});
- it('should return custom color, for theme version 3', () => {
+ it('should return custom color, for theme version 3, when selected', () => {
expect(
getChipColors({
theme: getTheme(),
selectedColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
textColor: 'purple',
});
});
- it('should return custom color, for theme version 2', () => {
+ it('should not return custom color, for theme version 3, when unselected', () => {
+ expect(
+ getChipColors({
+ theme: getTheme(),
+ selectedColor: 'purple',
+ isOutlined: false,
+ selected: false,
+ })
+ ).not.toMatchObject({
+ textColor: 'purple',
+ });
+ });
+
+ it('should return custom color, for theme version 2, when selected', () => {
expect(
getChipColors({
theme: getTheme(false, false),
selectedColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
textColor: color('purple').alpha(0.87).rgb().string(),
});
});
+
+ it('should not return custom color, for theme version 2, when unselected', () => {
+ expect(
+ getChipColors({
+ theme: getTheme(false, false),
+ selectedColor: 'purple',
+ isOutlined: false,
+ selected: false,
+ })
+ ).not.toMatchObject({
+ textColor: color('purple').alpha(0.87).rgb().string(),
+ });
+ });
});
describe('getChipColors - icon color', () => {
@@ -244,6 +272,7 @@ describe('getChipColors - icon color', () => {
theme: getTheme(),
selectedColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
iconColor: 'purple',
@@ -256,6 +285,7 @@ describe('getChipColors - icon color', () => {
theme: getTheme(false, false),
selectedColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
iconColor: color('purple').alpha(0.54).rgb().string(),
@@ -298,6 +328,7 @@ describe('getChipColors - ripple color', () => {
theme: getTheme(),
selectedColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
rippleColor: color('purple').alpha(0.12).rgb().string(),
@@ -310,6 +341,7 @@ describe('getChipColors - ripple color', () => {
theme: getTheme(false, false),
selectedColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
rippleColor: color('purple').fade(0.5).rgb().string(),
@@ -422,9 +454,10 @@ describe('getChipColor - selected background color', () => {
theme: getTheme(),
customBackgroundColor: 'purple',
isOutlined: true,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('purple')
+ backgroundColor: color('purple')
.mix(color(getTheme().colors.onSurfaceVariant), 0)
.rgb()
.string(),
@@ -437,9 +470,10 @@ describe('getChipColor - selected background color', () => {
theme: getTheme(),
customBackgroundColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('purple')
+ backgroundColor: color('purple')
.mix(color(getTheme().colors.onSecondaryContainer), 0)
.rgb()
.string(),
@@ -453,9 +487,10 @@ describe('getChipColor - selected background color', () => {
customBackgroundColor: 'purple',
showSelectedOverlay: true,
isOutlined: true,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('purple')
+ backgroundColor: color('purple')
.mix(color(getTheme().colors.onSurfaceVariant), 0.12)
.rgb()
.string(),
@@ -469,9 +504,10 @@ describe('getChipColor - selected background color', () => {
customBackgroundColor: 'purple',
showSelectedOverlay: true,
isOutlined: false,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('purple')
+ backgroundColor: color('purple')
.mix(color(getTheme().colors.onSecondaryContainer), 0.12)
.rgb()
.string(),
@@ -483,9 +519,10 @@ describe('getChipColor - selected background color', () => {
getChipColors({
theme: getTheme(),
isOutlined: true,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color(getTheme().colors.surface)
+ backgroundColor: color(getTheme().colors.surface)
.mix(color(getTheme().colors.onSurfaceVariant), 0)
.rgb()
.string(),
@@ -497,9 +534,10 @@ describe('getChipColor - selected background color', () => {
getChipColors({
theme: getTheme(),
isOutlined: false,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color(getTheme().colors.secondaryContainer)
+ backgroundColor: color(getTheme().colors.secondaryContainer)
.mix(color(getTheme().colors.onSecondaryContainer), 0)
.rgb()
.string(),
@@ -512,9 +550,10 @@ describe('getChipColor - selected background color', () => {
theme: getTheme(false, false),
customBackgroundColor: 'purple',
isOutlined: true,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('purple').darken(0.08).rgb().string(),
+ backgroundColor: color('purple').darken(0.08).rgb().string(),
});
});
@@ -524,9 +563,10 @@ describe('getChipColor - selected background color', () => {
theme: getTheme(false, false),
customBackgroundColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('purple').darken(0.2).rgb().string(),
+ backgroundColor: color('purple').darken(0.2).rgb().string(),
});
});
@@ -536,9 +576,10 @@ describe('getChipColor - selected background color', () => {
theme: getTheme(true, false),
customBackgroundColor: 'purple',
isOutlined: true,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('purple').lighten(0.2).rgb().string(),
+ backgroundColor: color('purple').lighten(0.2).rgb().string(),
});
});
@@ -548,9 +589,10 @@ describe('getChipColor - selected background color', () => {
theme: getTheme(true, false),
customBackgroundColor: 'purple',
isOutlined: false,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('purple').lighten(0.4).rgb().string(),
+ backgroundColor: color('purple').lighten(0.4).rgb().string(),
});
});
@@ -559,9 +601,10 @@ describe('getChipColor - selected background color', () => {
getChipColors({
theme: getTheme(false, false),
isOutlined: true,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color(getTheme(false, false).colors.surface)
+ backgroundColor: color(getTheme(false, false).colors.surface)
.darken(0.08)
.rgb()
.string(),
@@ -573,9 +616,10 @@ describe('getChipColor - selected background color', () => {
getChipColors({
theme: getTheme(false, false),
isOutlined: false,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('#ebebeb').darken(0.2).rgb().string(),
+ backgroundColor: color('#ebebeb').darken(0.2).rgb().string(),
});
});
@@ -584,9 +628,36 @@ describe('getChipColor - selected background color', () => {
getChipColors({
theme: getTheme(true, false),
isOutlined: false,
+ selected: true,
+ })
+ ).toMatchObject({
+ backgroundColor: color('#383838').lighten(0.4).rgb().string(),
+ });
+ });
+
+ it('should return custom selectedBackgroundColor when provided & chip is selected', () => {
+ expect(
+ getChipColors({
+ theme: getTheme(),
+ customSelectedBackgroundColor: 'red',
+ isOutlined: false,
+ selected: true,
+ })
+ ).toMatchObject({
+ backgroundColor: 'red',
+ });
+ });
+
+ it('should return custom selectedBackgroundColor for version 2 theme, when chip is selected', () => {
+ expect(
+ getChipColors({
+ theme: getTheme(false, false),
+ customSelectedBackgroundColor: 'red',
+ isOutlined: false,
+ selected: true,
})
).toMatchObject({
- selectedBackgroundColor: color('#383838').lighten(0.4).rgb().string(),
+ backgroundColor: 'red',
});
});
});
@@ -673,15 +744,31 @@ describe('getChipColor - border color', () => {
});
});
- it('should return custom color, for theme version 3', () => {
+ it('should return custom color, for theme version 3, when selected', () => {
expect(
getChipColors({
theme: getTheme(),
selectedColor: 'purple',
isOutlined: false,
+ selected: true,
+ })
+ ).toMatchObject({
+ borderColor: 'transparent',
+ textColor: 'purple',
+ });
+ });
+
+ it('should return theme color, for theme version 3, when unselected', () => {
+ expect(
+ getChipColors({
+ theme: getTheme(false, true),
+ selectedColor: 'purple',
+ isOutlined: false,
+ selected: false,
})
).toMatchObject({
borderColor: 'transparent',
+ textColor: getTheme(false, true).colors.onSecondaryContainer,
});
});
@@ -702,6 +789,7 @@ describe('getChipColor - border color', () => {
theme: getTheme(false, false),
selectedColor: 'purple',
isOutlined: true,
+ selected: true,
})
).toMatchObject({
borderColor: color('purple').alpha(0.29).rgb().string(),