پست (Post)

یک کامپوننت برای هر پست، خبر یا بخش پخش؛ کارت (پیش‌فرض)، ردیف، کاشی، خلاصه و جزئیات از همان مدل SocialPost

معرفی

Post تنها کامپوننت نمایش یک پست است: پست شبکه‌های اجتماعی، خبر و مقالهٔ وب، و بخشی از رونوشت تلویزیون یا رادیو. دادهٔ آن همیشه یک SocialPost است و چیدمانش با یک محور کوچک layout انتخاب می‌شود. پیش‌فرض همه‌جا کارت است: Post بدون layout و فهرست پست بدون layouts کارت نمایش می‌دهند؛ ردیف و کاشی نماهای انتخابی‌اند و فقط وقتی می‌آیند که خواننده با دکمهٔ چیدمان یا کد به‌صراحت آن‌ها را انتخاب کند.

چیدمانکجاقاعده
cardپیش‌فرض؛ خبرخوان در ستون فیدرسانه به عرض کارت، کامل و بدون برش در بازهٔ 4:5 تا 1.91:1 با حداکثر حدود 500 پیکسل ارتفاع؛ عرض کارت حداکثر 680 پیکسل
rowانتخابی؛ فهرست برای مرور سریعبندانگشتی 96 پیکسلی (72 در حالت فشرده) در سمت شروع، کنار متن؛ سه خط متن (دو خط فشرده) با طول خط خوانا؛ یک خط شاخص؛ ارتفاع ثابت
tileانتخابی؛ شبکهٔ تصویریتنها چیدمانی که رسانه را می‌بُرد (1:1 یا 4:5)؛ کلیک، جزئیات را باز می‌کند
summaryپستی که یک صفحهٔ تحلیل دربارهٔ آن استبندانگشتی، هویت، دو خط متن که باز می‌شود، شاخص‌ها و اقدامات همیشه پیدا
detailsصفحه یا پنل جزئیاتکل پست: متن کامل، همهٔ رسانه‌ها بزرگ و کامل، همهٔ شاخص‌ها و خروجی تحلیل

وضعیت‌ها داده‌اند، نه کامپوننت: post.state (یا ویژگی state) همان پست را در حال بارگذاری، در حال پردازش، ناموفق، در دسترس نبودن، خصوصی یا حذف‌شده از منبع نمایش می‌دهد. عددها فقط از رکورد می‌آیند: مقدار نامعلوم «—» است، شاخصی که برای این مورد معنا ندارد نمایش داده نمی‌شود و هیچ صفری ساخته نمی‌شود. آمار حساب (دنبال‌کننده، رتبه) هیچ‌وقت داخل پست نمی‌آید.

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

  • هر جا یک پست، خبر یا بخش پخش نمایش داده می‌شود: فهرست نتایج جست‌وجو، خبرخوان، شبکهٔ تصویری، سربرگ صفحهٔ تحلیل، صفحهٔ جزئیات.
  • برای فهرست، Post را داخل EntityCollection بگذارید؛ ستون، اسکلت، حالت خالی و خطا، انتخاب و کیبورد را مجموعه فراهم می‌کند.

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

  • برای یک جزء تنها (فقط شاخص‌ها یا فقط رسانه): از اجزای پایه استفاده کنید.
  • کارت یا ردیف پست را خودتان از اجزای پایه نسازید؛ همین کامپوننت را با layout و در صورت نیاز با جایگاه‌ها به کار ببرید.
card · default
فروشگاه نمونه
@sample_shop
جشنوارهٔ تخفیف فصلی از امروز شروع شد و تا پایان هفته ادامه دارد. برای دیدن فهرست محصولات و شرایط ارسال به صفحهٔ فروشگاه سر بزنید. #تخفیف #پاییز
  • لایک12,400
  • نظر0
  • نرخ تعامل2.1٪
