Hover card primitive wrappers
@fictjs
Fine-grained reactivity with a compiler-first runtime.
Fict ecosystemimport { Button } from '@/components/ui/button'
import { HoverCard, HoverCardContent, HoverCardTriggerEl } from '@/components/ui/hover-card'
...import { Button } from '@/components/ui/button'
import { HoverCard, HoverCardContent, HoverCardTriggerEl } from '@/components/ui/hover-card'
export default function HoverCardDemoExample() {
return <HoverCard openDelay={10} closeDelay={100}><HoverCardTriggerEl asChild><Button variant="link">Hover Here</Button></HoverCardTriggerEl><HoverCardContent class="w-64"><strong>@fictjs</strong><p class="text-sm">Fine-grained reactivity with a compiler-first runtime.</p><small class="text-muted-foreground">Fict ecosystem</small></HoverCardContent></HoverCard>
}
Installation
npx @fictjs/shadcn@latest add hover-cardInstall the runtime dependencies:
npm install @fictjs/radix-uiCopy the Fict shadcn component into your project.
Source
components/ui/hover-card.tsx
src/components/ui/hover-card.tsx
import { HoverCard as HoverCardPrimitive } from '@fictjs/radix-ui'
import { cn } from '@/lib/cn'
export const HoverCard = HoverCardPrimitive.Root
export const HoverCardTriggerEl = HoverCardPrimitive.Trigger
type HoverCardContentProps = {
class?: string
children?: unknown
[key: string]: unknown
}
export function HoverCardContent(props: HoverCardContentProps) {
const { class: className, align = 'center', sideOffset = 4, ...rest } = props
return (
<HoverCardPrimitive.Content
align={align}
sideOffset={sideOffset}
class={cn('z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none', className)}
{...rest}
/>
)
}
Usage
Examples
Sides
Hover Card
This hover card appears on the left side of the trigger.
Hover Card
This hover card appears on the top side of the trigger.
Hover Card
This hover card appears on the bottom side of the trigger.
Hover Card
This hover card appears on the right side of the trigger.
import { Button } from '@/components/ui/button'
import { HoverCard, HoverCardContent, HoverCardTriggerEl } from '@/components/ui/hover-card'
...import { Button } from '@/components/ui/button'
import { HoverCard, HoverCardContent, HoverCardTriggerEl } from '@/components/ui/hover-card'
const sides = ['left', 'top', 'bottom', 'right'] as const
export default function HoverCardSidesExample() {
return <div class="flex flex-wrap gap-2">{sides.map(side => <HoverCard openDelay={100} closeDelay={100}><HoverCardTriggerEl asChild><Button variant="outline" class="capitalize">{side}</Button></HoverCardTriggerEl><HoverCardContent side={side}><strong>Hover Card</strong><p class="text-sm">This hover card appears on the {side} side of the trigger.</p></HoverCardContent></HoverCard>)}</div>
}
Rtl
import { Button } from '@/components/ui/button'
import { HoverCard, HoverCardContent, HoverCardTriggerEl } from '@/components/ui/hover-card'
...import { Button } from '@/components/ui/button'
import { HoverCard, HoverCardContent, HoverCardTriggerEl } from '@/components/ui/hover-card'
const translations = {
ar: { dir: 'rtl', sides: ['يسار', 'أعلى', 'أسفل', 'يمين', 'بداية السطر', 'نهاية السطر'], product: 'سماعات لاسلكية', price: '٩٩.٩٩ $' },
he: { dir: 'rtl', sides: ['שמאל', 'למעלה', 'למטה', 'ימין', 'תחילת השורה', 'סוף השורה'], product: 'אוזניות אלחוטיות', price: '99.99 $' },
en: { dir: 'ltr', sides: ['Left', 'Top', 'Bottom', 'Right', 'Inline Start', 'Inline End'], product: 'Wireless Headphones', price: '$99.99' },
} as const
const positions = ['left', 'top', 'bottom', 'right', 'inline-start', 'inline-end'] as const
export default function HoverCardRtlExample() {
let language = $state<keyof typeof translations>('ar')
const text = () => translations[language]
return <div class="grid gap-4"><select value={language} onChange={event => { language = event.currentTarget.value as keyof typeof translations }}><option value="ar">Arabic (العربية)</option><option value="he">Hebrew (עברית)</option><option value="en">English</option></select><div class="flex flex-wrap gap-2" dir={text().dir}>{positions.map((side, index) => <HoverCard openDelay={10} closeDelay={100}><HoverCardTriggerEl asChild><Button variant="outline">{text().sides[index]}</Button></HoverCardTriggerEl><HoverCardContent side={side} dir={text().dir}><strong>{text().product}</strong><p>{text().price}</p></HoverCardContent></HoverCard>)}</div></div>
}