PB08▸🪟 Overlay · 覆蓋層▸預覽
Link Preview
連結預覽
難度 ★★★★★標籤 preview · hover · 預覽3 min read
模式簡述
Link Preview:滑鼠停在連結上預覽目標頁面或縮圖。Notion、Twitter 都這樣做。
造訪 Frontend Lab,看更多互動。
Claude Code Prompt
參考:PB08 link-preview 組件:LinkPreview.tsx Link Preview:滑鼠停在連結上預覽目標頁面或縮圖。Notion、Twitter 都這樣做。 限制: - 沒做 delay - 預覽圖太大 - 沒處理 fetch 失敗
完整程式碼
"use client";
import { useEffect, useState } from "react";
type State = "hover" | "preview";
export function LinkPreview({ state = "preview" }: { state?: State }) {
const [hover, setHover] = useState(state !== "hover" ? true : false);
useEffect(() => setHover(state !== "hover" ? true : false), [state]);
return (
<div className="grid h-[260px] w-full max-w-md place-items-center px-4">
<p
className="text-sm leading-relaxed text-foreground/90"
style={{ fontFamily: "var(--font-zh)" }}
>
造訪{" "}
<span className="relative inline-block">
<a
href="#"
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
className="text-lab-accent underline-offset-4 hover:underline"
>
Frontend Lab
</a>
{hover && (
<span className="pointer-events-none absolute left-1/2 top-full z-10 mt-2 w-56 -translate-x-1/2 overflow-hidden rounded-lg border border-border bg-background shadow-2xl animate-in fade-in zoom-in-95 duration-150">
<span className="block aspect-[16/9] w-full bg-gradient-to-br from-lab-accent/30 via-purple-500/20 to-blue-500/30" />
<span className="block p-2.5 text-left">
<span className="block font-mono text-[10px] uppercase tracking-wider text-muted-foreground/70">
visual-effects-lab.pages.dev
</span>
<span className="mt-1 block text-xs font-medium text-foreground">
Frontend Lab
</span>
<span className="mt-0.5 block text-[11px] text-muted-foreground">
視覺效果與 UI 互動模式字典
</span>
</span>
</span>
)}
</span>
,看更多互動。
</p>
</div>
);
}何時用
- ✅ 跨頁面連結需要先確認再點
- ✅ 內部知識庫的反向連結展示
- ✅ social 卡片預覽
何時別用
- ❌ 所有連結都加(一頁就鬧鬼)
- ❌ 外部連結(隱私風險、CORS、預覽失敗一片)
- ❌ 手機端(沒 hover、會誤觸)
我踩過的坑
-
沒做 delay:滑鼠輕掃過就 fetch,浪費資源。350ms hover 才觸發。
-
預覽圖太大:300x200 通常夠用,再大就破壞閱讀。
-
沒處理 fetch 失敗:404 的話應該悄悄不出現,不要顯示破圖。
相關模式
- PB04
- PB09