row · opt-in
فروشگاه نمونه
جشنوارهٔ تخفیف فصلی از امروز شروع شد و تا پایان هفته ادامه دارد. برای دیدن فهرست محصولات و شرایط ارسال به صفحهٔ فروشگاه سر بزنید. #تخفیف #پاییز
  • لایک12,400
  • نظر0
  • نرخ تعامل2.1٪
ویدئو، 0:08
کافه نمونه
بسته‌بندی تازهٔ محصول را در نمایشگاه دیدید؟ نظرتان را برای ما بنویسید؛ همهٔ پیام‌ها را می‌خوانیم و در طراحی نسخهٔ بعد به کار می‌بریم. @sample_shop
  • لایک2,400
  • نظر118
  • پخش ویدیو54,000
  • نرخ تعامل3.4٪
news.example.com
رونمایی محصول جدید در نمایشگاه با استقبال مشتری‌ها همراه شد
بازدیدکننده‌ها دربارهٔ بسته‌بندی، قیمت و پشتیبانی پس از فروش نظر دادند و بیشترین گفت‌وگو به همکاری برند با اینفلوئنسرها مربوط بود.
سارا محمدیاقتصادی
row · compact · opt-in
Brand Studio
رونمایی محصول جدید با حضور مشتری‌ها برگزار شد. گزارش کامل و عکس‌های مراسم: https://example.com/launch#photos
  • لایک12,400
  • نظر86
  • نرخ تعامل2.1٪
شبکهٔ نمونه
… در ادامهٔ برنامه دربارهٔ کمپین تخفیف فصلی و بازخورد بسته‌بندی گفت‌وگو شد و کارشناس برنامه گفت که …
2:05–2:50گفتاراطمینان 86٪گوینده: کارشناس برنامه
tile · opt-in
فروشگاه نمونه
  • لایک12,400
  • نظر0
  • نرخ تعامل2.1٪
کافه نمونه
  • لایک12,400
  • نظر86
  • نرخ تعاملنامعلوم
رونمایی محصول جدید با حضور مشتری‌ها برگزار شد. گزارش کامل و عکس‌های مراسم: https://example.com/launch#photos
Brand Studio
  • بازدید34,000

آناتومی

Post یک کامپوننت ترکیبی (compound) است: همهٔ تکه‌ها در همین صفحه مستند شده‌اند و صفحهٔ جدا ندارند. بدون children هر چیدمان ترکیب پیش‌فرض خودش را دارد؛ برای ترکیب دیگر، همین جایگاه‌ها را بچینید (جدول API هر تکه در بخش Props است). تکه‌هایی که جای دیگر هم به کار می‌روند کامپوننت عمومی خودشان را دارند: MediaFrame، Handle، MetricGroup و PlatformMark.

فروشگاه نمونه
@sample_shop
جشنوارهٔ تخفیف فصلی از امروز شروع شد و تا پایان هفته ادامه دارد. برای دیدن فهرست محصولات و شرایط ارسال به صفحهٔ فروشگاه سر بزنید. #تخفیف #پاییز
  • لایک12,400
  • نظر0
  • نرخ تعامل2.1٪
  1. 1Post.Header — هویت منبع، نشانی و زمان
  2. 2Post.Text — متن پست با هشتگ و منشن
  3. 3Post.Media — رسانه در MediaFrame، بدون برش
  4. 4Post.Stats — شاخص‌ها فقط از رکورد
  5. 5Post.Actions — اقدام‌های محصول (actions)

استفاده

فهرست پست‌ها همیشه یک EntityCollection است و هر مورد یک Post؛ ویژگی‌های مورد (item) را روی Post پخش کنید و ویژگی‌های محصول را کنارش بگذارید:

'use client'

import { useRouter } from 'next/navigation'
import { Send } from 'lucide-react'
import { EntityCollection, Post, type SocialPost } from '@partodata/ui/social'

interface SearchResultsProps {
  posts: SocialPost[]
  loading: boolean
  onAnalyze: (post: SocialPost) => void
}

