Hover Card
A card that appears when a user hovers over an element.
import { MapPinIcon } from 'lucide-react'
import { HStack, Stack } from 'styled-system/jsx'
import { Avatar } from '~/components/ui/avatar'
import { HoverCard } from '~/components/ui/hover-card'
import { Icon } from '~/components/ui/icon'
import { Link } from '~/components/ui/link'
import { Text } from '~/components/ui/text'
export const Demo = (props: HoverCard.RootProps) => {
return (
<HoverCard.Root {...props}>
<HoverCard.Trigger asChild>
<Link href="https://twitter.com/grizzly_codes/">@grizzly_codes</Link>
</HoverCard.Trigger>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
<Stack gap="4" direction="row">
<Avatar
name="Christian Schröter"
src="https://avatars.githubusercontent.com/u/1846056"
/>
<Stack gap="3">
<Stack gap="1">
<Text size="sm" fontWeight="semibold">
@grizzly_codes
</Text>
<Text size="sm" color="fg.muted">
Staff Software Engineer working at vivenu GmbH
</Text>
</Stack>
<HStack gap="1" color="fg.subtle">
<Icon size="sm">
<MapPinIcon />
</Icon>
<Text size="xs">Joined Dezember 2011</Text>
</HStack>
</Stack>
</Stack>
</HoverCard.Content>
</HoverCard.Positioner>
</HoverCard.Root>
)
}
import { MapPinIcon } from 'lucide-solid'
import { HStack, Stack } from 'styled-system/jsx'
import { Avatar } from '~/components/ui/avatar'
import { HoverCard } from '~/components/ui/hover-card'
import { Icon } from '~/components/ui/icon'
import { Link } from '~/components/ui/link'
import { Text } from '~/components/ui/text'
export const Demo = (props: HoverCard.RootProps) => {
return (
<HoverCard.Root {...props}>
<HoverCard.Trigger
asChild={(triggerProps) => (
<Link {...triggerProps()} href="https://twitter.com/grizzly_codes/">
@grizzly_codes
</Link>
)}
/>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
<Stack gap="4" direction="row">
<Avatar
name="Christian Schröter"
src="https://avatars.githubusercontent.com/u/1846056"
/>
<Stack gap="3">
<Stack gap="1">
<Text size="sm" fontWeight="semibold">
@grizzly_codes
</Text>
<Text size="sm" color="fg.muted">
Staff Software Engineer working at vivenu GmbH
</Text>
</Stack>
<HStack gap="1" color="fg.subtle">
<Icon size="sm">
<MapPinIcon />
</Icon>
<Text size="xs">Joined Dezember 2011</Text>
</HStack>
</Stack>
</Stack>
</HoverCard.Content>
</HoverCard.Positioner>
</HoverCard.Root>
)
}
Usage
import { HoverCard } from '~/components/ui/hover-card'
Installation
npx @park-ui/cli components add hover-card
1
Add Styled Primitive
Copy the code snippet below into ~/components/ui/styled/hover-card.tsx
'use client'
import type { Assign } from '@ark-ui/react'
import { HoverCard } from '@ark-ui/react/hover-card'
import { type HoverCardVariantProps, hoverCard } from 'styled-system/recipes'
import type { ComponentProps, HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withRootProvider, withContext } = createStyleContext(hoverCard)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withRootProvider<
Assign<HoverCard.RootProviderProps, HoverCardVariantProps>
>(HoverCard.RootProvider)
export type RootProps = ComponentProps<typeof Root>
export const Root = withRootProvider<Assign<HoverCard.RootProps, HoverCardVariantProps>>(
HoverCard.Root,
)
export const Arrow = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, HoverCard.ArrowBaseProps>
>(HoverCard.Arrow, 'arrow')
export const ArrowTip = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, HoverCard.ArrowTipBaseProps>
>(HoverCard.ArrowTip, 'arrowTip')
export const Content = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, HoverCard.ContentBaseProps>
>(HoverCard.Content, 'content')
export const Positioner = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, HoverCard.PositionerBaseProps>
>(HoverCard.Positioner, 'positioner')
export const Trigger = withContext<
HTMLButtonElement,
Assign<HTMLStyledProps<'button'>, HoverCard.TriggerBaseProps>
>(HoverCard.Trigger, 'trigger')
export { HoverCardContext as Context } from '@ark-ui/react/hover-card'
import { type Assign, HoverCard } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { type HoverCardVariantProps, hoverCard } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withRootProvider, withContext } = createStyleContext(hoverCard)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withRootProvider<
Assign<HoverCard.RootProviderProps, HoverCardVariantProps>
>(HoverCard.RootProvider)
export type RootProps = ComponentProps<typeof Root>
export const Root = withRootProvider<Assign<HoverCard.RootProps, HoverCardVariantProps>>(
HoverCard.Root,
)
export const Arrow = withContext<Assign<HTMLStyledProps<'div'>, HoverCard.ArrowBaseProps>>(
HoverCard.Arrow,
'arrow',
)
export const ArrowTip = withContext<Assign<HTMLStyledProps<'div'>, HoverCard.ArrowTipBaseProps>>(
HoverCard.ArrowTip,
'arrowTip',
)
export const Content = withContext<Assign<HTMLStyledProps<'div'>, HoverCard.ContentBaseProps>>(
HoverCard.Content,
'content',
)
export const Positioner = withContext<
Assign<HTMLStyledProps<'div'>, HoverCard.PositionerBaseProps>
>(HoverCard.Positioner, 'positioner')
export const Trigger = withContext<Assign<HTMLStyledProps<'button'>, HoverCard.TriggerBaseProps>>(
HoverCard.Trigger,
'trigger',
)
export { HoverCardContext as Context } from '@ark-ui/solid'
No snippet found
2
Add Re-Export
To improve the developer experience, re-export the styled primitives in~/components/ui/hover-card.tsx
.
export * as HoverCard from './styled/hover-card'
export * as HoverCard from './styled/hover-card'
3
Integrate Recipe
If you're not using @park-ui/preset
, add the following recipe to yourpanda.config.ts
:
import { hoverCardAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'
export const hoverCard = defineSlotRecipe({
className: 'hoverCard',
slots: hoverCardAnatomy.keys(),
base: {
content: {
'--hover-card-background': 'colors.bg.default',
background: 'var(--hover-card-background)',
borderRadius: 'l3',
boxShadow: 'lg',
maxW: '80',
p: '4',
position: 'relative',
_open: {
animation: 'fadeIn 0.25s ease-out',
},
_closed: {
animation: 'fadeOut 0.2s ease-out',
},
},
arrow: {
'--arrow-size': '12px',
'--arrow-background': 'var(--hover-card-background)',
},
arrowTip: {
borderTopWidth: '1px',
borderLeftWidth: '1px',
},
},
})