<script lang="ts">
import CalendarDaysIcon from "@lucide/svelte/icons/calendar-days";
import * as Avatar from "$lib/components/ui/avatar/index.js";
import * as HoverCard from "$lib/components/ui/hover-card/index.js";
</script>
<HoverCard.Root>
<HoverCard.Trigger
href="https://github.com/sveltejs"
target="_blank"
rel="noreferrer noopener"
class="rounded-sm underline-offset-4 hover:underline focus-visible:outline-2 focus-visible:outline-offset-8 focus-visible:outline-black"
>
@sveltejs
</HoverCard.Trigger>
<HoverCard.Content class="w-80">
<div class="flex justify-between space-x-4">
<Avatar.Root>
<Avatar.Image src="https://github.com/sveltejs.png" />
<Avatar.Fallback>SK</Avatar.Fallback>
</Avatar.Root>
<div class="space-y-1">
<h4 class="text-sm font-semibold">@sveltejs</h4>
<p class="text-sm">Cybernetically enhanced web apps.</p>
<div class="flex items-center pt-2">
<CalendarDaysIcon class="me-2 size-4 opacity-70" />
<span class="text-muted-foreground text-xs">
Joined September 2022
</span>
</div>
</div>
</div>
</HoverCard.Content>
</HoverCard.Root> Installation
pnpm dlx shadcn-svelte@latest add hover-card Install bits-ui:
pnpm add bits-ui -D Copy and paste the following code into your project.
<script lang="ts">
import { LinkPreview as HoverCardPrimitive } from 'bits-ui';
import { cn, type WithoutChildrenOrChild } from '$UTILS$.js';
import HoverCardPortal from './hover-card-portal.svelte';
import type { ComponentProps } from 'svelte';
let {
ref = $bindable(null),
class: className,
align = 'center',
sideOffset = 4,
portalProps,
...restProps
}: HoverCardPrimitive.ContentProps & {
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof HoverCardPortal>>;
} = $props();
</script>
<HoverCardPortal {...portalProps}>
<HoverCardPrimitive.Content
bind:ref
data-slot="hover-card-content"
{align}
{sideOffset}
class={cn(
'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 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 z-50 w-72 origin-(--transform-origin) border border-[#222225] bg-[#09090b] p-4 text-sm text-zinc-50 shadow-none outline-hidden duration-100',
className
)}
{...restProps}
/>
</HoverCardPortal>
<script lang="ts">
import { LinkPreview as HoverCardPrimitive } from 'bits-ui';
let { ...restProps }: HoverCardPrimitive.PortalProps = $props();
</script>
<HoverCardPrimitive.Portal {...restProps} />
<script lang="ts">
import { LinkPreview as HoverCardPrimitive } from 'bits-ui';
import { cn } from '$UTILS$.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: HoverCardPrimitive.TriggerProps = $props();
</script>
<HoverCardPrimitive.Trigger
bind:ref
data-slot="hover-card-trigger"
class={cn(
'outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring/30',
className
)}
{...restProps}
/>
<script lang="ts">
import { LinkPreview as HoverCardPrimitive } from 'bits-ui';
let { open = $bindable(false), ...restProps }: HoverCardPrimitive.RootProps = $props();
</script>
<HoverCardPrimitive.Root bind:open {...restProps} />
import Root from './hover-card.svelte';
import Content from './hover-card-content.svelte';
import Trigger from './hover-card-trigger.svelte';
import Portal from './hover-card-portal.svelte';
export {
Root,
Content,
Trigger,
Portal,
Root as HoverCard,
Content as HoverCardContent,
Trigger as HoverCardTrigger,
Portal as HoverCardPortal
};
Usage
<script lang="ts">
import * as HoverCard from '$lib/components/ui/hover-card/index.js';
</script> <HoverCard.Root>
<HoverCard.Trigger>Hover</HoverCard.Trigger>
<HoverCard.Content>SvelteKit - Web development, streamlined</HoverCard.Content>
</HoverCard.Root>