フィードバック

フィードバックの概要

処理結果、進行状況、注意、完了をユーザーへ返すためのコンポーネント群です。通知の強さ、表示時間、操作を求めるかどうかで使い分けます。

カテゴリ概要

コンポーネント一覧

各コンポーネントの詳細ページへ移動して、プレビュー、コード、プロパティを確認できます。

短い処理の表示

ActionProgress

保存や送信のような短い処理のあいだ、画面を塞いで「処理中」を伝える小さなダイアログです。中身は、上端の流れるバー、回る印(Spinner)、題と説明です。既定では 350ms 待ってから出すので、すぐ終わる処理では何も出ません。

詳細を見る

アラート

Alert

注意を促すためのコールアウトを表示します。

詳細を見る

バナー

Banner

ページ全体に関係するお知らせや状態を横長のバーで表示します。

詳細を見る

通知センター

NotificationCenter

通知の一覧と管理用の UI です。

詳細を見る

進捗バー

Progress

タスクの進捗を示すインジケーターです。

詳細を見る

進捗ウィジェット

ProgressWidget

進捗値、補足文、進捗バーをカードとしてまとめて表示します。

詳細を見る

ページ遷移の表示

RouteProgress

ページの移動中に画面の上端へ出す細いバーです。進み具合(%)を持たず、描画しているあいだだけ流れます。

詳細を見る

安全バナー

SafetyBanner

重要な警告や安全確認を強調し、必要に応じて明示的な確認状態を管理します。

詳細を見る

スピナー

Spinner

処理中であることを示すインジケーターです。

詳細を見る

ステータスバー

StatusBar

ステータスや情報を表示するバーです。

詳細を見る

ステータス画面

StatusScreen

404、エラー、オフライン、権限なし、メンテナンス、公開前など、全画面の状態フィードバックを表示します。

詳細を見る

ステッパー

Stepper

複数ステップの進行状況を、完了・現在地・未完了の状態で示すコンポーネントです。

詳細を見る

追従告知バー

StickyNoticeBar

アクションにつなげたいサイト告知を、明示的に選んだ上端または下端の一方へ追従表示します。

詳細を見る

トースト

Toast

一時的に表示する短いメッセージです。

詳細を見る

トーストプロバイダ

ToastProvider

トーストの表示と管理を行います。

詳細を見る

補足情報

一覧でコンポーネントを選んだあとに確認する、カテゴリ全体の責務、共通ルール、使い分けです。

このカテゴリの責務

ページや操作の結果を、ユーザーが次に判断できる粒度で返します。永続表示、短時間表示、進行中表示を混ぜずに選びます。

このページの使い方

まずカテゴリの責務を確認し、迷いやすい使い分けから該当コンポーネントへ移動します。

パターンで確認する場面

フォーム送信、メディア操作、チャット、管理画面など、複数コンポーネントを組み合わせた場面で通知の強さと位置を確認します。

フィードバック系の共通ルール

カテゴリ内で共通して守るべき判断基準です。

状態色だけで意味を伝えず、タイトルや説明で何が起きたかを明示します。

操作できない状態や失敗時は、理由と次の行動を近くに置きます。

迷いやすい使い分け

似ているコンポーネントを選ぶ時の入口です。

ページ内に残す注意は Alert、画面上部の横長通知は Banner、短時間の完了通知は Toast を使います。

単純な進捗は Progress、進捗に状態や操作が伴う場合は ProgressWidget を使います。

避ける使い方

フィードバックは目立たせるだけでなく、次に何をすべきかを伝える必要があります。

色だけで成功、警告、失敗を伝える。

破壊的な操作や復旧不能な操作を Toast だけで済ませる。

処理中の残り作業や失敗理由を、進捗バーから切り離して遠くに置く。

まとめて使う見本

この分類のコンポーネントをまとめて、取り込みの進み具合と結果を伝える1画面を組んだ例です。そのまま貼り付けて動きます。

"use client";

import { useState } from "react";
import {
    Alert,
    Banner,
    Button,
    Card,
    CardContent,
    CardHeader,
    CardTitle,
    Progress,
    Spinner,
    Stepper,
} from "@gunjo/ui";

const STEP_LABELS = ["読み込み", "検証", "取り込み"];

const STEP_MESSAGE = [
    "ファイルを読んでいます。このタブは閉じないでください。",
    "1行ずつ、決めた形式に合っているか確かめています。",
    "通った行をワークスペースに書き込んでいます。",
];

export function ImportJobStatus() {
    const [step, setStep] = useState(1);
    const [dismissed, setDismissed] = useState(false);

    const running = step < STEP_LABELS.length;
    const percent = Math.round(((step + 1) / (STEP_LABELS.length + 1)) * 100);

    return (
        <Card className="max-w-2xl">
            {dismissed ? null : (
                <Banner
                    variant="info"
                    onDismiss={() => setDismissed(true)}
                    dismissLabel="閉じる"
                >
                    取り込みは裏で進みます。このページを離れても大丈夫です。
                </Banner>
            )}
            <CardHeader>
                <CardTitle>顧客データの取り込み</CardTitle>
            </CardHeader>
            <CardContent className="space-y-6">
                <Stepper
                    steps={STEP_LABELS.map((label, index) => ({
                        label,
                        state:
                            index < step ? "completed" : index === step ? "current" : "upcoming",
                    }))}
                />

                <div className="space-y-2">
                    <div className="flex items-center gap-2 text-sm text-muted-foreground">
                        {running ? <Spinner size="sm" /> : null}
                        <span>{running ? STEP_MESSAGE[step] : "取り込みが終わりました。"}</span>
                    </div>
                    <Progress
                        value={percent}
                        label="取り込みの進み具合"
                        valueText={percent + "% 完了"}
                        tone={running ? "primary" : "success"}
                    />
                </div>

                {step === 1 ? (
                    <Alert
                        variant="warning"
                        title="12行に確認が必要です"
                        description="メールアドレスが無い行は取り込みません。"
                    />
                ) : null}

                {running ? null : (
                    <Alert
                        variant="success"
                        title="1,204件を取り込みました"
                        description="残る12行は取り込まず、一覧として書き出せます。"
                    />
                )}

                <div className="flex gap-3">
                    <Button
                        onClick={() => setStep(Math.min(step + 1, STEP_LABELS.length))}
                        disabled={!running}
                    >
                        次へ進む
                    </Button>
                    <Button variant="outline" onClick={() => setStep(0)}>
                        最初からやり直す
                    </Button>
                </div>
            </CardContent>
        </Card>
    );
}

設計の判断

通知や状態表示のコンポーネントをいつ使い、いつ使わないかは、UIXHERO の「UIコンポーネント完全ガイド」にある「カテゴリ 07|フィードバック・状態」の節にまとめています。画面に残して読ませるのか、短い時間だけ出して消すのかで、選ぶコンポーネントが変わります。

UIXHERO: UIコンポーネント完全ガイド(カテゴリ 07|フィードバック・状態)(新しいタブで開きます)