nandorojo / zeego

Menus for React (Native) done right.
https://zeego.dev
MIT License
1.42k stars 41 forks source link

Why DropdownMenu.ItemIcon is not showing when used in a custom component? #79

Open Albert-Gao opened 3 months ago

Albert-Gao commented 3 months ago

Hi, thanks for this great lib!

I have a question :)

import * as DropdownMenu from "zeego/dropdown-menu";
import { DropdownMenuLabel } from "../DropdownMenu";
import { dropdownStyles } from "../DropdownMenu.styles";
import { View } from "react-native";
import { PressableFeatherIcon } from "../PressableFeatherIcon";
import { ComponentProps } from "react";

const FrontMenuItem = DropdownMenu.create(
  ({
    onSelect,
    androidIcon,
    iosIcon,
    key,
    children,
  }: {
    androidIcon: string;
    iosIcon: ComponentProps<typeof DropdownMenu.ItemIcon>["ios"];
    key: string;
    children: string;
    onSelect: ComponentProps<typeof DropdownMenu.Item>["onSelect"];
  }) => {
    return (
      <DropdownMenu.Item
        key={key}
        onSelect={onSelect}
        style={dropdownStyles.item}
      >
        <DropdownMenu.ItemTitle>{children}</DropdownMenu.ItemTitle>
        <DropdownMenu.ItemIcon
          androidIconName={androidIcon}
          ios={iosIcon}
        />
      </DropdownMenu.Item>
    );
  },
  "Item",
);

export function FrontMenu() {
  return (
    <DropdownMenu.Root style={{}}>
      <DropdownMenu.Trigger>
        <View>
          <PressableFeatherIcon
            color="blue"
            featherIconName="plus-circle"
            iconSize={32}
            pressableStyle={({ pressed }) => ({ opacity: pressed ? 0.5 : 1 })}
            onPress={() => {}}
          />
        </View>
      </DropdownMenu.Trigger>

      <DropdownMenu.Content style={dropdownStyles.content}>
        <DropdownMenuLabel>Help</DropdownMenuLabel>

        <FrontMenuItem
          key="mine"
          androidIcon="ic_menu_gallery"
          iosIcon={{ hierarchicalColor: "#00FF00", name: "photo" }}
          onSelect={() => {}}
        >
          See more 1
        </FrontMenuItem>

        <DropdownMenu.Item
          onSelect={() => {}}
          key="zeego"
        >
          <DropdownMenu.ItemIcon
            androidIconName="ic_menu_gallery"
            ios={{ hierarchicalColor: "#00FF00", name: "photo" }}
          />

          <DropdownMenu.ItemTitle>See more 2</DropdownMenu.ItemTitle>
        </DropdownMenu.Item>
      </DropdownMenu.Content>
    </DropdownMenu.Root>
  );
}

the outcome is this: image

so you can see from the image that when I use DropdownMenu.Item with DropdownMenu.ItemIcon directly, it works. When I wrapped it inside a custom component like <FrontMenuItem>, it stops working.

What am I missing here, thanks :)

nandorojo commented 3 months ago

Please see the docs on creating custom components.

Zeego is doing magic here and will not work on native if you wrap components without explicitly passing props in render. Zeego is extracting the props from your components and passing them to the native side through some tricks, and that’s why it works the way it does. As a result, this is the one limitation…

which is to say, this is expected, but there’s always a way to make it work somehow.