پنل کناری (Sheet)
پنل کشویی از کنار صفحه
معرفی
کامپوننت Sheet یک پنل کشویی است که از کنار صفحه ظاهر میشود.
چه زمانی استفاده کنیم:
- برای فرمهای بلند (بیش از 5 فیلد) که در Dialog جا نمیشوند
- برای پنلهای جزئیات (detail panel) در کنار لیست اصلی
- برای تنظیمات، فیلترهای پیشرفته، یا پنلهای ویرایش در desktop
چه زمانی استفاده نکنیم:
- برای محتوای کوچک مثل تأیید — از
Dialogاستفاده کنید - برای تأیید اعمال مخرب — از
AlertDialogاستفاده کنید - برای filter panel در موبایل — از
Drawerاستفاده کنید
زمین بازی
با تغییر تنظیمات زیر، پیشنمایش زنده را مشاهده کنید.
import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, Button, SheetDescription } from '@partodata/ui'
<Sheet>
<SheetTrigger asChild>
<Button type="default" size="sm">باز کردن پنل</Button>
</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>عنوان پنل</SheetTitle>
<SheetDescription>توضیحات پنل کناری.</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>استفاده
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from '@partodata/ui'
import { Button } from '@partodata/ui'
export default function MyComponent() {
return (
<Sheet>
<SheetTrigger asChild>
<Button>باز کردن</Button>
</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>عنوان</SheetTitle>
<SheetDescription>توضیحات در اینجا قرار میگیرد</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
)
}حالتها و انواع
پیشفرض
جهتهای مختلف
Sheet از چهار جهت باز شدن پشتیبانی میکند: end (پیشفرض)، start، top و bottom.
مقادیر start و end منطقی (logical) هستند و با جهت صفحه میچرخند: end یعنی لبهٔ پایانیِ خط خواندن — در RTL سمت چپ و در LTR سمت راست. top و bottom فیزیکیاند و تغییر نمیکنند.
<Sheet>
<SheetTrigger asChild>
<Button variant="outline">از بالا</Button>
</SheetTrigger>
<SheetContent side="top">
<SheetHeader>
<SheetTitle>عنوان</SheetTitle>
</SheetHeader>
</SheetContent>
</Sheet>حالت بخشبندیشده (sectioned)
با sectioned روی SheetContent، سربرگ و فوتر خطدار میشوند و بدنه در یک SheetBody اسکرولشونده قرار میگیرد — مناسب فرمهای چندبخشی و پنلهای تنظیمات طولانی.
import {
Sheet,
SheetTrigger,
SheetContent,
SheetHeader,
SheetTitle,
SheetBody,
SheetFooter,
Button,
} from '@partodata/ui'
;<Sheet>
<SheetTrigger asChild>
<Button>ویرایش کمپین</Button>
</SheetTrigger>
<SheetContent sectioned>
<SheetHeader>
<SheetTitle>ویرایش کمپین</SheetTitle>
</SheetHeader>
<SheetBody>{/* فیلدهای فرم */}</SheetBody>
<SheetFooter>
<Button variant="outline">انصراف</Button>
<Button variant="primary">ذخیره</Button>
</SheetFooter>
</SheetContent>
</Sheet>سمتهای مختلف
<SheetContent side="end"> {/* پیشفرض — لبهٔ پایانی: چپ در RTL، راست در LTR */}
<SheetContent side="start"> {/* لبهٔ آغازین: راست در RTL، چپ در LTR */}
<SheetContent side="top">
<SheetContent side="bottom">left و right در 5.0 حذف شدند
left و right تا 4.x نامهای قدیمی start و end بودند (right دقیقاً end و left دقیقاً start، نه راست و چپ
فیزیکی). از 5.0 فقط start/end پذیرفته میشوند.
راهنمای استفاده
بکنید
- از
sideمناسب استفاده کنید —endبرای پنلهای جزئیات،startبرای ناوبری - همیشهSheetTitleوSheetDescriptionرا ارائه دهید - برای فرمهای داخل Sheet، دکمه ذخیره را در پایین Sheet قرار دهید
نکنید
- از Sheet در موبایل استفاده نکنید — از
Drawerاستفاده کنید - Sheet های تودرتو ایجاد نکنید - محتوای بسیار کوتاه (مثل یک پیام تأیید) را در Sheet قرار ندهید — ازDialogاستفاده کنید
جدول ویژگیها
Sheet
SheetContent
رفتار در RTL
پراپ side در این کامپوننت به صورت منطقی (logical) عمل میکند، نه فیزیکی:
-
side="end"(پیشفرض) سمت «انتها»ی خط خواندن است:- در چیدمان RTL: سمت چپ صفحه
- در چیدمان LTR: سمت راست صفحه
-
side="start"سمت «ابتدا»ی خط خواندن است:- در چیدمان RTL: سمت راست صفحه
- در چیدمان LTR: سمت چپ صفحه
-
side="top"وside="bottom"فیزیکی هستند و با تغییر جهت صفحه تغییر نمیکنند.
قاعدهٔ سمت: جزئیات و فیلترها همیشه از end باز میشوند (پیشفرض؛ در RTL از چپ): EntityDrawer، پنل جزئیات
URL، جزئیات پست (Post با layout="details") و پنل فیلتر موبایل (FilterPanel داخل Sheet). ناوبری از start باز میشود (در RTL از
راست): منوی موبایل ProductFrame و NavRail. فقط نامهای منطقی را بنویسید.
- نامهای فیزیکی
side="right"وside="left"در 5.0 حذف شدند؛side="right"در RTL پنل را سمت چپ میآورد.
دسترسیپذیری
- با Escape بسته میشود
- focus trap برای پیمایش کیبورد
- از
role="dialog"وaria-modalاستفاده میشود - اسکرول صفحه در هنگام باز بودن قفل میشود
- هنگام بستن، Radix فوکوس را به
SheetTriggerبرمیگرداند. Sheetی که controlled است وSheetTriggerندارد (از یک کارت، سطر جدول یا دکمهی بیرونی باopenباز میشود) باید خودش فوکوس را برگرداند؛ وگرنه فوکوس روی<body>میافتد و Tab بعدی از بالای صفحه شروع میشود.onOpenAutoFocusپیش از آنکه فوکوس وارد پنل شود صدا زده میشود، پسdocument.activeElementدر آن هنوز همان عنصر بازکننده است:
const returnFocus = React.useRef<HTMLElement | null>(null)
<SheetContent
onOpenAutoFocus={() => {
returnFocus.current = document.activeElement as HTMLElement | null
}}
onCloseAutoFocus={(event) => {
event.preventDefault()
returnFocus.current?.focus()
}}
>EntityDrawer این کار را خودش انجام میدهد؛ WhatsNewPanel و NavRail در موبایل فوکوس را به triggerRef برمیگردانند.
تعامل با کیبورد
Escape: بستن شیت -Tab: حرکت بین عناصر داخل شیت (فوکوس محبوس) -Shift + Tab: حرکت معکوس فوکوس
کشوی پایین روی موبایل: Drawer
Drawer (کشیدنی با انگشت) فقط برای کشوی پایینِ صفحههای لمسی است (مرجع). برای هر پنل کناری Sheet را به کار ببرید؛ مقدارهای start و end در Drawer منسوخاند.
کامپوننتهای مرتبط
- Drawer — وقتی در موبایل نیاز به پنل دارید (از پایین صفحه باز میشود)
- Dialog — وقتی محتوا کوتاه است و نیاز به پنل کناری کامل ندارید
- AlertDialog — برای هشدارهای اجباری که کاربر باید حتماً تأیید کند