Skip to content

Instantly share code, notes, and snippets.

@hemantasapkota
Created June 6, 2024 22:37
Show Gist options
  • Select an option

  • Save hemantasapkota/8f81272aa70f6b092816db5403140cec to your computer and use it in GitHub Desktop.

Select an option

Save hemantasapkota/8f81272aa70f6b092816db5403140cec to your computer and use it in GitHub Desktop.

Revisions

  1. hemantasapkota created this gist Jun 6, 2024.
    90 changes: 90 additions & 0 deletions ReactNativeAccordion.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    import {LucideChevronDown, LucideChevronUp} from 'lucide-react-native';
    import React, {useCallback, useImperativeHandle, useState } from 'react';
    import {
    StyleSheet,
    Text,
    View,
    Animated,
    LayoutAnimation,
    Platform,
    UIManager,
    TouchableWithoutFeedback,
    } from 'react-native';

    if (
    Platform.OS === 'android' &&
    UIManager.setLayoutAnimationEnabledExperimental
    ) {
    UIManager.setLayoutAnimationEnabledExperimental(true);
    }

    type Props = {
    title: string;
    children: React.ReactNode;
    };

    export const Accordion = React.forwardRef((props: Props, ref) => {
    const {title, children} = props;
    const [isOpen, setIsOpen] = useState(false);

    const toggleOpen = useCallback(() => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    setIsOpen(!isOpen);
    }, [isOpen]);

    useImperativeHandle(
    ref,
    () => ({
    open: () => {
    if (isOpen) {
    return;
    }
    return toggleOpen();
    },
    }),
    [toggleOpen, isOpen],
    );

    return (
    <View style={styles.accordionSection}>
    <TouchableWithoutFeedback
    onPress={toggleOpen}
    accessibilityRole="button"
    accessibilityLabel="Toggle Accordion">
    <View
    style={[
    styles.accordionTitle,
    {flexDirection: 'row', justifyContent: 'space-between'},
    ]}>
    <Text style={styles.accordionHeader}>{title}</Text>
    {isOpen ? (
    <LucideChevronUp color="black" />
    ) : (
    <LucideChevronDown color="black" />
    )}
    </View>
    </TouchableWithoutFeedback>
    <Animated.View style={[styles.accordionContent]}>
    {isOpen && <View>{children}</View>}
    </Animated.View>
    </View>
    );
    });

    const styles = StyleSheet.create({
    accordionSection: {
    marginBottom: 16,
    },
    accordionTitle: {
    padding: 10,
    backgroundColor: '#f0f0f0',
    },
    accordionContent: {
    overflow: 'hidden',
    backgroundColor: '#E0E0E0',
    },
    accordionHeader: {
    fontSize: 20,
    fontWeight: 'bold',
    },
    });