پرتوپرتو

لیست پست (PostList)

کانتینر لیست پست‌ها با toggle حالت نمایش، ناوبری کیبورد، و پشتیبانی از انتخاب چندتایی

معرفی

PostList یک wrapper برای PostCard است که نیازمندی‌های مشترک صفحه‌ی feed — toggle حالت نمایش (view)، keyboard navigation (↑↓ / j/k)، نگهداری انتخاب کاربر، و deep-linking — را به صورت یکپارچه ارائه می‌دهد.

چه زمانی استفاده کنیم:

  • صفحه نتایج جستجو یا feed پست‌های چندپلتفرمی
  • لیست‌هایی که کاربر باید بین فشرده، راحت و گرید سوییچ کند
  • لیست‌هایی با نیاز به انتخاب چندتایی برای bulk actions

چه زمانی استفاده نکنیم:

  • اگر فقط یک یا دو پست نمایش می‌دهید → PostCard مستقیم
  • اگر نیاز به ساختار جدولی با ستون‌های دلخواه دارید → DataTable
  • اگر لیست کامنت زیر پست است → CommentCard در یک اسکرول ساده

زمین بازی

با تغییر تنظیمات زیر، پیش‌نمایش زنده را مشاهده کنید.

زمین بازی
@علی_رضایی
پست نمونه از علی رضایی برای نمایش لیست.
۱۰۰۱۰
@مریم_اکبری
پست نمونه از مریم اکبری برای نمایش لیست.
۱۰۰۱۰
@حسین_کریمی
پست نمونه از حسین کریمی برای نمایش لیست.
۱۰۰۱۰
تنظیمات
ظاهر
کد این نمونه به‌صورت خودکار قابل تولید نیست — برای کد آماده‌ی copy/paste به بخش «استفاده» در بالای صفحه مراجعه کنید.

استفاده

@sara.ahmadi
تجربه خریدم از #دیجی‌کالا واقعاً عالی بود! محصول دقیقاً همان‌طور که توضیح داده شده بود و ظرف ۲۴ ساعت به دستم رسید. #رضایت_مشتری
۸۷۶۱۲۴
مثبت
@ali_r
·۸۹ کامنت
سه بار با پشتیبانی تماس گرفتم ولی هنوز مشکل بازگشت کالا حل نشده. خدمات پس از فروش واقعاً افت کرده @DigiKala
۸.۹K۲۳۴۸۹
منفی
@digimag_ir
گزارش سه‌ماهه دیجی‌کالا: رشد ۳۴٪ در تراکنش‌های موبایل، افزایش ۱۸٪ در میانگین سبد خرید. مدیرعامل: «هدف تا پایان سال ۵ میلیون کاربر فعال روزانه است.»
۴۵.۲K
خنثی
@TechPlusIR
·تحلیلرونوشت
۲۰:۳۸
آنباکسینگ و بررسی کامل لپ‌تاپ خریداری‌شده از #دیجی‌کالا آیا ارزش قیمت را دارد؟
۱۵۶K۸.۹K۱.۲K
مثبت
import { PostList, type PostData } from '@partodata/ui'

const posts: PostData[] = [...]

export default function Feed() {
  const [selectedIds, setSelectedIds] = React.useState<string[]>([])
  const [activeId, setActiveId] = React.useState<string>()

  return (
    <PostList
      posts={posts}
      activeId={activeId}
      selectedIds={selectedIds}
      onSelectedIdsChange={setSelectedIds}
      onOpen={(post) => setActiveId(post.id)}
    />
  )
}

حالت‌های نمایش (view)

پراپ view تنها مسیر تغییر چینش کارت‌هاست و سه مقدار می‌گیرد:

مقدار viewlayoutکاربرد
compactردیف فشرده — thumbnail کناری + پیش‌نمایش متن یک‌خطیfeed با حجم زیاد، triage و اسکن سریع
comfortableکارت عمودی کامل — هدر، بدنه، رسانه، metrics و signals (پیش‌فرض)حالت پیش‌فرض، خواندنی، تحلیل تک‌پست
gridکاشی مربعی media-dominant در گرید چندستونهfeed بصری شبیه اینستاگرام، گالری رسانه‌ای

حالت کنترل‌نشده (پیش‌فرض)

اگر prop view را ندهید، کامپوننت حالت نمایش را در localStorage نگه می‌دارد و کاربر می‌تواند بین سه حالت سوییچ کند.

