Skip to content

[ BUG ]HoverCard doesn't work with modal. The card shows under the modal instead of above it. #472

@Coolister-Ye

Description

@Coolister-Ye

Describe the bug
The HoverCard component doesn't render correctly. Ideally, the card should have showed up above the modal, but it was hidden under it. It seems modal will be the top one layer regardless of in where you put the PortalHost.

Steps to reproduce the behavior:

  1. npx @react-native-reusables/cli@latest init
  2. npx @react-native-reusables/cli@latest add hover-card
  3. Add Modal and a nested Hovercard into index.tsx
import { Button } from '@/components/ui/button';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card';
import { Icon } from '@/components/ui/icon';
import { Text } from '@/components/ui/text';
import { PortalHost } from '@rn-primitives/portal';
import { Link, Stack } from 'expo-router';
import { MoonStarIcon, StarIcon, SunIcon } from 'lucide-react-native';
import { useColorScheme } from 'nativewind';
import * as React from 'react';
import { Image, type ImageStyle, Modal, View } from 'react-native';

const LOGO = {
  light: require('@/assets/images/react-native-reusables-light.png'),
  dark: require('@/assets/images/react-native-reusables-dark.png'),
};

const SCREEN_OPTIONS = {
  title: 'React Native Reusables',
  headerTransparent: true,
  headerRight: () => <ThemeToggle />,
};

const IMAGE_STYLE: ImageStyle = {
  height: 76,
  width: 76,
};

export default function Screen() {
  const { colorScheme } = useColorScheme();

  return (
    <>
      <Stack.Screen options={SCREEN_OPTIONS} />
      <Modal visible={true} transparent>
        <View className="flex-1 bg-gray-200 opacity-50">
          <HoverCard>
            <HoverCardTrigger>
              <Text>Hover</Text>
            </HoverCardTrigger>
            <HoverCardContent>
              <Text>The React Framework – created and maintained by @vercel.</Text>
            </HoverCardContent>
          </HoverCard>
        </View>
      </Modal>
      <View className="flex-1 items-center justify-center gap-8 p-4">
        <Image source={LOGO[colorScheme ?? 'light']} style={IMAGE_STYLE} resizeMode="contain" />
        <View className="gap-2 p-4">
          <Text className="ios:text-foreground font-mono text-sm text-muted-foreground">
            1. Edit <Text variant="code">app/index.tsx</Text> to get started.
          </Text>
          <Text className="ios:text-foreground font-mono text-sm text-muted-foreground">
            2. Save to see your changes instantly.
          </Text>
        </View>
        <View className="flex-row gap-2">
          <Link href="https://reactnativereusables.com" asChild>
            <Button>
              <Text>Browse the Docs</Text>
            </Button>
          </Link>
          <Link href="https://github.com/founded-labs/react-native-reusables" asChild>
            <Button variant="ghost">
              <Text>Star the Repo</Text>
              <Icon as={StarIcon} />
            </Button>
          </Link>
        </View>
      </View>
    </>
  );
}

const THEME_ICONS = {
  light: SunIcon,
  dark: MoonStarIcon,
};

function ThemeToggle() {
  const { colorScheme, toggleColorScheme } = useColorScheme();

  return (
    <Button
      onPressIn={toggleColorScheme}
      size="icon"
      variant="ghost"
      className="ios:size-9 rounded-full web:mx-4">
      <Icon as={THEME_ICONS[colorScheme ?? 'light']} className="size-5" />
    </Button>
  );
}


  1. See error

Expected behavior
the card should have showed up above the modal, but it was hidden under it. It seems modal will be the top one layer regardless of in where you put the PortalHost. You can see from the screenshot below. The card is cover by the gray modal layer which I gave opacity-50 to it.

Screenshots

Image
  • Type: Browser
  • OS: Web
  • Browser chrome
  • Dependencies:
{
  "name": "my-app",
  "main": "expo-router/entry",
  "version": "1.0.0",
  "scripts": {
    "dev": "expo start -c",
    "android": "expo start -c --android",
    "ios": "expo start -c --ios",
    "web": "expo start -c --web",
    "clean": "rm -rf .expo node_modules"
  },
  "dependencies": {
    "@react-navigation/native": "^7.0.0",
    "@rn-primitives/hover-card": "^1.2.0",
    "@rn-primitives/portal": "~1.3.0",
    "@rn-primitives/slot": "^1.2.0",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "expo": "^54.0.0",
    "expo-linking": "~8.0.8",
    "expo-router": "~6.0.10",
    "expo-splash-screen": "~31.0.10",
    "expo-status-bar": "~3.0.8",
    "expo-system-ui": "~6.0.7",
    "lucide-react-native": "^0.545.0",
    "nativewind": "^4.2.1",
    "react": "19.1.0",
    "react-dom": "19.1.0",
    "react-native": "0.81.4",
    "react-native-reanimated": "~4.1.1",
    "react-native-safe-area-context": "~5.6.0",
    "react-native-screens": "~4.16.0",
    "react-native-svg": "15.12.1",
    "react-native-web": "^0.21.0",
    "react-native-worklets": "0.5.1",
    "tailwind-merge": "^3.3.1",
    "tailwindcss": "^3.4.14",
    "tailwindcss-animate": "^1.0.7"
  },
  "devDependencies": {
    "@babel/core": "^7.26.0",
    "@types/react": "~19.1.10",
    "prettier": "^3.6.2",
    "prettier-plugin-tailwindcss": "^0.6.14",
    "typescript": "~5.9.2"
  },
  "private": true
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions