Search code examples
cssiosreactjsreact-nativez-index

React Native z-index strange behavior


I am trying to write my custom dropdown component but I have a problem that even I set position absolute to my modal and high z-index, components which are below my dropdown seems to be on top. This behavior does not take place normally on web development because position: absolute creates new layer stack. How to fix that?

enter image description here

const Container = styled(Flex)`
  position: relative;
`

const Options = styled(Flex)`
  background-color: ${colors.white};
  position: absolute;
  z-index: 999999;
  transform: translateY(26px);
  top: 0;
  left: 4px;
  right: 4px;
  box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.16);
  border-bottom-left-radius: 26px;
  border-bottom-right-radius: 26px;
`

const Option = styled(TouchableOpacity)`
  display: flex;
  justify-content: center;
  flex-grow: 1;
  height: 52px;
  padding: 0 16px;
`

const Select = (props: Props) => {
  const { items, value, ...rest } = props

  return (
    <Container direction="column">
      <Input />
      <Options direction="column">
        <Option>
          <Text>Opcja 1</Text>
        </Option>
        <Option>
          <Text>Opcja 1</Text>
        </Option>
      </Options>
    </Container>
  )
}

export { Select }

Solution

  • this happening because all the Options containers have the same z-index , to solve this you can pass zIndex as a prop to the styled component , the value you pass is dependent on wither the dropDown is active or not so if its active you pass a high value if its not pass a low value this insures the active DropDown is always on top , also for this to work properly their should be either one expanded dropdown or none

    const Options = styled(Flex)`
      background-color: ${colors.white};
      position: absolute;
      z-index:${({zIndex})=>zIndex} ;
      transform: translateY(26px);
      top: 0;
      left: 4px;
      right: 4px;
      box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.16);
      border-bottom-left-radius: 26px;
      border-bottom-right-radius: 26px;
    `
    
    
    
    const Select = (props: Props) => {
      const { items,index, value,isActive,setActiveDropDown, ...rest } = props
    
      return (
        <Container onClick{e=>setActiveDropDown(index)}  direction="column">
          <Input />
          {
             isActive
             ?<Options  zIndex={isActive?9000:1000}  direction="column">
            <Option>
              <Text>Opcja 1</Text>
            </Option>
            <Option>
              <Text>Opcja 1</Text>
            </Option>
          </Options>
            :null
          }
        </Container>
      )
    }
    

    in your selects :

    const Wrapper=()=>{
          //initializing  activeDropDown <ith -1 means all dropdowns are collapsed 
          const [activeDropDown,setActiveDropDown]=useSate(-1)
    
        return <View>
             <Select setActiveDropDown={setActiveDropDown} index={0} isActive={activeDropDown==0}  />
             <Select setActiveDropDown={setActiveDropDown} index={1} isActive={activeDropDown==1}  />
             <Select setActiveDropDown={setActiveDropDown} index={2} isActive={activeDropDown==2}  />
        </View>
    
    }