پرتوپرتو

PostDetailsDrawer (پنل جزئیات)

پنل کناری راست برای بررسی عمیق یک پست — Surface canonical جزئیات با ناوبری j/k بین پست‌های فید.

معرفی

<PostDetailsDrawer> Surface canonical برای نمایش جزئیات کامل یک پست در دسکتاپ است. الگوی Linear inbox / Brandwatch / Gmail — کاربر می‌تواند بدون بستن پنل، با j و k به پست بعدی/قبلی در فید برود.

  • چه زمانی استفاده کنیم: برای نمایش پست انتخاب‌شده در <PostList>. در موبایل به‌طور خودکار به‌صورت full-screen bottom sheet دیده می‌شود.
  • چه زمانی استفاده نکنیم: برای modalهای موقت اطلاع‌رسانی — از <Dialog> استفاده کنید.

زمین بازی

با تغییر کنترل‌های زیر، حالت‌های مختلف پنل جزئیات را زنده ببینید — از نبود تحلیل هوشمند تا متن‌های طولانی، انواع رسانه، حالت بحرانی و پنل بدون نظرات.

زمین بازی

پنل جزئیات پست — برای مشاهده‌ی حالت‌های مختلف از کنترل‌های بالا استفاده کنید.

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

استفاده

import { PostDetailsDrawer } from '@partodata/ui'
;<PostDetailsDrawer
  open={Boolean(detailsPost)}
  onOpenChange={(o) => !o && setDetailsPost(null)}
  post={detailsPost}
  details={detailsByPostId[detailsPost.id]}
  bookmarked={bookmarkedIds.has(detailsPost.id)}
  onBookmark={handleBookmark}
  onNext={() => navigate(1)}
  onPrevious={() => navigate(-1)}
/>

Tabs

  • post — متن، رسانه، URL preview، نقل‌قول، سیگنال‌ها (sentiment/emotion/flow/severity/cluster/language)، گرید متریک‌ها. در context="detail" و url قابل پخش، video به HTML5 <video controls> تبدیل می‌شود.
  • comments — نظرات تو‌در‌تو با enrichment کامل (replyCount, edited, badge, authorReply, hiddenByModerator, toxicityScore, translatedText toggle). تو در تو با depth.
  • analysis — surface غنی شامل:
    • خلاصه پست
    • کارت سه‌گانه: نیت پیام + اطمینان مدل + تأثیرگذاری نویسنده
    • توزیع احساسات (نمودار میله‌ای ۹-کلاسه)
    • موضوعات، موجودیت‌های شناسایی‌شده (شخص/برند/مکان/…)
    • ریسک‌های شناسایی‌شده
    • اطلاعات پلتفرم (platformMeta) به صورت key-value list — متفاوت برای هر منبع (Instagram saves/location، Twitter retweet/quote، YouTube subscribers، Press AVE، …)
    • تاریخ تولید تحلیل
  • transcript — رونوشت ویدیو/صوت + OCR.

کیبورد

  • j / → پست بعدی
  • k / → پست قبلی
  • Esc → بستن

RTL

درآور در پنل‌های افکارسنجی همیشه روی لبه‌ی بصری راست ظاهر می‌شود (جایی که چشم RTL در آنجا anchor شده). پیاده‌سازی: ترکیب dir="rtl" صریح روی SheetContent + override فیزیکی (!start-auto !end-auto !right-0 !left-auto) تا از سناریوهای portal-context که dir را به ارث نمی‌برند هم امن باشد.

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