export function SearchResults({ posts, loading, onAnalyze }: SearchResultsProps) {
  const router = useRouter()
  return (
    <EntityCollection
      entity="post"
      items={posts}
      getId={(post) => post.id}
      loading={loading}
      label="نتایج جست‌وجو"
      renderItem={(post, item) => (
        <Post
          post={post}
          {...item}
          onOpen={(p) => router.push(`/posts/${p.id}`)}
          metrics={['likes', 'comments', 'views']}
          actions={[{ id: 'analyze', label: 'ارسال به تحلیل', icon: <Send />, onSelect: onAnalyze }]}
        />
      )}
    />
  )
}

دادهٔ API را پیش از نمایش یک بار به مدل تبدیل کنید: ردیف PostData با fromPostData و ردیف خام جست‌وجوی محتوا با fromSearchContent، هر دو از @partodata/ui/social/adapters. مجموعه چند مورد اول را با اولویت بارگذاری می‌کند (priority را خودتان نگذارید).

کلیک و اقدامات

  • کلیک اصلی (و Enter روی مورد فوکوس‌شده) onOpen را صدا می‌زند: پست را داخل محصول باز کنید (صفحه یا پنل جزئیات).
  • «مشاهده در منبع» یک اقدام جداست: وقتی post.url هست، آخرین اقدام پیوندی به منبع در برگهٔ تازه است (sourceLink={false} آن را برمی‌دارد). هرگز کلیک اصلی کاربر را از برنامه بیرون نمی‌برد.
  • اقدامات محصول (ارسال به تحلیل، افزودن به گزارش، بوست) داده‌اند و با actions می‌آیند؛ سیستم طراحی هیچ اقدامی را از پیش نمی‌سازد. چند اقدام اول که آیکون دارند دکمهٔ آیکونی‌اند و بقیه در منوی «⋯».
  • اقدامات در card، row و tile با بردن نشانگر، با فوکوس کیبورد و روی صفحهٔ لمسی پیدا می‌شوند و جایشان را نگه می‌دارند، پس با پیدا شدنشان متن جابه‌جا نمی‌شود. در summary و details همیشه پیدا هستند.
  • پیوندها، هشتگ‌ها، منشن‌ها، دکمه‌های اقدام و چک‌باکس فقط کار خودشان را می‌کنند و پست را باز نمی‌کنند. کشیدن نشانگر برای انتخاب متن هم کلیک حساب نمی‌شود.
  • با selectable و onSelectedChange چک‌باکس انتخاب نمایش داده می‌شود و Space روی مورد فوکوس‌شده انتخاب را عوض می‌کند. نام دسترس‌پذیر چک‌باکس نام نویسنده و چند واژهٔ اول متن است، تا دو پست یک نویسنده از هم جدا شوند.
  • ردیفِ باریک‌تر از 28rem (گوشی، پنل کناری) همهٔ اقدامات را در منوی «⋯» جمع می‌کند و آن را به انتهای خط شاخص‌ها می‌برد، تا متن و شاخص‌ها عرض داشته باشند. aside در ردیف انتهای خط سرتیتر است (حداکثر نیمی از آن و کنار تصویر 40 درصد) و ستونی کنار متن نمی‌گیرد. این جایگاه یک‌خطی است: وقتی جا کم است، aside با «…» کوتاه می‌شود و نام (دست‌کم سه حرف‌پهنا) و زمان پست می‌مانند.

جزئیات پست همراه با نظرها

یک الگو، یک پاسخ: صفحهٔ جزئیات همان Post با layout="details" است و بحث زیر آن یک EntityCollection با entity="comment" از Comment (رشتهٔ thread، بدون دکمهٔ چیدمان). مجموعه اسکلت نظرها، حالت خالی، خطا با «تلاش دوباره»، جایگاه «نظرهای بیشتر»، شمار نظرها در سربرگ و کیبورد را می‌دهد؛ پاسخ‌هایی که هنوز بارگذاری نشده‌اند با onLoadReplies از خود Comment می‌آیند. فهرست نظرها را خودتان با map نسازید.

