نوار پیشرفت ناوبری (RouteProgress)
نوار گرادیانی نازک بالای صفحه برای نمایش transition روت یا job های بلند — با trickle خودکار
معرفی
RouteProgress یک نوار گرادیانی ۲px که روی لبهی بالای صفحه شناور است. سه حالت استفاده:
(۱) controlled با active prop،
(۲) imperative با start() / finish() روی ref،
(۳) fully controlled با مقدار عددی value در [0, 1].
چه زمانی استفاده کنیم:
- هنگام transition روت در Next.js (
router.events.on('routeChangeStart'...)) — به کاربر feedback لحظهای میدهد - برای upload فایل یا job بلند (مقدار مشخص)
- برای هر عملیات async که UI را بلاک نمیکند اما کاربر باید بداند در حال اجراست
چه زمانی استفاده نکنیم:
- برای loading state کامپوننت خاص — از
SkeletonیاChartLoadingSkeletonاستفاده کنید - برای progress بلندمدت با مقدار مشخص درون کارت/فرم — از
Progressمعمولی استفاده کنید - برای پیامهای موفقیت/خطا — از
ToastیاBannerاستفاده کنید
نوار بالای این کادر را تماشا کنید — با کلیک روی دکمهها حرکت میکند.
زمین بازی
با تغییر تنظیمات زیر، پیشنمایش زنده را مشاهده کنید.
زمین بازی
محتوای صفحه — نوار پیشرفت در بالا
تنظیمات
حالت
ظاهر
2px
چیدمان
کد این نمونه بهصورت خودکار قابل تولید نیست — برای کد آمادهی copy/paste به بخش «استفاده» در بالای صفحه مراجعه کنید.
سه حالت استفاده
حالت ۱: Controlled با active
const [isNavigating, setIsNavigating] = React.useState(false)
<RouteProgress active={isNavigating} />مادامی که active={true} بار ترقهای تا trickleCap (پیشفرض ۰.۹) جلو میرود. با active={false} snap به ۱۰۰٪ و fade out.
controlled: active prop — trickles while true، snaps to 100٪ هنگام false.
حالت ۲: Imperative با ref
const ref = React.useRef<RouteProgressHandle>(null)
router.events.on('routeChangeStart', () => ref.current?.start())
router.events.on('routeChangeComplete', () => ref.current?.finish())
<RouteProgress ref={ref} />حالت ۳: Fully controlled (مقدار)
const progress = useUploadProgress() // 0..1 از upload
<RouteProgress value={progress} />وقتی value دستدست شده، بار نه trickle نه fade میکند — دقیقاً همانجاست که گذاشتید.
ادغام با Next.js App Router
در Next.js 14+ که event loop router آن تغییر کرده، راحتترین راه استفاده از useTransition در کنار useRouter:
'use client'
import { useRouter } from 'next/navigation'
import { useTransition } from 'react'
import { RouteProgress } from '@parto-system-design/ui'
export function NavLink({ href, children }) {
const router = useRouter()
const [pending, start] = useTransition()
return (
<>
<RouteProgress active={pending} />
<a
onClick={(e) => {
e.preventDefault()
start(() => router.push(href))
}}
>
{children}
</a>
</>
)
}Props
RouteProgressHandle (ref)
type RouteProgressHandle = {
start: () => void // reset + show + trickle
finish: () => void // snap to 100% + fade out
}راهنمای استفاده
بکنید
- از
activeبرای route transitionها استفاده کنید — API تمیزتر از ref است -trickleCapرا کم نکنید — ۰.۹ حس انتظار طبیعی میدهد، ۰.۷ کاربر را میترساند که «گیر کرده» -prefers-reduced-motionتوسط browser بصورت خودکار احترام نهاده میشود — نوار همچنان کار میکند اما animation سادهتر
نکنید
activeوvalueرا همزمان پاس ندهید — رفتار غیرقابلپیشبینی میشود - چند RouteProgress همزمان در صفحه mount نکنید — فقط یک نوار گلوبال، درlayout.tsxریشه - نوار را برای loading صفحهی کل استفاده نکنید وقتی UI زیرش بلاک است — ازPageLoaderاستفاده کنید
دسترسیپذیری
role="progressbar"+aria-valuenow+aria-valuemin/max— assistive tech درصد را میخواندpointer-events-none— روی کلیکپذیری المانهای زیر تأثیر نمیگذاردz-indexبالاتر از tooltip — روی مودالها هم پیداست (هدف: هشدار بصری transition)
کامپوننتهای مرتبط
- Progress — برای progress درونصفحهای (کارت، فرم)
- Spinner — برای loading کوچک درون دکمه
- PageLoader — برای blocking loading صفحهی کامل
- SiteHeader — معمولاً بالای هدر قرار میگیرد