この記事の対象読者
- 一覧画面や検索画面を作る人
- 空状態の文言をなんとなく書いている人
- ユーザーに次の行動を案内できる画面にしたい人
本題に入る前に
一覧画面で0件だったとき、「データがありません」とだけ出していませんか。
もちろん間違いではありません。でも、使っている人からすると「で、次に何をすればいいの?」となることがあります。
0件にもいろいろあります。
- まだ何も作っていない
- 検索条件が厳しすぎる
- 権限がなくて見えていない
- 読み込みに失敗している
この記事では、業務画面の空状態を少し親切にする考え方を整理します。
空状態の理由を分ける
まず、0件の理由を分けます。
type EmptyReason = "initial" | "filtered" | "forbidden" | "error";
理由ごとに文言を変えます。
const emptyMessages: Record<EmptyReason, { title: string; body: string }> = {
initial: {
title: "まだ予約がありません",
body: "最初の予約を作成すると、ここに一覧表示されます。",
},
filtered: {
title: "条件に一致する予約がありません",
body: "検索条件を変更するか、期間を広げてもう一度お試しください。",
},
forbidden: {
title: "表示できる予約がありません",
body: "閲覧権限が必要な可能性があります。管理者に確認してください。",
},
error: {
title: "予約を読み込めませんでした",
body: "時間をおいて再度お試しください。",
},
};
コンポーネントにする
Reactで小さく作るならこうです。
type EmptyReason = "initial" | "filtered" | "forbidden" | "error";
function EmptyState({ reason }: { reason: EmptyReason }) {
const message = emptyMessages[reason];
return (
<section>
<h2>{message.title}</h2>
<p>{message.body}</p>
</section>
);
}
一覧画面では、状態に応じて出し分けます。
function ReservationList({
reservations,
hasFilter,
canRead,
hasError,
}: {
reservations: unknown[];
hasFilter: boolean;
canRead: boolean;
hasError: boolean;
}) {
if (hasError) return <EmptyState reason="error" />;
if (!canRead) return <EmptyState reason="forbidden" />;
if (reservations.length === 0 && hasFilter) {
return <EmptyState reason="filtered" />;
}
if (reservations.length === 0) {
return <EmptyState reason="initial" />;
}
return <div>予約一覧</div>;
}
次の行動を入れる
空状態には、次の行動を入れると親切です。
| 状態 | 次の行動 |
|---|---|
| 初回0件 | 新規作成ボタンを出す |
| 検索結果0件 | 検索条件をリセットする |
| 権限なし | 管理者への確認を案内する |
| エラー | 再読み込みを案内する |
ただ「ありません」と言うより、「次にどうすればよいか」まで出すと、迷いにくくなります。
まとめ
0件画面は、ただの余白ではありません。
初回0件、検索結果0件、権限なし、読み込み失敗を分ける。理由に合わせて文言と次の行動を変える。
これだけでも、業務画面はかなり親切になります。