Skip to content

Commit 290eb3a

Browse files
committed
fix: add dedicated background and radius props
1 parent b93dc8f commit 290eb3a

5 files changed

Lines changed: 62 additions & 98 deletions

File tree

‎docs/6.x/docs/guides/migration.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,15 @@ Some components now accept explicit `testID` props for their interactable elemen
130130
#### New props
131131

132132
- **`trailingIcon`** / **`onTrailingIconPress`** / **`trailingIconAccessibilityLabel`** add a trailing action (e.g. a dropdown) independent of the close button. `trailingIcon` takes precedence over `onClose`'s close icon when both are specified.
133+
- **`backgroundColor`** / **`borderRadius`** replace overriding the chip's background color or border radius through `style`. `style` no longer accepts `backgroundColor` or `borderRadius`.
134+
135+
```tsx
136+
// Before (v5)
137+
<Chip onPress={() => {}} style={{ backgroundColor: 'purple', borderRadius: 16 }}>Example Chip</Chip>
138+
139+
// After (v6)
140+
<Chip onPress={() => {}} backgroundColor="purple" borderRadius={16}>Example Chip</Chip>
141+
```
133142

134143
### Appbar
135144

‎example/src/Examples/ChipExample.tsx‎

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -173,19 +173,12 @@ const ChipExample = () => {
173173
icon="palette"
174174
onPress={() => {}}
175175
selectedColor={customColor}
176-
style={[
177-
styles.chip,
178-
{
179-
backgroundColor: color(customColor).alpha(0.2).rgb().string(),
180-
},
181-
]}
176+
backgroundColor={color(customColor).alpha(0.2).rgb().string()}
177+
style={styles.chip}
182178
>
183179
Custom color
184180
</Chip>
185-
<Chip
186-
onPress={() => {}}
187-
style={[styles.chip, styles.customBorderRadius]}
188-
>
181+
<Chip onPress={() => {}} borderRadius={16} style={styles.chip}>
189182
Rounded
190183
</Chip>
191184
<Chip onPress={() => {}} style={styles.fullWidthChip}>
@@ -220,9 +213,6 @@ const styles = StyleSheet.create({
220213
flex: 1,
221214
margin: 4,
222215
},
223-
customBorderRadius: {
224-
borderRadius: 16,
225-
},
226216
});
227217

228218
export default ChipExample;

‎src/components/Chip/Chip.tsx‎

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ import TouchableRipple from '../TouchableRipple/TouchableRipple';
3030
import type { Props as TouchableRippleProps } from '../TouchableRipple/TouchableRipple';
3131
import Text from '../Typography/Text';
3232

33-
// The trailing icon's ripple is a square that stretches flush to the chip's
34-
// top/bottom edges, so it's sized to match the chip's height rather than a
35-
// fixed value of its own.
33+
// The trailing icon's touch target is a square flush with the chip's
34+
// top/bottom edges (so its ripple/state layer stays circular per MD3),
35+
// sized to the chip height rather than a fixed value of its own.
3636
const TRAILING_ICON_AREA_SIZE = ChipTokens.containerHeight;
3737

38-
// The icon glyph is centered inside that (larger) ripple square, so its own
39-
// edge sits this far in from the ripple square's edge.
38+
// The icon glyph is centered inside that (larger) touch target, so its own
39+
// edge sits this far in from the touch target's edge.
4040
const TRAILING_ICON_INSET = (TRAILING_ICON_AREA_SIZE - ChipTokens.iconSize) / 2;
4141

4242
// Suppresses the browser's native focus outline so only our own focus
@@ -150,11 +150,23 @@ export type Props = Omit<ViewProps, 'style'> & {
150150
* Whether the chip should have elevation.
151151
*/
152152
elevated?: boolean;
153+
/**
154+
* Custom background color for the chip, overriding the default background for its mode/selected state.
155+
*/
156+
backgroundColor?: ColorValue;
157+
/**
158+
* Custom border radius for the chip.
159+
*/
160+
borderRadius?: number;
153161
/**
154162
* Style of chip's text.
155163
*/
156164
textStyle?: StyleProp<TextStyle>;
157-
style?: StyleProp<ViewStyle>;
165+
/**
166+
* Style of the chip's container. Background color and border radius should be specified via
167+
* the `backgroundColor`/`borderRadius` props instead.
168+
*/
169+
style?: StyleProp<Omit<ViewStyle, 'backgroundColor' | 'borderRadius'>>;
158170
/**
159171
* Sets additional distance outside of element in which a press can be detected.
160172
*/
@@ -235,6 +247,8 @@ const Chip = ({
235247
showSelectedCheck = true,
236248
ellipsizeMode,
237249
elevated = false,
250+
backgroundColor: customBackgroundColor,
251+
borderRadius: borderRadiusProp,
238252
maxFontSizeMultiplier,
239253
hitSlop,
240254
...rest
@@ -264,15 +278,8 @@ const Chip = ({
264278
[]
265279
);
266280

267-
const defaultBorderRadius = theme.shapes.corner.small;
268-
const {
269-
backgroundColor: customBackgroundColor,
270-
borderRadius = defaultBorderRadius,
271-
} = StyleSheet.flatten(style) || {};
272-
const focusRingBorderRadius =
273-
typeof borderRadius === 'number'
274-
? borderRadius + ChipTokens.focusIndicatorOffset
275-
: borderRadius;
281+
const borderRadius = borderRadiusProp ?? theme.shapes.corner.small;
282+
const focusRingBorderRadius = borderRadius + ChipTokens.focusIndicatorOffset;
276283

277284
const {
278285
borderColor,

‎src/components/Chip/utils.ts‎

Lines changed: 27 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { ColorValue, StyleProp, ViewStyle } from 'react-native';
22

33
import { ChipTokens } from './tokens';
4-
import type { InternalTheme } from '../../theme/types';
4+
import type { ColorRole, InternalTheme } from '../../theme/types';
55

66
export type ChipAvatarProps = {
77
style?: StyleProp<ViewStyle>;
@@ -80,60 +80,16 @@ const getBorderColor = ({
8080
return theme.colors[ChipTokens.outlineColor];
8181
};
8282

83-
const getLabelColor = ({
84-
theme,
85-
selected,
86-
disabled,
87-
selectedColor,
88-
}: BaseProps & {
89-
selectedColor?: ColorValue;
90-
}) => {
91-
if (disabled) {
92-
return theme.colors[ChipTokens.disabledColor];
93-
}
94-
95-
if (selectedColor !== undefined) {
96-
return selectedColor;
97-
}
98-
99-
if (selected) {
100-
return theme.colors[ChipTokens.selectedLabelColor];
101-
}
102-
103-
return theme.colors[ChipTokens.labelColor];
104-
};
105-
106-
const getLeadingIconColor = ({
107-
theme,
108-
selected,
109-
disabled,
110-
selectedColor,
111-
}: BaseProps & {
112-
selectedColor?: ColorValue;
113-
}) => {
114-
if (disabled) {
115-
return theme.colors[ChipTokens.disabledColor];
116-
}
117-
118-
if (selectedColor !== undefined) {
119-
return selectedColor;
120-
}
121-
122-
if (selected) {
123-
return theme.colors[ChipTokens.selectedIconColor];
124-
}
125-
126-
return theme.colors[ChipTokens.leadingIconColor];
127-
};
128-
129-
const getTrailingIconColor = ({
130-
theme,
131-
selected,
132-
disabled,
133-
selectedColor,
134-
}: BaseProps & {
135-
selectedColor?: ColorValue;
136-
}) => {
83+
const resolveColor = (
84+
{
85+
theme,
86+
disabled,
87+
selected,
88+
}: Pick<BaseProps, 'theme' | 'disabled' | 'selected'>,
89+
selectedColor: ColorValue | undefined,
90+
selectedToken: ColorRole,
91+
defaultToken: ColorRole
92+
): ColorValue => {
13793
if (disabled) {
13894
return theme.colors[ChipTokens.disabledColor];
13995
}
@@ -142,11 +98,7 @@ const getTrailingIconColor = ({
14298
return selectedColor;
14399
}
144100

145-
if (selected) {
146-
return theme.colors[ChipTokens.selectedTrailingIconColor];
147-
}
148-
149-
return theme.colors[ChipTokens.trailingIconColor];
101+
return theme.colors[selected ? selectedToken : defaultToken];
150102
};
151103

152104
export const getChipColors = ({
@@ -179,18 +131,24 @@ export const getChipColors = ({
179131
...baseChipColorProps,
180132
selectedColor,
181133
}),
182-
textColor: getLabelColor({
183-
...baseChipColorProps,
134+
textColor: resolveColor(
135+
baseChipColorProps,
184136
selectedColor,
185-
}),
186-
iconColor: getLeadingIconColor({
187-
...baseChipColorProps,
137+
ChipTokens.selectedLabelColor,
138+
ChipTokens.labelColor
139+
),
140+
iconColor: resolveColor(
141+
baseChipColorProps,
188142
selectedColor,
189-
}),
190-
trailingIconColor: getTrailingIconColor({
191-
...baseChipColorProps,
143+
ChipTokens.selectedIconColor,
144+
ChipTokens.leadingIconColor
145+
),
146+
trailingIconColor: resolveColor(
147+
baseChipColorProps,
192148
selectedColor,
193-
}),
149+
ChipTokens.selectedTrailingIconColor,
150+
ChipTokens.trailingIconColor
151+
),
194152
contentOpacity,
195153
backgroundColor: getContainerColor({
196154
...baseChipColorProps,

‎src/components/__tests__/Chip.test.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ it('overlays the close button on top of the chip so its ripple spans behind it',
231231

232232
it('clips the ripple to custom chip border radius', async () => {
233233
await render(
234-
<Chip onPress={() => {}} testID="rounded-chip" style={{ borderRadius: 16 }}>
234+
<Chip onPress={() => {}} testID="rounded-chip" borderRadius={16}>
235235
Rounded chip
236236
</Chip>
237237
);

0 commit comments

Comments
 (0)