react-native-paper icon indicating copy to clipboard operation
react-native-paper copied to clipboard

fix: fixed `Chip` "shadow" and height issue

Open kamilkedzierski opened this issue 1 year ago • 1 comments

Motivation

image

There is an issue with the Chip component when a Chip with mode="outlined" is used next to one with mode="flat" (see screenshot). The Chip with mode="flat" displays a kind of "shadow" at the bottom.

This problem is caused by the Surface component, which splits styles provided via props into outerLayerViewStyles and innerLayerViewStyles. Specifically, it is caused by the backgroundColor, which has the same value in both outerLayerViewStyles and innerLayerViewStyles (see below, reference):

  const outerLayerViewStyles = {
        ...(isElevated && getStyleForShadowLayer(elevation, 0)),
        ...outerLayerStyles,
        ...borderRadiusStyles,
        backgroundColor: bgColor,
      };

  const innerLayerViewStyles = {
    ...(isElevated && getStyleForShadowLayer(elevation, 1)),
    ...filteredStyles,
    ...borderRadiusStyles,
    flex: flattenedStyles.height ? 1 : undefined,
    backgroundColor: bgColor,
  };

A Chip with mode="outlined" is 2dp larger in width and height than one with mode="flat" due to its borderWidth of 1dp. When both modes are placed next to each other, the outer View of the Surface component adjusts to fill the height difference, but the inner View does not. Since the background color for a disabled Chip uses RGBA (with opacity), the inner and outer background colors create overlapping layers, resulting in the visible "shadow" at the bottom.

Possible solutions

1. Adding flexGrow: 1 to the Surface used inside Chip component

Adding flexGrow: 1 would resolve the issue by allowing the inner View of the Surface to grow and match the height of the outer View. However, because outerLayerStylesProperties includes flexGrow, it won't be applied to the inner layer out of the box. To manage this, we could pass separate props like innerLayerStyles and outerLayerStyles. However, this approach might affect other components using Surface, making it a more complex solution.

2. Setting borderWidth:1 for both modes and within the flat mode setting the borderColor to transparent (implemented here)

IMO this is the least impactful solution. It ensures both modes have matching dimensions (width and height) and restricts the change to the Chip component itself.

Related issue

https://github.com/callstack/react-native-paper/issues/4457

Test plan

You can test it by changing ChipExample.tsx

 <View style={styles.container}>
      <Chip mode="outlined" selected={false}>
          Not selected, enabled
      </Chip>
      <Chip mode="flat" selected disabled>
          Selected, disabled
      </Chip>
 </View>

const styles = StyleSheet.create({
  container: {
    marginTop: 16,
    flexDirection: 'row',
    justifyContent: 'space-around',
  },
});

image

kamilkedzierski avatar Jul 24 '24 14:07 kamilkedzierski

Hey @kamilkedzierski, thank you for your pull request 🤗. The documentation from this branch can be viewed here.

callstack-bot avatar Jul 24 '24 14:07 callstack-bot