بنر محدودیت نرخ (RateLimitBanner)
Banner برای هشدار فعال بودن rate-limit — شمارش معکوس live، دکمه retry اختیاری، و ترکیب با actionType برای context.
معرفی
RateLimitBanner به کاربر اعلام میکند که یک عملیات در حال حاضر توسط پلتفرم rate-limit شده و باید تا زمان مشخصی صبر کرد. شمارش معکوس live (هر ثانیه بهروز میشود) + دکمه retry اختیاری + context از ActionTypeKey.
برخلاف QuotaProgressBar که «نزدیک شدن به سقف» را نشان میدهد، این banner بعد از برخورد با سقف میآید: «پلتفرم گفت صبر کن، X دقیقه دیگر تلاش کن.»
چه زمانی استفاده کنیم:
- وقتی backend گزارش میدهد worker با rate-limit از سمت Instagram مواجه شده
- در داشبورد وقتی یک عملیات متوقف شده و
resumeAtمشخص است - بالای کارت worker یا در top-of-page برای هشدار جدی
- در admin panel برای نمایش rate-limit سمت API
چه زمانی استفاده نکنیم:
- برای هشدار فقط «نزدیک به سقف» — از
QuotaProgressBarاستفاده کنید - برای خطاهای عمومی (نه rate-limit) — از
BannerیاAlertاستفاده کنید - برای toast موقت — از
sonnerاستفاده کنید
زمین بازی
با تغییر تنظیمات زیر، پیشنمایش زنده را مشاهده کنید.
استفاده
'use client'
import { RateLimitBanner } from '@partodata/ui'
export function WorkerFeed({ worker }) {
if (!worker.rateLimit?.isActive) return null
return (
<RateLimitBanner
resumeAt={worker.rateLimit.resumeAt}
actionType="like"
reason="پلتفرم نرخ پسند این حساب را موقتاً کاهش داده است."
onRetryNow={() => retryWorker(worker.id)}
/>
)
}شمارش معکوس live
countdown هر ثانیه بهروز میشود:
با live={true} (پیشفرض)، یک setInterval هر ثانیه state را re-render میکند و formatTimeRemaining دوباره محاسبه میکند. در صفحاتی که banner طولانی مدت باز میماند، این اطلاعات دقیق به کاربر میدهد. اگر کاربر prefers-reduced-motion: reduce فعال کرده باشد، این tick بهجای هر ثانیه به هر ۳۰ ثانیه کند میشود تا از churn بصری کم شود بدون اینکه شمارش معکوس از دست برود.
اگر نیاز به performance بالا دارید یا در تستها، live={false} کنید.
ترکیب با actionType
با actionType، عنوان به «محدودیت نرخ فعال — پسندیدن» (مثلاً) تغییر میکند و data-action-type روی root میآید — برای CSS یا telemetry.
variant warning (کمتر جدی)
برای سناریوهایی که rate-limit موقت و کمخطر است (مثلاً backend gateway با ۴۰ req/h)، variant="warning" رنگ کهربایی میدهد به جای قرمز.
با دکمه retry
کلیک روی «تلاش مجدد» تعداد را افزایش میدهد: 0
وقتی onRetryNow تنظیم شود، دکمه «تلاش مجدد» در سمت end banner ظاهر میشود. کاربر میتواند override کند و سعی کند قبل از پایان cooldown.
Props
helper formatTimeRemaining
در کنار کامپوننت، تابع formatTimeRemaining(target, locale) هم export میشود — اگر خودتان میخواهید countdown سفارشی بسازید:
import { formatTimeRemaining } from '@partodata/ui'
formatTimeRemaining(new Date('2026-04-25T10:00:00Z'), 'fa')
// → "۲ ساعت و ۳۰ دقیقه دیگر"
formatTimeRemaining(Date.now() + 45_000, 'en')
// → "in 45s"راهنمای استفاده
بکنید
- وقتی پلتفرم/backend صراحتاً rate-limit برگرداند و
resumeAtمشخص است این banner را نمایش دهید — کاربر منتظر چه زمانی میماند را دقیق میفهمد - برای rate-limit جدی (block پلتفرم) ازvariant="destructive"و برای gateway موقت ازvariant="warning"استفاده کنید - وقتی retry override واقعاً شدنی است (مثل proxy جدید)onRetryNowبدهید؛ در غیر این صورت دکمه را پاس ندهید تا کاربر صبر کند - باactionTypecontext را غنی کنید — کاربر میفهمد محدودیت روی like است نه comment
نکنید
- برای خطاهای transient (network blip, 500) از این banner استفاده نکنید — از
Sonnertoast استفاده کنید - برای هشدار «نزدیک به سقف» (نه برخورد به سقف) از این استفاده نکنید — ازQuotaProgressBarمکمل استفاده کنید - چندین RateLimitBanner را در یک صفحه انباشت نکنید — اولویتبندی کنید و فقط جدیترین rate-limit را نمایش دهید -live={true}را در صفحاتی که چند banner همزمان دارند روی همه فعال نکنید — هر کدامsetIntervalجداگانه میسازد
دسترسیپذیری
- Banner از
<Banner>زیرین استفاده میکند کهrole="banner"دارد — landmark در landmark tree ساخته میشود. - عنوان + دلیل + countdown همگی متن هستند؛ screen reader ترتیب خوانایی درستی دارد.
- دکمه retry یک
<button type="button">استاندارد با focus ring است. - در حالت
dismissible, دکمه × یک button باaria-label="بستن"است (این مقدار درBannerزیرین hardcode شده و locale-aware نیست). - countdown با
data-slot="rate-limit-countdown"markup شده — وقتیlive={true}هر ثانیه بهروز میشود ولی screen reader re-announce نمیکند (هنوز live region نیست؛ برای جلوگیری از اسپم). اگر نیاز به اعلان هر دقیقه داشتید،aria-live="polite"را به عنوان override اضافه کنید. - motion-safe — countdown با react state هست، نه CSS animation؛ و در
prefers-reduced-motion: reduceنرخ بهروزرسانی از هر ۱ ثانیه به هر ۳۰ ثانیه کند میشود.
کامپوننتهای مرتبط
- QuotaProgressBar — هشدار «نزدیک به سقف»؛ این banner مکمل است برای «بعد از سقف»
- Banner — banner عمومی؛ این کامپوننت روی آن بنا شده
- Alert — alert سطح component (نه صفحه) برای خطاهای غیر-rate-limit
- ActionTypeChip — نمایش نوع عملیات بهصورت chip جداگانه