Hover Card
Hover Card Primitive
Terminal window
~/components/ui/hover-card.tsx
Demo
Allows users with vision to preview the content hidden behind an element before hovering or pressing.
Installation
npx @react-native-reusables/cli@latest add hover-card
Copy/paste the following code to ~/components/ui/hover-card.tsx
:
import * as HoverCardPrimitive from '@rn-primitives/hover-card';import * as React from 'react';import { Platform, StyleSheet } from 'react-native';import Animated, { FadeIn } from 'react-native-reanimated';import { cn } from '~/lib/utils';import { TextClassContext } from '~/components/ui/text';
const HoverCard = HoverCardPrimitive.Root;
const HoverCardTrigger = HoverCardPrimitive.Trigger;
const HoverCardContent = React.forwardRef< HoverCardPrimitive.ContentRef, HoverCardPrimitive.ContentProps>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => { const { open } = HoverCardPrimitive.useRootContext(); return ( <HoverCardPrimitive.Portal> <HoverCardPrimitive.Overlay style={Platform.OS !== 'web' ? StyleSheet.absoluteFill : undefined} > <Animated.View entering={FadeIn}> <TextClassContext.Provider value='text-popover-foreground'> <HoverCardPrimitive.Content ref={ref} align={align} sideOffset={sideOffset} className={cn( 'z-50 w-64 rounded-md border border-border bg-popover p-4 shadow-md shadow-foreground/5 web:outline-none web:cursor-auto data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', open ? 'web:animate-in web:fade-in-0 web:zoom-in-95' : 'web:animate-out web:fade-out-0 web:zoom-out-95', className )} {...props} /> </TextClassContext.Provider> </Animated.View> </HoverCardPrimitive.Overlay> </HoverCardPrimitive.Portal> );});HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
export { HoverCard, HoverCardContent, HoverCardTrigger };
Usage
import { View } from 'react-native';import { Avatar, AvatarFallback, AvatarImage } from '~/components/ui/avatar';import { Button } from '~/components/ui/button';import { HoverCard, HoverCardContent, HoverCardTrigger } from '~/components/ui/hover-card';import { Text } from '~/components/ui/text';import { CalendarDays } from '~/lib/icons/CalendarDays';
function Example() { return ( <View className='flex-1 justify-center items-center p-6 gap-12'> <HoverCard> <HoverCardTrigger asChild> <Button variant='link' size='lg'> <Text>@nextjs</Text> </Button> </HoverCardTrigger> <HoverCardContent className='w-80 native:w-96'> <View className='flex flex-row justify-between gap-4'> <Avatar alt='Vercel avatar'> <AvatarImage source={{ uri: 'https://github.com/vercel.png' }} /> <AvatarFallback> <Text>VA</Text> </AvatarFallback> </Avatar> <View className='gap-1 flex-1'> <Text className='text-sm native:text-base font-semibold'>@nextjs</Text> <Text className='text-sm native:text-base'> The React Framework – created and maintained by @vercel. </Text> <View className='flex flex-row items-center pt-2 gap-2'> <CalendarDays size={14} className='text-foreground opacity-70' /> <Text className='text-xs native:text-sm text-muted-foreground'> Joined December 2021 </Text> </View> </View> </View> </HoverCardContent> </HoverCard> </View> );}
Props
HoverCard
Extends View
props
Prop | Type | Note |
---|---|---|
onOpenChange | (value: boolean) => void | |
asChild | boolean | (optional) |
relativeTo | ’longPress’ | ‘trigger’ | Native Only (optional) |
HoverCardTrigger
Extends Pressable
props
Prop | Type | Note |
---|---|---|
asChild | boolean | (optional) |
HoverCardContent
Extends View
props
Prop | Type | Note |
---|---|---|
asChild | boolean | (optional) |
forceMount | true | undefined | (optional) |
alignOffset | number | (optional) |
insets | Insets | (optional) |
avoidCollisions | boolean | (optional) |
align | ’start’ | ‘center’ | ‘end’ | (optional) |
side | ’top’ | ‘bottom’ | (optional) |
sideOffset | number | (optional) |
disablePositioningStyle | boolean | Native Only (optional) |
collisionBoundary | Element | null | Array<Element | null> | Web Only (optional) |
sticky | ’partial’ | ‘always’ | Web Only (optional) |
hideWhenDetached | boolean | Web Only (optional) |