WebberUI

Thumbnail Gallery

主圖與縮圖同步的畫廊,支援拖曳換圖、方向鍵、滑動/淡入切換與四向縮圖列。

載入預覽⋯

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

<ThumbnailGallery />

安裝

npx shadcn@latest add https://webberui.com/r/thumbnail-gallery.json

或在 components.json 設定 registries 後,改用 @webberui/thumbnail-gallery 安裝。

安裝依賴後,從 registry JSON(/r/thumbnail-gallery.jsonfiles[0].content)複製 thumbnail-gallery.tsx 原始碼到你的 components/ui/ 目錄:

npm install motion lucide-react clsx tailwind-merge

使用

import { ThumbnailGallery } from "@/components/ui/thumbnail-gallery";

const images = [
  { src: "/photos/1.jpg", alt: "海邊日落" },
  { src: "/photos/2.jpg", alt: "山林步道", thumbnail: "/photos/2-thumb.jpg" },
  { src: "/photos/3.jpg", alt: "城市夜景" },
];

<ThumbnailGallery images={images} />;

受控模式

傳入 valueonValueChange 即可由外部狀態接管目前索引:

const [index, setIndex] = React.useState(0);

<ThumbnailGallery images={images} value={index} onValueChange={setIndex} />;

縮圖位置與切換效果

<ThumbnailGallery images={images} thumbnailPosition="left" effect="fade" />

Props

Prop型別預設值說明
imagesGalleryImage[]圖片清單,第一項為初始主圖
valuenumber受控的目前索引
defaultValuenumber0非受控模式的初始索引
onValueChange(index: number) => void目前索引變更時觸發
thumbnailPosition"bottom" | "top" | "left" | "right""bottom"縮圖列位置(左/右為垂直列)
effect"slide" | "fade""slide"主圖切換效果
loopbooleanfalse是否在頭尾循環
showArrowsbooleantrue是否顯示主圖上的方向箭頭
aspectRatiostring"4 / 3"主圖長寬比(CSS aspect-ratio 值)
dragThresholdnumber60觸發換圖的拖曳位移閾值(px)
velocityThresholdnumber400觸發換圖的拖曳甩動速度閾值(px/s)
labelstring"圖片畫廊"無障礙用途的整體標籤

GalleryImage

欄位型別說明
srcstring主圖來源網址
altstring替代文字(無障礙必填)
thumbnailstring | undefined縮圖來源;未提供時退回使用 src

細節

  • 主圖以 AnimatePresence 依換圖方向做滑入(slide)或淡入(fade),並保有前後圖交疊的過場。
  • 在主圖上按住拖曳(水平縮圖時左右拖、垂直縮圖時上下拖),超過位移或甩動速度閾值即換到下一/上一張,未達門檻則彈回。
  • 目前縮圖會自動捲入縮圖列的可視範圍並置中,捲動僅發生在縮圖列容器內、不牽動整頁。
  • loop 開啟時頭尾相接;關閉時已到端點的方向箭頭會自動停用。

可及性

  • 主圖區為可聚焦的 輪播,方向鍵切換上一/下一張,Home / End 跳到首張/末張。
  • 縮圖列為 tablist,每個縮圖為 tab,目前項標記 aria-selectedaria-current,僅目前項可 Tab 聚焦(roving tabindex)。
  • 內建 aria-live="polite" 區域,換圖時朗讀「第 X 張,共 Y 張」與圖片替代文字。
  • 使用者系統開啟「減少動態效果」時,改為即時切換(不滑動、不淡入),拖曳也一併停用。

On this page