فروشگاه نمونه
@sample_shop
جشنوارهٔ تخفیف فصلی از امروز شروع شد و تا پایان هفته ادامه دارد. برای دیدن فهرست محصولات و شرایط ارسال به صفحهٔ فروشگاه سر بزنید. #تخفیف #پاییز
  • 12,400لایک
  • 0نظر
  • 2.1٪نرخ تعامل
مثبت
بسته‌بندی82٪
2 نظر
سارا@sara_1402
بسته‌بندی جدید خیلی بهتر شده، ولی هزینهٔ ارسال بالاست. کاش ارسال رایگان هم داشتید. @sample_shop
قیمت91٪ارسال64٪
ترکیبی
  • پسند24
  • پاسخ4
نگار@negar.m
رنگ جدید بسته‌بندی را بیشتر دوست دارم.
ترکیبی
  • پسند2
  • پاسخ1
'use client'

import { Button } from '@partodata/ui/button'
import { Comment, EntityCollection, Post, type SocialComment, type SocialPost } from '@partodata/ui/social'

interface PostDetailsProps {
  post: SocialPost
  comments: SocialComment[]
  totalComments: number
  loading: boolean
  error?: unknown
  onRetry: () => void
  onMore?: () => void
  onLoadReplies: (comment: SocialComment) => Promise<void>
}

export function PostDetails({
  post,
  comments,
  totalComments,
  loading,
  error,
  onRetry,
  onMore,
  onLoadReplies,
}: PostDetailsProps) {
  return (
    <div className="flex flex-col gap-6">
      <Post post={post} layout="details" headingLevel={2} />
      <EntityCollection
        entity="comment"
        items={comments}
        getId={(comment) => comment.id}
        label="نظرها"
        header={<span>{`${totalComments} نظر`}</span>}
        loading={loading}
        error={error}
        onRetry={onRetry}
        pagination={
          onMore ? (
            <Button variant="ghost" size="sm" onClick={onMore}>
              نظرهای بیشتر
            </Button>
          ) : undefined
        }
        renderItem={(comment, item) => <Comment comment={comment} {...item} onLoadReplies={onLoadReplies} />}
      />
    </div>
  )
}

پنل کناری جزئیات

صفحه یا پنل جزئیات همین الگو است (Post با layout="details" و EntityCollection نظرها)؛ برای پنل کناری آن را داخل EntityDrawer یا Sheet بگذارید. (PostDetailsDrawer نسخهٔ 3 در 5.0 حذف شد.)

حالت‌ها و انواع

خبر، بخش پخش و وضعیت‌ها

خبر وب (kind: 'article') با تیتر، خلاصه و نویسنده نمایش داده می‌شود و شاخص اجتماعی ندارد؛ بخش تلویزیون یا رادیو (kind: 'transcript') نام برنامه، زمان پخش (تاریخ و ساعت)، بازهٔ بخش و متن اطراف واژهٔ جست‌وجوشده را با علامت نشان می‌دهد. جزئیات تشخیص متنِ بخش پخش در خط شاخص‌ها می‌آید: روش به‌دست‌آمدن متن (broadcast.textSource: «گفتار» یا «متن روی تصویر»)، اطمینان تشخیص (confidence بین 0 و 1؛ مقدار null «—» است و نبودنش یعنی نمایش داده نمی‌شود) و گوینده (speaker). ردیف و کاشی که سرتیترشان یک‌خطی است، بازهٔ بخش را هم در همین خط می‌آورند. رسانهٔ منقضی‌شده‌ای که ابعاد ندارد، در کارت و جزئیات یک خط اطلاع است، نه کادر خالی 500 پیکسلی.

news.example.com

رونمایی محصول جدید در نمایشگاه با استقبال مشتری‌ها همراه شد

