Shopify / flash-list

A better list for React Native
https://shopify.github.io/flash-list/
MIT License
5.38k stars 277 forks source link

iOS only: DropDown buttons placed in list items cannot be pressed on if they leave the bounds of parent item #1283

Open benrbowers opened 1 month ago

benrbowers commented 1 month ago

Current behavior

On iOS, when I have a vertical FlashList with items that have dropdown buttons, the drop down content is not able to be pressed on if it leaves the bounds of the parent item.

Important to note this seems to ALSO be the behavior for the FlatList components from both "react-native" and "react-native-gesture-handler". All three allow drop-downs to work on android and NOT on iOS.

I am using the CellRendererComponent prop to successfully allow the drop-down to APPEAR on top of the next item, but it is still not pressable on iOS.

The drop down content in this case is using position: 'absolute', but it appears even just "pushing" the content out of bounds with elements on top also causes it to not be able to be pressed on. So, the problem is related purely to being outside the parent item, and not it's position style.

<FlashList<AnnouncementWithCreator>
  refreshControl={
    <RefreshControl
      refreshing={refreshing}
      onRefresh={handleRefresh}
    />
  }
  data={data}
  nestedScrollEnabled
  renderItem={renderAnnouncement}
  itemName="announcements"
  keyExtractor={keyExtractor}
  loading={isFetching}
  lastPage={!hasNextPage}
  fetchNewPage={fetchNextPage}
  estimatedItemSize={160}
  CellRendererComponent={CellRendererComponent}
/>

const CellRendererComponent: FlashListProps<AnnouncementWithCreator>['CellRendererComponent'] =
  forwardRef(function CellRendererComponent({ index, style, ...props }, ref) {
    return (
      <CellContainer
        {...props}
        index={index}
        style={{ ...style, zIndex: 9999 - index }}
        ref={ref}
      />
    );
  });

Expected behavior

On iOS, content that exits item cells should be able to receive touch events.

Not entirely sure the fix is on you guys since it appears to also be present on the vanilla FlatList as well, but I guess it would be nice since you guys are like the "cool" FlatList lol.

If this makes more sense as a feature request, just let me know and I'll move it over.

In the meantime, for anyone else with this issue, some sort of modal solution is probably the best workaround. Or just have your dropdown content remain in the parent cell.

To Reproduce

Create a vertical FlashList whose items have dropdown content that exits the parent cell.

Platform:

Screenshots

Without CellRendererComponent (not pressable, obviously) DropDownCovered

With CellRendererComponent (STILL not pressable) DropDownShown

Environment

@shopify/flash-list@1.7.0 "expo": "~51.0.22", "react-native": "^0.74.3", "react-native-gesture-handler": "~2.16.1",

Screenshots from: XCode iOS Simulator iPhone SE (3rd generation)

Hardware: Model Name: MacBook Pro Model Identifier: MacBookPro11,5 Processor Name: Quad-Core Intel Core i7

phgn0 commented 3 weeks ago

So here's what fixed click interactions with absolute overlay content for me.

<FlashList
    ...
    CellRendererComponent={(props) => (
        <View
            {...props}
            style={{
                zIndex: isActiveElement ? 10 : 1,
            }}
        >
            {props.children}
        </View>
    )}
    disableAutoLayout={true} // needed to fix CellRendererComponent
/>

See: https://github.com/Shopify/flash-list/discussions/738 Related: https://github.com/Shopify/flash-list/issues/1283

benrbowers commented 3 weeks ago

So here's what fixed click interactions with absolute overlay content for me.

That looks like it might work! How are you getting the isActiveElement value?

benrbowers commented 2 weeks ago

I've tried manually setting the zIndex on specific cells to 9999, the drop down remains unpressable.

At the is point my options seem to be to allow the dropdown to extend the parent body, which looks bad, or to just use ScrollView.

If I'm going to apply the "no need to have more microservices than users" mindset, then I think ScrollView is the way to go.