react-nativecss-positionabsolutenativewind

Relative View overlay in web - React Native


I recently crafted a Dropdown component in React Native. However, I faced a challenge where the Flatlist content ended up positioned beneath the subsequent Dropdown component. This positioning issue prompted me to review my code. Here's the code snippet for reference:

Dropdown Component:

export const DropDown = ({
  className,
  setSelectedValue,
  label,
  defaultValue,
  padding,
  options,
}) => {
  const [value, setValue] = useState({});
  const [show, setShow] = useState(false);
  const labelTranslateY = new Animated.Value(
    value?.label || defaultValue ? -7 : 11
  );

  const handleToggle = () => {
    setShow((prev) => !prev);
  };

  const handlePress = (item) => {
    setValue(item);
    setSelectedValue(item);
    setShow((prev) => !prev);
  };

  const renderItem = ({ item }) => (
    <TouchableOpacity onPress={() => handlePress(item)}>
      <View
        style={{}}
        className=" hover:bg-black cursor-pointer border-b border-gray-600/25 w-full flex flex-wrap flex-row "
      >
        <Text className="flex-1 py-1 px-2 text-left text-base  ">
          {item?.label || ""}
        </Text>
      </View>
    </TouchableOpacity>
  );

  return (
    <View
      className={`w-full h-full z-10 border-2 border-[#A7A7A7] ${
        value?.label || defaultValue ? `bg-white` : `bg-[#E8E8E8]`
      }  rounded-md flex flex-row justify-between items-center p y-1 px-2 ${className}`}
    >
      <TouchableOpacity className="w-full z-10" onPress={handleToggle}>
        <View className="w-full flex z-10 flex-row justify-between items-center">
          <Text className="text-xs z-10">{value?.label || defaultValue}</Text>
          <FontAwesomeIcon
            icon={show ? faCaretUp : faCaretDown}
            style={{ width: "1.5rem", height: "1.5rem", color: "#A7A7A7" }}
          />
        </View>
      </TouchableOpacity>
      <Animated.Text
        style={[
          styles.label,
          {
            transform: [{ translateY: labelTranslateY }],
            backgroundColor:
              value?.label || defaultValue ? "white" : "transparent",
          },
        ]}
      >
        {label}
      </Animated.Text>

      {show ? (
        <View
          className={
            `${Platform.OS ==="web" ? "w-full" : "w-[106%]"} z-10 rounded-md overflow-hidden absolute  right-0 top-[100%]`
          }
        >
          <FlatList
            data={options}
            className=" w-full border z-10 border-gray-300 rounded-sm  bg-gray-100 shadow-2xl "
            renderItem={renderItem}
            keyExtractor={(item, index) => item.value}
          />
        </View>
      ) : (
        <View></View>
      )}
    </View>
  );
};

index.js

const OverlapExample = () => {
  const [filters, setFilters] = useState({});

  const options = [
    { label: "jjjjj", value: "1" },
    { label: "kkkkk", value: "2" },
    { label: "lllll", value: "3" },
  ];

  const structData = [
    {
      options: options,
      value: 55,
      class: "h-12 p-1 w-1/4",
      name: "counter",
      label: "Counter",
    },
    {
      options: options,
      value: 55,
      class: "h-12 p-1 w-1/4",
      name: "category",
      label: "Category",
    },
    {
      options: options,
      value: 55,
      class: "h-12 p-1 w-1/4",
      name: "collection",
      label: "Collection",
    },
  ];

  const handleChange = (e, name) => {
    setFilters((prev) => {
      const newObject = { ...prev };
      newObject[`${name}`] = e;

      return newObject;
    });
  };

  return (
    <View className="w-full">
      {structData?.map((item, index) => {
        return (
          <View key={index} className={`${item.class}`}>
            <DropDown
              setSelectedValue={(e) => handleChange(e, item.name)}
              options={item.options}
              label={item.label}
              className={`border-2 border-[#A7A7A7] rounded-md py-1 px-2`}
              defaultValue={item.label || ""}
            />
          </View>
        );
      })}
    </View>
  );
};

Result:

enter image description here

enter image description here

I'm currently exploring ways to address this problem and ensure that the Flatlist content properly aligns with the Dropdown component as intended in the layout.


Solution

  • Just add greater zIndex property to top level dropdown and decrease it to lower level dropdown.

    Example

    counter dropdown have : zIndex: 10000
    
    category dropdown have : zIndex: 1000
    
    collection dropdown have : zIndex: 100
    

    hope it will help.