Frontend Lab
← 回到所有模式
PA03🧩 Compose · 互動組合社群

Comments Thread

留言串

難度 ★★★★★標籤 留言 · 狀態 · empty · loading3 min read

模式簡述

留言區是「狀態 UI」最完整的案例:空 / 載入 / 正常 / 大量 / 錯誤。每個狀態都需要設計, 而且空狀態跟錯誤狀態經常被偷懶忽略,造成「畫面空白以為網頁壞了」的爛經驗。

尚無留言

|尚無留言 — CTA 邀請發言

Claude Code Prompt

💬 Claude Code Prompt
參考:PA03 comments-thread
技術:純 React + skeleton 載入

具體行為:
- 空:顯示 icon + CTA「搶頭香」
- 載入:3 筆 skeleton(avatar + 2 行)
- 正常:avatar、name、時間、內容;自己的留言高亮
- 大量:先顯示 6 筆 + 「載入更多」按鈕
- 錯誤:red icon + 訊息 + retry

限制:
- skeleton 一定要跟真實內容尺寸接近,不然會跳版
- 自己的留言用 ring + bg 微微強調就好,不要太顯眼
- 時間用相對時間(2 分鐘前),不要 ISO

完整程式碼

CommentsThread.tsx
'use client'

type Comment = { name: string; avatar: string; text: string; own?: boolean; time: string }

export function CommentsThread({ comments, state }: { comments: Comment[]; state: 'empty'|'loading'|'normal'|'error' }) {
if (state === 'empty') {
  return (
    <div>
      <p>尚無留言</p>
      <button>搶頭香</button>
    </div>
  )
}

if (state === 'loading') {
  return (
    <ul>
      {[0,1,2].map(i => (
        <li key={i} className="flex gap-3">
          <div className="h-8 w-8 animate-pulse rounded-full bg-muted" />
          <div className="flex-1 space-y-2">
            <div className="h-3 w-24 animate-pulse rounded bg-muted" />
            <div className="h-3 w-full animate-pulse rounded bg-muted" />
          </div>
        </li>
      ))}
    </ul>
  )
}

if (state === 'error') {
  return <div>讀取失敗 <button>重試</button></div>
}

return (
  <ul>
    {comments.map((c, i) => (
      <li key={i} className={c.own ? 'bg-lab-accent/5 ring-1 ring-lab-accent/20' : ''}>
        <div>{c.avatar}</div>
        <div>
          <span>{c.name}</span> <span>{c.time}</span>
          <p>{c.text}</p>
        </div>
      </li>
    ))}
  </ul>
)
}

何時用

  • ✅ 部落格、文章下方留言
  • ✅ Issue / PR 討論串
  • ✅ 任何需要「使用者參與」的內容區

何時別用

  • ❌ 沒人會看的舊內容(懶得做就別做空狀態)
  • ❌ 即時聊天(要用 chat UI 模式,bottom-up)
  • ❌ 一次性 feedback(用 form 更直接)

我踩過的坑

  1. 空狀態只寫「沒有留言」:使用者看不出來能不能留言。要加 CTA。

  2. skeleton 尺寸跟真實差很多:載入完畫面整個跳。要量好 avatar 寬度跟 文字 line-height,skeleton 才不會跳版。

  3. 自己的留言高亮太重:早期用 bg-yellow,整篇刺眼。 改成 bg-lab-accent/5 + ring-1 ring-lab-accent/20,剛好。

相關模式

  • PA01 Search Match — 搜尋留言時的命中高亮

搜尋

按 ⌘K 隨時開啟