oblador / react-native-collapsible

Animated collapsible component for React Native, good for accordions, toggles etc
MIT License
2.47k stars 452 forks source link

Arrow Next to Section Header #462

Open Richard-Cao226 opened 1 year ago

Richard-Cao226 commented 1 year ago

Is there a way to add a dropdown arrow next to each section header? Something like below...

image image
blwinters commented 1 year ago

I was able to achieve this with the following code. You can adjust the rotateZ amount according to your design.

export const CollapsibleSection = (props: CollapsibleSectionProps) => {
  const styles = useStyles()
  const [isCollapsed, setIsCollapsed] = useState(props.collapsedByDefault ?? false)

  const open = useSharedValue(isCollapsed)
  const progress = useDerivedValue(() => (open.value ? withTiming(1) : withTiming(0)))

  const onToggleCollapse = () => {
    setIsCollapsed(!isCollapsed)
    open.value = !open.value
  }

  return (
    <View>
      <RaisedBox style={styles.header} onPress={onToggleCollapse}>
        <Label color="$textMuted">{props.title}</Label>
        <Chevron progress={progress} />
      </RaisedBox>
      <Collapsible collapsed={isCollapsed}>
        {props.children}
      </Collapsible>
    </View>
  )
}

export interface ChevronProps {
  progress: Animated.SharedValue<number>
}

export const Chevron = ({ progress }: ChevronProps) => {
  const animatedStyle = useAnimatedStyle<AnimatedStyleProp<ViewStyle>>(() => {
    const value = Math.PI - progress.value * Math.PI
    return {
      transform: [{ rotateZ: `${value}rad` }],
    }
  })

  return (
    <Animated.View style={animatedStyle}>
      <Icon id="chevron-up" stroke="gray" />
    </Animated.View>
  )
}