I have an app which displays it's users and there is a small button (on the component that displays user information) that makes (the child component) a list with action buttons to pop up. The problem with it is when they are in a FlatList, the part of the pop-up list that is outside the parent component, turns translucent. Result

The expected result is something like this. Expected Result

How do I stop the child component from going partially translucent?

You can find a snack for this issue here.

My app consists of multiple strip components that display user info in a FlatList. Each StripUser component has a child component ListOptionMore, which is a pop up list of more options.

App structure

The code for the components are the following.

// ./components/ListOptionMore

import React, {useState, useEffect} from 'react';
import {FlatList, StyleSheet, Text, TouchableOpacity, View} from 'react-native';

const ListOptionMore = props => {
  const [showMore, setShowMore] = useState(props.showMore);

  useEffect(() => {
    setShowMore(props.showMore);
  }, [props.showMore]);

  const renderItem = ({item}) => (
    <TouchableOpacity
      activeOpacity={0.75}
      onPress={() => {
        setShowMore(false);
        props.changeShowMore(false);
        item?.action(item);
      }}
      style={styles.action}>
      <Text style={styles.actionName}>{item?.name}</Text>
    </TouchableOpacity>
  );

  if (showMore) {
    return (
      <View style={[styles.root, props.style]}>
        <FlatList
          data={props.more}
          renderItem={renderItem}
          keyExtractor={(item, index) => index}
          style={styles.list}
          ItemSeparatorComponent={() => (
            <View style={styles.itemSeparatorComponent} />
          )}
        />
      </View>
    );
  } else {
    return <View />;
  }
};

ListOptionMore.defaultProps = {
  style: {},
  showMore: false,
  changeShowMore: () => {},
  more: [
    {
      name: 'More Option',
      action: item => {
        console.log('Perform More action.');
      },
    },
  ],
};

const styles = StyleSheet.create({
  root: {
    position: 'absolute',
    right: 18,
    top: 30,
  },

  list: {
    backgroundColor: '#E5E5E5',
    borderWidth: 0.5,
    borderTopWidth: 0.2,
    borderBottomWidth: 1.5,
    borderColor: '#CCCCCC',
    minWidth: '24%',
    padding: 10,
    borderRadius: 6,
  },

  action: {
    padding: 6,
  },
  actionName: {
    color: '#000000',
    fontSize: 12,
    fontFamily: 'Montserrat-SemiBold',
  },
  itemSeparatorComponent: {
    height: 1,
    backgroundColor: '#CCCCCC',
  },
});

export default ListOptionMore;

// ./components/StripUser

import React, {useState, useEffect} from 'react';
import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import Feather from 'react-native-vector-icons/Feather';

import ListOptionMore from './ListOptionMore';

const StripUser = props => {
  const [showMore, setShowMore] = useState(props.showMore);

  useEffect(() => {
    setShowMore(props.showMore);
  }, [props.showMore]);

  return (
    <TouchableOpacity
      activeOpacity={0.75}
      onPress={() => {
        console.log('Leave Info Strip');
        setShowMore(false);
      }}
      style={[styles.root, props.style]}>
      <Image
        source={{
          uri: props.data?.image_link,
        }}
        style={styles.image}
      />

      <View style={styles.textContainer}>
        <Text style={styles.name}>{props.data?.name}</Text>
        <Text style={styles.email}>{props.data?.email}</Text>
      </View>

      <TouchableOpacity
        activeOpacity={0.75}
        onPress={() => {
          setShowMore(!showMore);
        }}
        style={styles.moreButton}>
        <Feather
          name={'more-vertical'}
          size={18}
          color={'#888888'}
        />
      </TouchableOpacity>
        
      <ListOptionMore
        showMore={showMore}
        changeShowMore={setShowMore}
        more={props.more}
      />
      
    </TouchableOpacity>
  );
};

StripUser.defaultProps = {
  style: {},
  height: 216,
  showMore: false,
  more: [
    {
      name: 'View',
      action: item => {
        console.log('View');
      },
    },
    {
      name: 'Edit',
      action: item => {
        console.log('Edit');
      },
    },
    {
      name: 'Delete',
      action: item => {
        console.log('Delete');
      },
    },
    {
      name: 'Unpublish',
      action: item => {
        console.log('Unpublish');
      },
    },
  ],
};

const styles = StyleSheet.create({
  root: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingVertical: 12,
  },

  image: {
    width: 70,
    aspectRatio: 1,
    borderRadius: 16,
    marginRight: 18,
    backgroundColor: '#E5E5E5',
  },

  textContainer: {
    flex: 1,
  },
  name: {
    color: '#000000',
    fontSize: 16,
    fontFamily: 'Montserrat-Bold',
  },
  email: {
    color: '#666666',
    fontSize: 14,
    fontFamily: 'Montserrat-Bold',
    paddingTop: 6,
  },

  moreButton: {
    width: 20,
    height: 20,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    borderColor: '#CCCCCC',
    borderWidth: 1,
    borderTopWidth: 0.5,
    borderBottomWidth: 2,
  },
});

export default StripUser;

// ./App

import React, { useState, useEffect } from 'react';
import { FlatList, ScrollView, StyleSheet, Text, View } from 'react-native';

import StripUser from './components/StripUser';

const UsersAll = () => {
  const userList = [
    {
      id: 1,
      name: 'Sandra Lucas',
      email: '[email protected]',
      image_link: 'https://randomuser.me/api/portraits/women/49.jpg',
    },
    {
      id: 2,
      name: 'Cassandra Black',
      email: '[email protected]',
      image_link: 'https://randomuser.me/api/portraits/women/72.jpg',
    },
    {
      id: 3,
      name: 'Connor Griffin',
      email: '[email protected]',
      image_link: 'https://randomuser.me/api/portraits/men/71.jpg',
    },
    {
      id: 4,
      name: 'Clifton Dixon',
      email: '[email protected]',
      image_link: 'https://randomuser.me/api/portraits/men/35.jpg',
    },
    {
      id: 5,
      name: 'Charlotte Barnes',
      email: '[email protected]',
      image_link: 'https://randomuser.me/api/portraits/women/34.jpg',
    },
  ];

  const renderItem = ({ item }) => (
    <StripUser
      data={{
        image_link: item?.image_link,
        name: item?.name,
        email: item?.email,
      }}
    />
  );

  return (
    <View style={styles.root}>
      <View style={styles.section}>
        <Text style={styles.title}>Users</Text>
        <FlatList
          data={userList}
          renderItem={renderItem}
          keyExtractor={(item, index) => index}
          contentContainerStyle={styles.sectionList}
          showsVerticalScrollIndicator={false}
          ItemSeparatorComponent={() => (
            <View style={styles.sectionItemSeparator} />
          )}
        />
      </View>

      <View height={50} />
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    flex: 1,
    backgroundColor: '#F7F7F7',
  },

  title: {
    fontSize: 18,
    color: '#073669',
    fontFamily: 'Montserrat-SemiBold',
  },

  section: { width: '100%', paddingHorizontal: 24, marginTop: 30, flex: 1 },
  sectionList: {
    backgroundColor: '#FFFFFF',
    marginTop: 12,
    paddingHorizontal: 16,
    paddingVertical: 20,
    borderRadius: 8,
  },
  sectionItemSeparator: {
    borderWidth: 0.5,
    borderColor: '#CCCCCC',
  },
});

export default UsersAll;
0

There are 0 best solutions below