سارا محمدی
بازدیدکننده‌ها دربارهٔ بسته‌بندی، قیمت و پشتیبانی پس از فروش نظر دادند و بیشترین گفت‌وگو به همکاری برند با اینفلوئنسرها مربوط بود.
اقتصادی
شبکهٔ نمونه
گزارش اقتصادی2:05–2:50
… در ادامهٔ برنامه دربارهٔ کمپین تخفیف فصلی و بازخورد بسته‌بندی گفت‌وگو شد و کارشناس برنامه گفت که …
رسانه منقضی شده است0:45
گفتاراطمینان 86٪گوینده: کارشناس برنامه
در حال بارگذاری
کافه نمونهدر حال پردازش
@cafe_example2
بسته‌بندی تازهٔ محصول را در نمایشگاه دیدید؟ نظرتان را برای ما بنویسید؛ همهٔ پیام‌ها را می‌خوانیم و در طراحی نسخهٔ بعد به کار می‌بریم. @sample_shop
  • لایک12,400
  • نظر86
  • نرخ تعاملنامعلوم
Brand Studioحذف‌شده از منبعنسخهٔ بایگانی
@brand.studio
رونمایی محصول جدید با حضور مشتری‌ها برگزار شد. گزارش کامل و عکس‌های مراسم: https://example.com/launch#photos
  • لایک12,400
  • نظر86
  • نرخ تعامل2.1٪
فروشگاه نمونهمحتوای حساس
@sample_shop
جشنوارهٔ تخفیف فصلی از امروز شروع شد و تا پایان هفته ادامه دارد. برای دیدن فهرست محصولات و شرایط ارسال به صفحهٔ فروشگاه سر بزنید. #تخفیف #پاییز
  • لایک12,400
  • نظر0
  • نرخ تعامل2.1٪
وضعیتنمایش
loadingاسکلت همان چیدمان (بدون داده هم کار می‌کند: <Post state="loading" />)
processing / failedپست با نشان «در حال پردازش» / «پردازش ناموفق بود»
unavailable / privateپست با نشان «در دسترس نیست» / «خصوصی»
deletedپست با نشان «حذف‌شده از منبع» و پیوند «نسخهٔ بایگانی» اگر flags.archiveUrl باشد

پرچم‌های flags (تبلیغ، همکاری تجاری، محتوای حساس، سنجاق‌شده، ویرایش‌شده) نشان کوچک می‌گیرند. پست حساس (flags.sensitive) علاوه بر نشان، همهٔ رسانه‌هایش را محو می‌کند، هر چه خود رسانه‌ها بگویند: در کارت و جزئیات هر رسانه دکمهٔ نمایش خودش را دارد و در ردیف، خلاصه، کاشی و تصویر پیش‌نمایش پیوند محو می‌ماند (رسانهٔ کامل یک کلیک دورتر، در جزئیات است)؛ کاشی متنیِ پست حساس با نشان «محتوای حساس» شروع می‌شود. سیگنال‌های تحلیل فقط وقتی نمایش داده می‌شوند که تحلیل آن‌ها را ساخته باشد، و جایشان به چیدمان بستگی دارد:

چیدمانسیگنال‌ها
row، tile، summaryشدت «بالا» یا «فوری» و احساسِ غیرخنثی، به‌صورت نشان‌های کوچک در ابتدای خط شاخص‌ها
card، detailsهمهٔ سیگنال‌ها (احساس، هیجان، موضع مخاطب، شدت، خوشه) و برچسب‌ها با اطمینانشان

رسانه‌ای که در حال پردازش است یا ناموفق شده و ابعاد ندارد، در کارت و جزئیات یک کادر 16:9 با برچسب وضعیت می‌گیرد؛ چرخ‌فلک اولین رسانه‌ای را نشان می‌دهد که هنوز در دسترس است.

رسانه: ذخیره‌شده، ذخیره‌نشده، بدون رسانه

