PostMedia (پستمدیا)
رندرر چندحالتهی رسانه برای پستها — تکتصویری، گرید، کاروسل، ویدیو، صوت با حالتهای loading / failed / unavailable / expired / source-removed و بلر NSFW.
معرفی
<PostMedia> تنها رندهرر canonical برای محتوای رسانهای پستهاست. روی body.type در PostBodyData دیسپچ میکند و همهی حالتهای دانلود/کیفیت/حساسیت را با یک API مدیریت میکند.
چه زمانی استفاده کنیم:
- هرجا که در داخل
<PostCard>یا<PostDetailsDrawer>رسانهی پست را رندر میکنید. - وقتی بدنهی پست (
PostBodyData) چند شکل دارد (تکتصویر، گرید، کاروسل، ویدیو، صوت، استوری) و میخواهید یک dispatcher واحد همه را پوشش دهد. - وقتی وضعیت دانلود (loading / failed / unavailable / expired) یا محتوای حساس (nsfw / graphic / spoiler) باید با قرارداد یکسان placeholder و blur مدیریت شود.
چه زمانی استفاده نکنیم:
- برای تصاویر تکی غیر پست — به جای آن از
<SafeImage>یا<AspectRatio>استفاده کنید. - برای بدنهی صرفاً متنی —
<PostMedia>باbody.type === 'text'هیچچیزی رندر نمیکند؛ متن را<PostBody>والد رندر میکند. - برای گالری تصاویر مستقل از ساختار پست — از
Carouselپایه استفاده کنید.
زمین بازی
زمین بازی
تنظیمات
ظاهر
کد این نمونه بهصورت خودکار قابل تولید نیست — برای کد آمادهی copy/paste به بخش «استفاده» در بالای صفحه مراجعه کنید.
استفاده
import { PostMedia } from '@partodata/ui'
;<PostMedia body={post.body} context="comfortable" onRetry={(item) => refetch(item.url)} />حالتها
media-single— تکتصویر؛ در فید کراپ (cover) و در نمای جزئیات letterbox با backdrop بلرشدهmedia-grid(۲–۴ تصویر) — لِیاوت Instagram-stylemedia-carousel(۵+) — اسلایدر با dots + countervideo— تامبنیل + play overlay + duration chipaudio— waveform + play (مناسب رادیو/voice-note)- وضعیت
loading— shimmer placeholder - وضعیت
failed— placeholder با دکمهی تلاش مجدد - وضعیت
unavailable— placeholder «در سامانه ذخیره نشده» - وضعیت
expired— رسانه ضبط شده اما از بازهی نگهداری خارج شده (مثلاً کلیپهای پخش ~۳۰ روزه) source-removed— اعلان بایگانی + دکمهی «نمایش بایگانی»sensitivity(nsfw/graphic/spoiler) — بلر با reveal کلیکی
راهنمای استفاده
بکنید
contextرا با جایگاه واقعی رندر ست کنید:compactبرای ردیفهای فشرده،comfortableبرای فید،detailبرای درآور جزئیات — انتخاب کراپ (cover) یا letterbox + بکدراپ بلور از همین prop میآید.- برای هر
PostMediaItemمتنaltتوصیفی بدهید — رندرر آن را مستقیم روی<img alt>میگذارد و در نبودشalt=""رندر میشود؛ یعنی تصویر برای صفحهخوان عملاً نامرئی است. onRetryرا پاس بدهید تا آیتمهایstatus: 'failed'دکمه «تلاش مجدد» داشته باشند — بدون آن placeholder بدون CTA رندر میشود.- نسبت ابعادی طبیعی (
aspectRatio) هر آیتم را پاس بدهید و کراپ/letterbox را به کامپوننت بسپارید. - برای حساسیت سطح پست (
PostFlags.sensitive) ازsensitiveOverrideاستفاده کنید تا کل ناحیهی رسانه یکجا blur شود؛ حساسیت تکآیتمی را رویitem.sensitivityبگذارید.
نکنید
- آیتمهای بیش از ۴ تا را برای گرید خودتان slice نکنید — گرید چهار تای اول را نشان میدهد و روی سلول آخر چیپ «+N» میگذارد.
- وضعیت reveal محتوای حساس را بیرون از کامپوننت نگه ندارید — رضایت reveal به ازای هر مدیا است و با تغییر
item.urlعمداً ریست میشود؛ state موازی این قرارداد را میشکند. - بهجای
status: 'failed'یا'unavailable'، تگ<img>شکسته یا placeholder دستساز رندر نکنید. expiredرا باunavailableجایگزین نکنید — expired یعنی رسانه ضبط شده بود و از بازهی نگهداری خارج شده است؛ متن اعلان این دو عمداً متفاوت است.- تصویر حساس را با
thumbnailUrlدر کامپوننت دیگری بدون blur نمایش ندهید —PostMediaThumbهمین قرارداد blur را در سایز کوچک هم اجرا میکند و reveal در آن سایز عمداً وجود ندارد.
Props
<PostMedia> علاوه بر props زیر، همهی React.HTMLAttributes<HTMLDivElement> (مثل className) را میپذیرد. ثابتهای CENTERED_CONTAINER_CLS، FOREGROUND_IMG_CLS و SENSITIVITY_LABEL نیز export میشوند تا الگوی مرکزچینی رسانه و برچسبهای حساسیت در مصرفکنندهها یکسان بماند.
PostMedia
PostMediaSingle
PostMediaGrid
PostMediaCarousel
PostMediaVideo
PostMediaAudio
PostMediaStory
PostMediaHighlight
PostMediaPlaceholder
PostMediaSourceRemoved
PostMediaSensitiveOverlay
PostMediaThumb
KeywordSnippet
BlurBackdrop
دسترسیپذیری
جریان متن جایگزین (alt)
PostMediaItem.altمستقیم روی<img alt>مینشیند. اگر ست نشود،alt=""رندر میشود تا صفحهخوان URL تصویر را نخواند — پس برای تصاویر informative حتماً alt توصیفی بدهید.- لایههای decorative همیشه از درخت دسترسی خارج هستند: بکدراپ بلور (
aria-hidden="true"+alt="")، میلهها/تصویر waveform، dot indicator های کاروسل، و آیکن بزرگنمایی روی هاور.
محتوای حساس (blur + reveal)
- overlay مربوط به reveal یک
<button type="button">واقعی است باaria-label«نمایش محتوای حساس / محتوای تصویری شدید / افشاگر داستان» — با Tab فوکوس میگیرد و با Enter یا Space فعال میشود. - در حالت
sensitiveOverride، ناحیهی blur شدهaria-hidden="true"وpointer-events-noneدارد — صفحهخوان فقط دکمهی reveal را میبیند و محتوای زیر blur افشا نمیشود. - reveal به ازای هر مدیا نگه داشته میشود و با تغییر
item.url(مثلاً ناوبری j/k در درآور) ریست میشود — رضایت کاربر به مدیای بعدی نشت نمیکند. - reveal یکطرفه است: دکمهای برای blur مجدد وجود ندارد؛ بازگشت به حالت blur تنها با تغییر مدیا اتفاق میافتد.
- در سایز thumbnail (
PostMediaThumb) reveal عمداً وجود ندارد — فقط blur + آیکن قفل؛ نمایش محتوای حساس به نمای جزئیات واگذار میشود.
کاروسل و هایلایت
- فلشهای قبلی/بعدی کاروسل دکمههای واقعی با
aria-label="اسلاید قبلی"/aria-label="اسلاید بعدی"هستند، در دو انتهاdisabledمیشوند و باfocus-visibleحتی بدون هاور ظاهر میشوند. - جهت فلشها از جهت واقعی سند (
useDocumentDirection) خوانده میشود، نه از variantrtl:— در پرتالهای Radix و iframe ها هم درست میماند. - dot indicator ها decorative (
aria-hidden="true") هستند؛ موقعیت اسلاید با چیپ متنی «X از Y» (ارقام فارسی) منتقل میشود. - فلشهای پیمایش هایلایت نیز
aria-label="استوری قبلی"/aria-label="استوری بعدی"دارند و در ابتدا و انتهای مجموعهdisabledمیشوند.
وضعیتها و پخش
- placeholder بارگذاری
role="status"وaria-busy="true"باaria-label="در حال بارگذاری تصویر"دارد — صفحهخوان وضعیت را اعلام میکند. - دکمهی play صوت
aria-labelپویا دارد («پخش صوت» / «توقف پخش») و بدون URL قابلپخشdisabledمیشود. - ویدیو در نمای جزئیات
<video controls>بومی است — کنترل کیبوردی مرورگر (Space، فلشها) کار میکند. مدیای خزیدهشده caption track ندارد؛ رونوشت در تب جداگانهی درآور ارائه میشود.
تعامل با کیبورد
Tab: انتقال فوکوس بین کنترلهای تعاملی — دکمه reveal محتوای حساس، فلشهای کاروسل/هایلایت، دکمه play صوت، «تلاش مجدد»، و کنترلهای<video>-EnterیاSpace: فعالسازی کنترل فوکوسشده (reveal، پخش/توقف، پیمایش اسلاید) - فلشهای کاروسل روی فوکوس کیبورد (focus-visible) نمایان میشوند، حتی بدون هاور - کنترلهایdisabled(انتهای کاروسل، صوت بدون URL) از ترتیب فعالسازی خارج میشوند
کامپوننتهای مرتبط
- اگر فقط متن نمایش میدهید → از
<PostBody>خود<PostCard>استفاده کنید - اگر میخواهید چندین کارت در فید نمایش دهید → از
<PostList>بهجای رندر مستقیم<PostMedia>