صفحهٔ سفارشی (CustomPage)
راه خروج برای صفحهای که در هیچ قالبی جا نمیشود — همان سرِ صفحه، عرض و ریتم، با محتوای خودتان و یک DS-GAP ثبتشده
معرفی
CustomPage برای صفحهای است که در هیچکدام از قالبها جا نمیشود. سرِ صفحه (و با آن تنها h1، راه بازگشت،
اقدامها و زبانهها)، عرض نامدار و ریتم صفحه را نگه میدارد و ناحیهٔ محتوا را به شما میدهد. dsGap الزامی است: پیش از
ساختن صفحه، نیاز را بهعنوان یک DS-GAP برای مسئول طراحی ثبت کنید و شناسهاش را اینجا بنویسید؛ روی ریشهٔ صفحه
data-ds-gap مینشیند تا هر صفحهٔ سفارشی پیدا و شمرده شود. وقتی همان نیاز دو بار تکرار شد، قالب تازه میشود.
چه زمانی استفاده کنیم:
- صفحهای که واقعاً هیچ قالبی ندارد: ویرایشگر، خط زمانی رویدادها، نقشه.
چه زمانی استفاده نکنیم:
- هر صفحهای که فهرست، جزئیات، فرم، تنظیمات، داشبورد یا صفحهٔ کمکی است: قالب خودش را به کار ببرید (انتخاب قالب صفحه).
- برای گریز از یک قاعدهٔ قالب (جای اقدام، عرض): قاعده را در DS-GAP مطرح کنید.
استفاده
محتوا PageSectionهاست (از @partodata/ui) یا DetailSectionها، که ریتم صفحه را نگه میدارند:
'use client'
import { Button, PageSection } from '@partodata/ui'
import { CustomPage } from '@partodata/ui/templates'
const steps = [
{ id: 's1', title: 'اعلام کمپین تخفیف فصلی', time: 'شنبه، ساعت 10' },
{ id: 's2', title: 'اولین موج منشنها در اینستاگرام', time: 'شنبه، ساعت 14' },
]
export default function CampaignTimelinePage() {
return (
<CustomPage
dsGap="DS-GAP-12: خط زمانی رویدادهای کمپین"
title="خط زمانی کمپین"
secondaryActions={<Button variant="default">خروجی</Button>}
>
<PageSection>
<ol className="flex flex-col gap-layout-block-gap border-s border-border ps-6">
{steps.map((step) => (
<li key={step.id} className="flex flex-col gap-1">
<span className="text-sm font-medium text-foreground">{step.title}</span>
<span className="text-sm text-foreground-light">{step.time}</span>
</li>
))}
</ol>
</PageSection>
</CustomPage>
)
}حالتها و انواع
ثبت DS-GAP
- نیاز را بنویسید: صفحه چه چیزی دارد که هیچ قالبی ندارد، و کدام قالب نزدیکترین است.
- آن را برای مسئول طراحی ثبت کنید و شناسهاش را در
dsGapبگذارید. - جزء محلی با نام سیستم طراحی نسازید؛ کمترین ترکیب ممکن از اجزای موجود را داخل
CustomPageبسازید.
صفحهای که ارتفاع را پر میکند: layout="fill"
فضای کاری رسانه (پخش زنده کنار متن گفتار)، نقشه، پنلهای کنار هم، کنسول یا سندی در iframe صفحهٔ بخشهایی نیست که پیمایش
شود: layout="fill" ناحیهٔ محتوا را به اندازهٔ کل ارتفاع ناحیهٔ محتوای قاب زیر سرِ صفحه میکند. فرزندانش آن را پر
میکنند — PagePaneهایی کنار هم (از 56rem محتوا؛ پایینتر روی هم، هر کدام سهمی از ارتفاع)، یا یک عنصر تماماندازه — و
هر کدام درون خودش پیمایش میشود؛ خود صفحه هرگز پیمایش نمیشود.
- این شکلِ مجاز است، نه کمبود: صفحهٔ
fillبهdsGapنیاز ندارد و باdata-layout="fill"جدا شمرده میشود؛ شناسهٔ DS-GAP فقط وقتی لازم است که خودِ فضای کاری چیزی کم دارد. inset="none"محتوا را لبهبهلبه و به عرض کامل ناحیهٔ محتوای قاب میکند، هرwidthی که داده شده باشد (بی حاشیهٔ صفحه و فاصلهٔ پایین): نقشه، دیوار ویدیو. دیوار اپراتور کروم قاب را هم باchrome={useKioskChrome()}رویProductFrameبرمیدارد.titleHiddenفقط در همین حالت: عنوان هنوز تنهاh1صفحه است ولی فقط برای صفحهخوان — برای صفحهای که محتوایش خودش کروم است (دیوار اپراتور، نقشهٔ تمامصفحه با کنترلهای خودش). سرِ صفحه دیگر نیست، پس نه اقدام، نه زبانه، نه بازگشت.PagePaneیک ناحیهٔ عنواندار است با اقدامهای خودش — و اقدام اصلی خودش: هر پنل ناحیهٔ مستقلی است (دکمهٔ «منطقهٔ تازه»ی پنل فهرست و «ذخیره»ی پنل فرم هر کدام اقدام اصلی پنل خودشاناند).width="aside"پنلی به عرض--layout-aside-widthاست (فهرستی کنار جزئیاتش)؛ بقیه فضای باقی را میگیرند. پنلی که محتوایش باPageToolbarشروع میشود اقدام اصلیاش را یا در ردیف عنوان پنل دارد یا درprimaryActionنوارابزار — هرگز هر دو.PagePaneفقط فرزندCustomPage layout="fill"است (بیرون از آن هشدار توسعه). بدنهٔ پنل با صفحهکلید فوکوس و پیمایش میشود.
صفحهٔ تغییرات: pattern="changelog"
صفحهٔ کاملِ تغییرات محصول (فهرست نسخهها و تغییرات هر کدام) قالب جدا ندارد و کمبود هم نیست: CustomPage با
pattern="changelog" و یک ReleaseTimeline بهعنوان محتوا. به dsGap نیاز
ندارد و با data-pattern="changelog" جدا شمرده میشود. پنل «آخرین تغییرات» در سرِ صفحه همچنان
WhatsNewPanel است.
// app/(app)/changelog/page.tsx
import { CustomPage } from '@partodata/ui/templates'
import { ReleaseTimeline } from '@partodata/ui/release-timeline'
import { whatsNewFeed } from '@/content/whats-new'
export default function ChangelogPage() {
return (
<CustomPage pattern="changelog" title="تغییرات">
<ReleaseTimeline notes={whatsNewFeed.notes} />
</CustomPage>
)
}عرض
width یکی از عرضهای نامدار است: narrow 768، default 1200 (پیشفرض)، wide 1600، full بیسقف.
راهنمای استفاده
بکنید
- پیش از
CustomPageمطمئن شوید هیچ قالبی جا نمیشود. - محتوا را در
PageSectionها بگذارید تا ریتم 48 پیکسلی صفحه بماند.
نکنید
CustomPageرا برای صفحهای که قالب دارد به کار نبرید.h1یا سرِ صفحهٔ دیگری داخل محتوا نسازید.dsGapرا خالی یا ساختگی نگذارید؛ نوعش فقط شناسهای مثلDS-GAP-12: خط زمانیرا میپذیرد.
Props
CustomPage
PagePane
دسترسیپذیری
- سرِ صفحه همان سرِ صفحهٔ قالبهاست: تنها
h1، پیوند بازگشت نامدار، زبانههای نشانیدار. - دسترسپذیری محتوای سفارشی با خود شماست: سرعنوانهای بخشها از
h2شروع شوند.
کامپوننتهای مرتبط
- انتخاب قالب صفحه — پیش از
CustomPage. DetailPage— نزدیکترین قالب برای صفحهای با بخشها.- اسکلت صفحه —
PageSectionو اجزای سطح پایین صفحه.