بسیاری از پست‌ها (اینستاگرام و دیگران) در منبع رسانه دارند ولی ما آن را دریافت و ذخیره نکرده‌ایم؛ بعضی رسانهٔ ذخیره‌شده دارند؛ و بعضی (اغلب تلگرام و X) اصلاً رسانه ندارند. هر سه را صادقانه نشان دهید:

  • ذخیره‌شده: media: [{ kind, src, width, height }].
  • ذخیره‌نشده: media: [{ kind: 'image' | 'video', status: 'unavailable' }] (برای چندرسانه‌ای، یک مورد برای هر رسانه). همان کادر محدود کارت با نشانهٔ نوع، «رسانه ذخیره نشده است» و پیوند «مشاهده در منبع» به post.url؛ هیچ‌وقت تصویر شکسته و هیچ‌وقت شبیه بارگذاری ناموفق نیست. در ردیف فقط نشانه است.
  • بدون رسانه: media را نگذارید (نه آرایه‌ای با مورد unavailable). هیچ کادری نمایش داده نمی‌شود و کارت متنی فشرده می‌ماند؛ فقط کاشی متن را در همان کادر کاشی می‌گذارد.

failed و expired یعنی رسانه را داشتیم و بارگذاری نشد یا منقضی شد. مبدل‌ها (fromSearchContent، fromPostData) پست اینستاگرام بدون thumbnailUrl را ذخیره‌نشده و پست تلگرام یا X بدون آن را بدون رسانه می‌گیرند.

فروشگاه نمونه
@sample_shop
جشنوارهٔ تخفیف فصلی از امروز شروع شد و تا پایان هفته ادامه دارد. برای دیدن فهرست محصولات و شرایط ارسال به صفحهٔ فروشگاه سر بزنید. #تخفیف #پاییز
  • لایک12,400
  • نظر0
  • نرخ تعامل2.1٪
stored
کافه نمونه
@cafe_example2
بسته‌بندی تازهٔ محصول را در نمایشگاه دیدید؟ نظرتان را برای ما بنویسید؛ همهٔ پیام‌ها را می‌خوانیم و در طراحی نسخهٔ بعد به کار می‌بریم. @sample_shop
مشاهده در منبع
3 رسانه
  • لایک12,400
  • نظر86
  • نرخ تعاملنامعلوم
not stored
Brand Studio
@brand.studio
رونمایی محصول جدید با حضور مشتری‌ها برگزار شد. گزارش کامل و عکس‌های مراسم: https://example.com/launch#photos
  • بازدید34,000
no media
زمین بازی
فروشگاه نمونه
@sample_shop
جشنوارهٔ تخفیف فصلی از امروز شروع شد. #تخفیف
مشاهده در منبع
  • لایک1,240
  • نظر86
تنظیمات
داده
ظاهر
import { Post, type SocialPost } from '@partodata/ui/social'

const post: SocialPost = {
  "id": "playground",
  "source": {
    "key": "instagram"
  },
  "kind": "photo",
  "actor": {
    "name": "فروشگاه نمونه",
    "handle": "sample_shop"
  },
  "publishedAt": 1791613445524,
  "url": "https://www.instagram.com/p/X1/",
  "text": "جشنوارهٔ تخفیف فصلی از امروز شروع شد. #تخفیف",
  "media": [
    {
      "kind": "image",
      "status": "unavailable"
    }
  ],
  "metrics": {
    "likes": 1240,
    "comments": 86
  }
}

export function PostExample() {
  return <Post post={post} />
}

ترکیب با جایگاه‌ها

بدون children، هر چیدمان ترکیب پیش‌فرض خودش را دارد. برای ترکیب دیگر، جایگاه‌ها را بچینید: Post.Select، Post.Repost، Post.Header، Post.Text، Post.Media، Post.LinkPreview، Post.Embeds، Post.Stats، Post.Signals، Post.Tags، Post.Actions و Post.Aside. هر بخش ترکیب‌های پیش‌فرض جایگاه خودش را دارد و ترکیب دلخواه فقط جایگاه‌هایی را نمایش می‌دهد که چیده‌اید: پستِ انتخاب‌شدنی Post.Select لازم دارد.

