WebberUI

Morph Expand Card

點擊卡片以 shared layout 無縫形變放大為置中詳情面板,同組同時只展開一張。

載入預覽⋯

Playground

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

2
<MorphExpandCard />

安裝

npx shadcn@latest add https://webberui.com/r/morph-expand-card.json

或在 components.json 設定 registries 後,改用 @webberui/morph-expand-card 安裝。

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

npm install motion lucide-react clsx tailwind-merge

使用

每張 MorphExpandCard 內放一個 MorphExpandCardSummary(收合內容)與一個 MorphExpandCardDetail(展開詳情)。外層以 MorphExpandGroup 包裹時,同組同時只會展開一張卡片。

import {
  MorphExpandGroup,
  MorphExpandCard,
  MorphExpandCardSummary,
  MorphExpandCardDetail,
} from "@/components/ui/morph-expand-card";

<MorphExpandGroup columns={2}>
  <MorphExpandCard value="a" label="星雲濾鏡">
    <MorphExpandCardSummary>
      <div className="p-4 font-semibold">星雲濾鏡</div>
    </MorphExpandCardSummary>
    <MorphExpandCardDetail>
      <div className="p-6">完整的詳情內容…</div>
    </MorphExpandCardDetail>
  </MorphExpandCard>
</MorphExpandGroup>;

單張卡片也可獨立使用(不包 MorphExpandGroup),此時卡片自行管理開闔。

受控模式

MorphExpandGroup 傳入 valueonValueChange 即可外部控制目前展開的卡片:

const [open, setOpen] = React.useState<string | null>(null);

<MorphExpandGroup value={open} onValueChange={setOpen}>
  {/* … */}
</MorphExpandGroup>;

自訂關閉鈕

詳情面板預設在右上角提供關閉鈕。若要自訂位置,於 MorphExpandCardDetailhideDefaultClose,並在內容任意處放置 MorphExpandCardClose

import { MorphExpandCardClose } from "@/components/ui/morph-expand-card";

<MorphExpandCardDetail hideDefaultClose>
  <MorphExpandCardClose className="left-3" />
  {/* … */}
</MorphExpandCardDetail>;

Props

MorphExpandGroup

Prop型別預設值說明
valuestring | null受控模式:目前展開卡片的值(null 為全部收合)
defaultValuestring | nullnull非受控模式的初始展開值
onValueChange(value: string | null) => void展開/收合變更時觸發
columnsnumber2網格欄數(1–6)
childrenReactNode放入 MorphExpandCard 子元件

MorphExpandCard

Prop型別預設值說明
valuestring自動產生卡片唯一值,群組用它判斷展開對象
labelstring無障礙標籤,套用於觸發卡片與詳情對話框
childrenReactNode需含一個 MorphExpandCardSummary 與一個 MorphExpandCardDetail

MorphExpandCardDetail

Prop型別預設值說明
hideDefaultClosebooleanfalse隱藏預設右上角關閉鈕(改用自訂 MorphExpandCardClose
childrenReactNode展開時顯示的詳情內容

MorphExpandCardClose

Prop型別預設值說明
childrenReactNodeX 圖示自訂按鈕內容

細節

  • 觸發卡片與詳情面板共用同一 layoutId,Motion 以 shared layout 讓卡片邊界框無縫形變為面板,收合時反向縮回原位。
  • 詳情面板透過 createPortal 掛載到 document.body,並以固定定位置中,形變不受父層 overflow 或堆疊脈絡影響。
  • 展開時原位卡片暫時 visibility: hidden,避免與形變中的面板重影。
  • 展開會鎖住 body 捲動,收合(或卸載)時還原;面板高度上限 85vh,內容過長時內部捲動。

可及性

  • 觸發卡片為 role="button"、可聚焦,支援 Enter/Space 展開;詳情面板為 role="dialog"aria-modal
  • 展開時焦點移入面板,收合後歸還觸發卡片;支援 Esc 收合、點擊遮罩收合。
  • 傳入 label 會同時作為卡片與對話框的 aria-label
  • 使用者開啟「減少動態效果」時,形變位移歸零,改以短暫淡入淡出取代。

On this page