بکنید

  • details را به‌صورت lazy واکشی کنید و در طول واکشی isLoadingDetails را true بدهید — تب‌های وابسته (نظرات، تحلیل، متن استخراجی) حالت بارگذاری استاندارد را با role="status" نمایش می‌دهند.
  • onNext و onPrevious را همیشه با هم تنظیم کنید تا ناوبری j/k کامل باشد و کاربر بتواند بدون بستن پنل، کل فید را مرور کند — مثلاً بررسی پست‌های یک کمپین تخفیف فصلی پشت‌سرهم.
  • اکشن‌های اختصاصی محصول (مانند «افزودن به بولتن») را از طریق extraActions به هدر تزریق کنید — این prop دقیقاً برای همین کنار اکشن‌های پیش‌فرض رندر می‌شود.
  • وضعیت باز/بسته را در والد نگه دارید (open / onOpenChange) — کامپوننت controlled است و معمولاً PostList با onOpenDetails آن را باز می‌کند.

نکنید

  • دکمه بستن دستی اضافه نکنید — primitive Sheet خودش دکمه بستن (X) را با متن sr-only در گوشه بالا رندر می‌کند و دکمه تکراری کاربران صفحه‌خوان را سردرگم می‌کند.
  • تب‌های بدون داده را دستی مخفی یا شرطی نکنید — کامپوننت خودش تب‌های فاقد داده را disabled می‌کند و اگر defaultTab به تب غیرفعال اشاره کند، به‌طور خودکار به post برمی‌گردد.
  • نتیجه onTranslate را خودتان در post.body ننویسید — کامپوننت toggle «نمایش متن اصلی / نمایش ترجمه» و کش ترجمه را داخلی مدیریت می‌کند و با تغییر post.id آن را ریست می‌کند.
  • برای تأیید عملیات مخرب (مانند حذف پست از آرشیو) از این پنل استفاده نکنید — از AlertDialog استفاده کنید؛ این پنل Surface مرور و تحلیل است، نه تصمیم‌گیری بازگشت‌ناپذیر.

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

Prop

Type

PostDetails

Prop

Type

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

  • پنل روی primitive Sheet (Radix Dialog) ساخته شده است: هنگام باز شدن role="dialog" و aria-modal دارد، فوکوس داخل پنل trap می‌شود و هنگام بستن به عنصر قبلی برمی‌گردد.
  • عنوان دیالوگ با SheetTitle مخفی (sr-only) به‌صورت «جزئیات پست از (نام نویسنده)» رندر می‌شود — صفحه‌خوان نام دیالوگ را با هویت پست اعلام می‌کند، بدون تکرار بصری هدر.
  • دکمه بستن داخلی Sheet متن sr-only «بستن» دارد؛ همه اکشن‌های آیکنی هدر aria-label دارند: «نشانه‌گذاری / حذف از نشان‌شده‌ها»، «کپی لینک» و «مشاهده در مبدأ». پس از کپی موفق، aria-label دکمه کپی به «کپی شد» تغییر می‌کند.
  • تب‌ها Radix Tabs هستند (role="tablist" / tab / tabpanel) با ناوبری Arrow بین triggerها؛ تب‌های فاقد داده disabled می‌شوند و از ترتیب فوکوس خارج‌اند.
  • میان‌برهای j/k// فقط وقتی پنل باز است فعال‌اند و اگر فوکوس داخل input یا textarea باشد، غیرفعال می‌شوند تا تایپ کاربر ربوده نشود. Esc را خود Sheet مدیریت می‌کند (بخش «کیبورد» بالا).
  • حالت بارگذاری هر تب با role="status" و aria-busy="true" رندر می‌شود تا صفحه‌خوان در جریان واکشی details قرار بگیرد.
  • در نمودار «توزیع احساسات»، هر میله role="progressbar" با aria-valuenow/aria-valuemin/aria-valuemax و aria-label شامل نام احساس و درصد آن است.

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

  • برای فید خود پست‌ها → <PostList> (که با onOpenDetails خودش drawer را باز می‌کند)
  • برای quoted/embedded posts درون drawer → <PostQuotedEmbed> (رندر می‌شود وقتی post.quoted ست شده)
  • برای اکشن‌های گروهی روی پست‌های انتخاب‌شده → <PostBulkActionBar>