می‌خواهیدراه
یک مقدار محصول (وضعیت، «پست 3»، رتبه) در ترکیب پیش‌فرضویژگی aside
همان مقدار در ترکیب دلخواهPost.Aside (ویژگی aside نادیده می‌ماند)
ترتیب یا بخش‌های دیگرchildren با جایگاه‌ها

در محیط توسعه، اگر ترکیب دلخواهِ پست انتخاب‌شدنی Post.Select نداشته باشد یا aside کنار children داده شود، یک هشدار در کنسول می‌آید.

'use client'

import { Post, type SocialPost } from '@partodata/ui/social'

export function AnalysisSubject({ post }: { post: SocialPost }) {
  return (
    <Post post={post} layout="summary">
      <Post.Media />
      <div className="flex min-w-0 flex-1 flex-col gap-1.5">
        <Post.Header />
        <Post.Text maxLines={2} />
        <Post.Stats keys={['likes', 'comments']} />
      </div>
      <Post.Aside>
        <span className="text-meta">پست 3</span>
      </Post.Aside>
    </Post>
  )
}

در کامپوننت سرور <Post … /> را بدون جایگاه به کار ببرید؛ ماژول‌های 'use client' در سرور قابل نقطه‌گذاری نیستند (Post.Header خطا می‌دهد). ترکیب با جایگاه‌ها و هر onOpen یا actions در کامپوننت کلاینت است.

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

بکنید

  • فهرست تک‌ستونی (card یا row) را در ستون فید (حدود 680 پیکسل) بگذارید و شبکهٔ tile را در عرض پهن؛ EntityCollection همین قاعده را اجرا می‌کند.
  • ابعاد رسانه را در مبدل بدهید (mediaSize) تا کادر از ابتدا درست باشد.
  • priority را فقط برای دو یا سه مورد اول بالای صفحه بگذارید.
  • شاخص‌هایی را که محصول لازم دارد با metrics انتخاب کنید و ترتیبشان را همان‌جا تعیین کنید؛ فهرستِ row همیشه metrics بدهد (دو تا چهار شاخص). ردیف و کاشی شاخص‌ها را در یک خط نگه می‌دارند و شاخصی را که جا نشود کامل کنار می‌گذارند.
  • ردیف و کارت را در ستونی با عرض معین بگذارید؛ ردیف ظرف (container) خودش است و داخل والدی که عرضش از محتوا می‌آید (مثل inline-flex یا خانهٔ جدول با عرض خودکار) عرضش صفر می‌شود.

نکنید

  • مقدار نامعلوم را با 0 پر نکنید و آمار حساب را در post.metrics نگذارید؛ مبدل‌ها این را درست انجام می‌دهند.
  • کلیک اصلی را به منبع نفرستید؛ «مشاهده در منبع» اقدام جداست.
  • برای حالت حذف‌شده یا در حال پردازش کامپوننت یا کارت جدا نسازید؛ state را تنظیم کنید.
  • دکمه‌های محصول را داخل متن یا سربرگ نسازید؛ با actions بدهید.

Props

Post

Prop

Type

Post.Text / PostTextProps

Prop

Type

Post.Media / PostMediaProps

Prop

Type

Post.Stats / PostStatsProps

Prop

Type

Post.Actions / PostActionsProps

Prop

Type

Post.Select، Post.Repost، Post.Header، Post.LinkPreview، Post.Embeds، Post.Signals، Post.Tags و Post.Aside ویژگی خاص خودشان را ندارند و ویژگی‌های HTML را می‌پذیرند. Post.Signals در row، tile و summary مجموعهٔ کوچک (شدت بالا یا فوری و احساسِ غیرخنثی؛ احساس خنثی نشانه‌ای برای مرور سریع نیست) و در card و details همهٔ سیگنال‌ها را نمایش می‌دهد.