<PostList posts={posts} />

حالت کنترل‌شده

برای زمانی که می‌خواهید view را از URL یا state بالاتر کنترل کنید (مثلاً همگام‌سازی بین tabها یا persist روی URL):

const [view, setView] = React.useState<'compact' | 'comfortable' | 'grid'>('comfortable')

<PostList
  posts={posts}
  view={view}
  onViewChange={setView}
/>

بدون toolbar — toggle بیرونی

اگر toggle حالت نمایش را خودتان در یک header سفارشی رندر می‌کنید، با showToolbar={false} toolbar داخلی را خاموش کنید.

<PostList posts={posts} showToolbar={false} view={view} onViewChange={setView} />

toolbarExtra — افزودن کنترل کنار toggle

با toolbarExtra می‌توانید فیلتر، dropdown مرتب‌سازی، یا breadcrumb را در همان نوار toolbar در کنار toggle view قرار دهید.

<PostList
  posts={posts}
  toolbarExtra={
    <div className="flex items-center gap-2">
      <FilterChip label="پلتفرم: توییتر" />
      <FilterChip label="احساس: مخالف" />
    </div>
  }
/>

انتخاب چندتایی برای bulk actions

با ارائه selectedIds و onSelectedIdsChange Checkbox روی هر کارت فعال می‌شود و Space از روی صفحه‌کلید وضعیت انتخاب را toggle می‌کند.

const [selectedIds, setSelectedIds] = React.useState<string[]>([])

<PostList
  posts={posts}
  selectedIds={selectedIds}
  onSelectedIdsChange={setSelectedIds}
/>

حالت read با readIds

با پاس دادن readIds (آرایه یا Set) پست‌های قبلاً بازشده با visual «دیده‌شده» متفاوت رندر می‌شوند. مناسب برای feed افکارسنجی روزانه.

<PostList
  posts={posts}
  readIds={new Set(['post-1', 'post-3'])}
  activeId="post-2"
  onOpen={(post) => router.push(`/posts/${post.id}`)}
/>

اکشن‌های مشترک روی همه کارت‌ها

با actions می‌توانید مجموعه اکشن یکسانی (ذخیره، گزارش، اشتراک) را برای تمام کارت‌های لیست تعریف کنید.

هر آیتم PostAction به icon (از نوع LucideIcon) نیاز دارد:

import { Bookmark, Flag } from 'lucide-react'

;<PostList
  posts={posts}
  actions={[
    { id: 'save', label: 'ذخیره', icon: Bookmark, onClick: (p) => savePost(p.id) },
    { id: 'flag', label: 'گزارش تخلف', icon: Flag, onClick: (p) => flagPost(p.id) },
  ]}
/>

راهنمای استفاده

بکنید

  • برای deep-linking، activeId را از URL بگیرید تا با back/forward مرورگر کار کند. - برای bulk actions، کنترل‌شده بودن selectedIds را حفظ کنید تا بتوانید لیست را خارج از PostList خالی کنید. - در صورت تغییر حالت پیش‌فرض برای کاربران جدید، localStorage را پاک کنید.

نکنید

  • از PostList برای لیست‌های ۵۰۰۰+ بدون virtualization استفاده نکنید — virtualization در Phase 4 اضافه می‌شود. - ناوبری کیبورد خودکار را با onKeyDown سفارشی روی کارت‌ها overwrite نکنید — PostCard خودش Enter/Space را می‌پذیرد.

جدول ویژگی‌ها

PostList

Prop

Type

دسترسی‌پذیری

  • ↑/↓ و j/k بین کارت‌ها focus را جابجا می‌کنند.
  • Enter روی کارت focus شده پست را باز می‌کند.
  • Space وضعیت انتخاب را toggle می‌کند (اگر onSelectedIdsChange ارائه شده باشد).
  • ToggleGroup حالت نمایش aria-label فارسی دارد (حالت فشرده / حالت راحت / حالت گرید).

کامپوننت‌های مرتبط

  • PostCard — بلوک سازنده‌ی لیست. اگر فقط یک پست دارید، مستقیم از این استفاده کنید.
  • DataTable — اگر نیاز به ستون‌های دلخواه و sort دارید، نه ساختار پست.
  • Pagination — PostList در حال حاضر pagination داخلی ندارد؛ آن را بیرون wrap کنید.