حالتهای خالی
راهنمای حالتهای خالی — صفر نتیجه، فهرست خالی، صفحهٔ خالی و مسیر گمشده؛ هر کدام یک پاسخ دارد و در صفحه قالب آن را میکشد
معرفی
حالتهای خالی زمانی ظاهر میشوند که محتوایی برای نمایش وجود ندارد. یک حالت خالی خوب سه کار انجام میدهد: وضعیت را توضیح میدهد، علت را بیان میکند، و راه ادامه را نشان میدهد.
در صفحههای اپلیکیشن این حالتها را خودتان نمیسازید: هر کدام یک پاسخ دارد و قالب صفحه آن را میکشد. حالت خالی جای کل فهرست مینشیند؛ سرستونهای جدول نمیمانند و ردیفی داخل جدول ساخته نمیشود.
نمونه بصری
صفر نتیجه — جستوجو یا فیلتری فعال است
نتیجهای یافت نشدنتیجهای یافت نشد
عبارت جستوجو یا فیلترها را تغییر دهید.
فهرست خالی — بدون فیلتر
هنوز اینفلوئنسری ثبت نشده استهنوز اینفلوئنسری ثبت نشده است
پیادهسازی
Empty از نسخهٔ 4.0 بهاندازهٔ محتوایش است و حداقل ارتفاع ندارد (تا 3٫x چهارصد پیکسل بود). داخل کارت، جدول یا فهرست همین درست است. برای وضعیت خالیِ یک صفحهٔ کامل، UtilityPage kind="empty" (پایین همین صفحه) جایش را تعیین میکند؛ بیرون از قالب به آن صحنه بدهید: <Empty minHeight="400px">.
انواع حالت خالی و پاسخ هر کدام
| نوع | کجا پیش میآید | پاسخ |
|---|---|---|
| صفر نتیجه | فهرستی که جستوجو یا فیلترش فعال است | filtered و onClearFilters قالب ListPage: «نتیجهای یافت نشد» با «پاک کردن فیلترها» |
| فهرست خالی | فهرستی که چیزی برنگرداند و فیلتری ندارد | emptyCopy: { title } در pageState — عنوانی که نام آنچه نیست را میبرد |
| صفحهٔ خالی (اولیه) | صفحهای از منو که هنوز چیزی ندارد | UtilityPage با kind="empty"، title و description |
| مسیر گمشده | نشانی یا موجودیتی که وجود ندارد | UtilityPage با kind="404" (در Next.js در app/not-found.tsx) |
صفر نتیجه و فهرست خالی: state قالب
فهرست یک صفحه ListPage است و حالتهایش state آن: pageState از فیلدهای useAsync یک مقدار میسازد و قالب،
با filtered خود صفحه، تصمیم میگیرد کدام حالت خالی را نشان دهد.
import { DataTable, useAsync } from '@partodata/ui'
import { ListPage, pageState } from '@partodata/ui/templates'
const { data, isLoading, error, run } = useAsync<Paged<Influencer>>()
;<ListPage
title="اینفلوئنسرها"
search={search}
filtered={query !== ''}
onClearFilters={clear}
state={pageState({
data: data?.items,
isLoading,
error,
onRetry: load,
emptyCopy: { title: 'هنوز اینفلوئنسری ثبت نشده است' },
})}
>
<DataTable columns={columns} data={data?.items ?? []} />
</ListPage>- صفر نتیجه: تا
filteredدرست است، فهرست خالی همیشه «نتیجهای یافت نشد» با «پاک کردن فیلترها» است (متن DS)، نه عنوانemptyCopy. دکمه همه را پاک میکند و به صفحهٔ 1 برمیگردد؛ اگر با صفحهکلید زده شود، فوکوس به جستوجو میرود. - فهرست خالی: عنوان
emptyCopyنام آنچه نیست را میبرد («هنوز اینفلوئنسری ثبت نشده است») و اقدامی ندارد: اقدام اصلی صفحه («افزودن اینفلوئنسر») همان بالا روی صفحه است. - بلوکی که جدا از صفحه بارگذاری میشود (نظرهای یک پست در صفحهٔ جزئیات):
stateهمانDetailSectionیا یکPageState؛ اگر فیلتر خودش را دارد،pageState({ …, filtered, onClearFilters }).
الگوهای رایج
صفحهٔ خالی: UtilityPage kind="empty"
صفحهای از منو که قابلیتش هنوز چیزی ندارد (هنوز گزارشی ساخته نشده) یک UtilityPage است، نه ListPage با فهرست خالی.
title وضعیت را میگوید، نه نام صفحه را:
import { } from '@partodata/ui/templates'
export default function () {
return (
<
="empty"
="هنوز گزارشی ساخته نشده است"
="گزارشها پس از راهاندازی این بخش، اینجا فهرست میشوند."
/>
)
}action فقط وقتی هست که چیزی در محصول اولین مورد را میسازد، و آنوقت کاری انجام میدهد — پیوندی به آن یا یک onClick؛
هرگز دکمهای بیعمل:
import Link from 'next/link'
import { Button } from '@partodata/ui'
import { UtilityPage } from '@partodata/ui/templates'
export default function SourcesPage() {
return (
<UtilityPage
kind="empty"
title="هنوز منبعی افزوده نشده است"
description="با افزودن اولین منبع، منشنهای آن اینجا جمع میشوند."
action={
<Button asChild>
<Link href="/sources/new">افزودن منبع</Link>
</Button>
}
/>
)
}مسیر گمشده: UtilityPage kind="404"
// app/not-found.tsx
import from 'next/link'
import { } from '@partodata/ui'
import { } from '@partodata/ui/templates'
export default function () {
return (
<
="404"
={
< >
< ="/">بازگشت به صفحهٔ اصلی</>
</>
}
/>
)
}موجودیتی که درخواستش تمام شد و چیزی برنگرداند (isSuccess && !data از useAsync) هم بهجای DetailPage یک
UtilityPage kind="404" با title، description و پیوند بازگشت به فهرست است.
بیرون از قالب صفحه
کامپوننت ترکیبی Empty را فقط جایی خودتان بنویسید که قالبی حالت را نمیکشد: پنل کناری،
Popover، Sheet یا محتوای یک CustomPage. اقدامش ثانوی (variant="default") است و کاری انجام میدهد:
;<>
<>هنوز منبعی به این پنل افزوده نشده است</>
<>منبعی را که میخواهید در این پنل ببینید از فهرست منبعها انتخاب کنید.</>
<>
< ="default" ={}>
انتخاب منبع
</>
</>
</>بهترین روشها + دامهای رایج
- عنوان حالت خالی نام آنچه نیست را میبرد و راهنماست: «هنوز اینفلوئنسری ثبت نشده است»، نه «هیچ اینفلوئنسری وجود ندارد».
- حالت خالی جای کل بلوک مینشیند و قالب ارتفاع کمینهاش را (
--layout-state-min-height) نگه میدارد تا جابهجایی صفحه کم باشد. - اسکلت پیش از حالت خالی میآید و ترتیب بارگذاری → خطا → خالی → آماده را
pageStateتعیین میکند؛ خودتان سهتایی شرطی ننویسید. - اقدام حالت خالی ثانوی است و فقط وقتی هست که کاری انجام میدهد.
دامهای رایج:
- ردیف «نتیجهای یافت نشد» داخل جدول (در
emptyStateجدول یا یکTableRowباcolSpan): حالت خالی جای جدول است. EmptyیاCalloutدستساز برای صفحهٔ 404:UtilityPage kind="404".- ساختن صفحهای که هنوز چیزی ندارد با
ListPageو فهرست خالی:UtilityPage kind="empty". - دکمهٔ «افزودن …» بدون
onClickیا پیوند. ErrorStateبهجای حالت خالی برای نتیجهٔ صفر: این خطا نیست.
صفحات مرتبط
- ListPage —
filtered،onClearFiltersوstateصفحهٔ فهرست - PageState —
pageStateو حالتهای یک بلوک - UtilityPage —
kind="empty"وkind="404" - الگوهای خطا — وقتی بارگذاری با خطا مواجه شد
- الگوهای بارگذاری — اسکلت پیش از حالت خالی
- Empty — کامپوننت حالت خالی، بیرون از قالب صفحه