EntityAction

فیلدنوعتوضیح
idstringشناسهٔ پایدار
labelstringبرچسب منو و نام دسترس‌پذیر دکمهٔ آیکونی
iconReact.ReactNodeعنصر آیکون؛ اقدام بدون آیکون در منو می‌آید
onSelect(item: T) => voidاجرای اقدام برای همین مورد
hrefstringاقدام پیوندی به‌جای تابع (نشانی مطلق در برگهٔ تازه)
disabledbooleanغیرفعال
tone'default' | 'destructive'اقدام حذف‌کننده

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

  • هر پست یک article است که با نام نویسنده (یا شناسه، یا منبع) نام‌گذاری می‌شود؛ وقتی باز شدنی یا انتخاب‌شدنی است فوکوس می‌گیرد و حلقهٔ فوکوس دیده می‌شود: Enter باز می‌کند و Space انتخاب را عوض می‌کند. کلیدهای جهت، Home و End به فهرست اطراف می‌رسند.
  • پیوندها، هشتگ‌ها و اقدامات کنترل‌های واقعی‌اند و Enter و Space آن‌ها به پست نمی‌رسد.
  • دکمه‌های آیکونی نام دسترس‌پذیر و راهنمای شناور دارند؛ اقدامات پنهان با فوکوس کیبورد پیدا می‌شوند.
  • پستِ در حال بارگذاری aria-busy است و یک «در حال بارگذاری» پنهان برای صفحه‌خوان دارد.
  • شناسه‌ها و دامنه‌ها جزیرهٔ چپ‌به‌راست با ارقام لاتین‌اند و متن کاربر جهت هر خط را از خودش می‌گیرد. نام، تیتر، نام برنامه، نویسندهٔ خبر، دسته، عنوان پیش‌نمایش پیوند و نام بازنشرکننده هر کدام جزیرهٔ جهت خودشان‌اند، پس «Apple Inc.» در خط فارسی نقطه‌اش را در انتها نگه می‌دارد؛ و همان قاعدهٔ ارقام SocialText را دارند: متنی که با حرف لاتین شروع شود ارقام لاتین می‌گیرد («Studio 54»، نه «Studio 54»).
  • دکمهٔ «ترجمه» در حین ترجمه فوکوس را نگه می‌دارد (غیرفعال نمی‌شود) و جابه‌جایی به ترجمه یا متن اصلی را اعلام می‌کند.

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

شبکهٔ رسانهٔ منتشرشدهٔ اکانت

وقتی خود پست محتوای اصلی است، مانند جست‌وجو و شواهد، نمایش اولیه فید تک‌ستونی کارت است. برای بخش رسانهٔ منتشرشدهٔ یک اکانت، زمینه را صریح اعلام کنید؛ این گزینه پیش‌فرض عمومی Post و نسبت 16:9 را تغییر نمی‌دهد.

<EntityCollection
  entity="post"
  context="account-published-media"
  layouts={['tile', 'card']}
  defaultLayout="tile"
  items={posts}
  getId={(post) => post.id}
  renderItem={(post, item) => (
    <Post post={post} {...item}>
      <Post.Header />
      <Post.Media />
      <Post.Stats keys={['likes', 'comments']} wrap />
      <Post.Actions />
    </Post>
  )}
/>

Post.Stats.wrap در ردیف/کاشی اجازه می‌دهد همهٔ شمارش‌های انتخاب‌شده دیده شوند و از سطر مخفی حذف نشوند؛ پیش‌فرض آن false است. پسند و نظرِ معلوم، از جمله 0، حفظ می‌شوند؛ نامعلوم «—» است و متریکِ نامرتبط نمایش ندارد. context="account-published-media" فقط برای entity="post" معتبر است و به‌تنهایی layout را تغییر نمی‌دهد.