WebberUI

Async State Slot

非同步狀態槽:在 idle/載入/空狀態/錯誤/內容五態間以高度變形與共享元素過渡切換。

載入預覽⋯

Playground

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

0.4
160
<AsyncStateSlot />

安裝

npx shadcn@latest add https://webberui.com/r/async-state-slot.json

或在 components.json 設定 registries 後,改用 @webberui/async-state-slot 安裝。

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

npm install motion lucide-react clsx tailwind-merge

使用

以單一 state prop 驅動整個插槽;狀態切換時外框高度會平滑補間,退場元素摺疊、進場元素滑入補位。content 狀態顯示 children,其餘四態未提供覆寫時會渲染內建佔位。

import { AsyncStateSlot } from "@/components/ui/async-state-slot";

function Inbox() {
  const [state, setState] = React.useState<AsyncState>("loading");

  React.useEffect(() => {
    fetch("/api/items")
      .then((r) => r.json())
      .then((items) => setState(items.length ? "content" : "empty"))
      .catch(() => setState("error"));
  }, []);

  return (
    <AsyncStateSlot state={state} onRetry={() => setState("loading")}>
      <ItemList />
    </AsyncStateSlot>
  );
}

各狀態皆可用對應 prop 完全覆寫內建畫面:

<AsyncStateSlot
  state={state}
  loading={<MySkeleton />}
  empty={<MyEmptyState />}
>
  <ItemList />
</AsyncStateSlot>

Props

Prop型別預設值說明
state"idle" | "loading" | "empty" | "error" | "content"目前狀態(受控)
childrenReactNodecontent 狀態的內容
idleReactNode內建idle 狀態覆寫
loadingReactNode內建骨架loading 狀態覆寫
emptyReactNode內建插圖empty 狀態覆寫
errorReactNode內建插圖error 狀態覆寫
idleTitlestring"待命中"內建待命標題
idleDescriptionstring"等待觸發載入。"內建待命說明
emptyTitlestring"沒有資料"內建空狀態標題
emptyDescriptionstring"目前這裡還沒有任何內容。"內建空狀態說明
errorTitlestring"載入失敗"內建錯誤標題
errorDescriptionstring"發生了一些問題,請稍後再試。"內建錯誤說明
onRetry() => void提供時於內建錯誤狀態顯示重試按鈕
retryLabelstring"重試"重試按鈕文字
durationnumber0.4高度變形與淡入淡出時長(秒)
transitionTransition覆寫高度變形轉場(優先於 duration
minHeightnumber | string插槽最小高度,避免切換塌陷
srLabelsPartial<Record<AsyncState, string>>內建覆寫各狀態朗讀文字

細節

  • 高度變形:外框以 Motion 的 layout 依進場元素的實際高度平滑補間,內層以 layout="position" 抵銷縮放,文字不會被拉伸。
  • 共享元素過渡AnimatePresencemode="popLayout",退場元素移出排版流、換入元素獨自決定新高度,兩者過場重疊,形成「空狀態摺疊退場、首筆資料滑入補位」的效果。
  • 狀態受控state 由外部單一來源驅動,元件不持有內部狀態機,方便對應任何非同步資料流。
  • 未提供覆寫時,idleemptyerror 共用置中插圖版型,loading 為頭像加內文列的骨架。

可及性

  • 容器帶 aria-busyloading 時為 true)與 data-state,方便樣式與輔助科技辨識。
  • 內含 role="status"aria-live="polite" 的隱藏區塊,狀態切換時朗讀當前狀態,文字可用 srLabels 覆寫。
  • 重試按鈕具鍵盤焦點樣式(focus-visible)。
  • 使用者系統開啟「減少動態效果」時,停用高度與位移動畫,狀態直接切換。

On this page