sileo-react-toasts について
Sileoは、短い状態メッセージと任意の展開可能な説明を表示するReact用トースト通知コンポーネントです。SVGの形状変化とスプリングアニメーションを使い、状態別およびPromise対応のAPIを備えています。
主な機能
- 01成功・エラー・警告・情報の通知
- 02Promiseの読み込みから結果への通知
- 03アクションボタンと展開可能な説明
- 046種類の表示位置
- 05テーマとスタイルのカスタマイズ
- 06スワイプで閉じる操作と動きを抑える設定
活用シーン
- 01変更の保存を通知
- 02APIリクエストの結果を報告
- 03更新後の操作を提示
- 04アップロード中の状態を表示
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ xoverlap/ sileo-skill --skill sileo-react-toastsインストール後、Claude Code で/sileo-react-toastsを入力して読み込まれたか確認します。
詳細
スキル:Sileo(React トースト通知)
公式ドキュメント: https://sileo.aaryan.design/docs API リファレンス: https://sileo.aaryan.design/docs/api Toaster API: https://sileo.aaryan.design/docs/api/toaster スタイリングガイド: https://sileo.aaryan.design/docs/styling プレイグラウンド: https://sileo.aaryan.design/play GitHub: https://github.com/hiaaryan/sileo
Sileo とは?
Sileo は、React 用の小型で独自の設計方針を持つ、物理演算ベースのトーストコンポーネントです。feGaussianBlur と feColorMatrix のフィルターチェーンを使った グー状の SVG モーフィングと、motion/react(以前の Framer Motion)によるスプリングアニメーションを使用し、設定不要でそのまま美しく、非常になめらかな通知を実現します。
Sileo は汎用の通知センターではありません。1 行のフィードバックメッセージに、必要に応じて展開可能な説明を添えるために設計された、洗練された独特の見た目のトーストシステムです。
主な特徴:
- フレームワーク:React のみ(Next.js App Router との互換性のため、
"use client"ディレクティブを同梱) - ピア依存関係:
motion(スプリング物理演算エンジン、motion/react) - アーキテクチャ:ピル型(折りたたみ時)とカード型(展開時)の状態間をグー状のブロブがモーフィングする、SVG ベースのレンダリング
- TypeScript ファースト:すべての型をエクスポート(
SileoOptions、SileoPosition、SileoState、SileoStyles、SileoButton) - アクセシビリティ:ビューポートセクションで
aria-live="polite"を使用し、prefers-reduced-motionに対応 - スワイプで閉じる:ポインターイベントに基づく、上下方向のスワイプジェスチャーを標準搭載(しきい値 30px)
インストール
npm install sileo
Sileo のピア依存関係として、react と motion が必要です。
クイックセットアップ
- アプリのルートレイアウトに
<Toaster />を一度だけマウントします。 sileoをインポートすれば、どこからでもトーストを表示できます。
import { sileo, Toaster } from "sileo";
export default function App() {
return (
<>
<Toaster position="top-right" />
<YourApp />
</>
);
}
sileoには"use client"が含まれているため、追加のラッパーなしで Next.js App Router でシームレスに動作します。
基本的な使い方
Sileo は、状態ごとのショートカットを備えたグローバルコントローラー sileo を公開します。
import { sileo } from "sileo";
// State shortcuts (each returns the toast `id` as a string)
sileo.success({ title: "Saved", description: "Your changes were stored." });
sileo.error({ title: "Failed", description: "Could not save." });
sileo.warning({ title: "Warning", description: "Disk space low." });
sileo.info({ title: "Tip", description: "Try the new feature." });
// Generic toast (defaults to success, but accepts `type` for dynamic state)
sileo.show({ title: "Done", type: "success" });
// Dynamic state selection
sileo.show({
type: response.ok ? "success" : "error",
title: "Upload complete",
});
sileo の全メソッド
| メソッド | 戻り値 | 説明 |
|---|---|---|
sileo.success(options) | string(id) | 緑色の成功トースト |
sileo.error(options) | string(id) | 赤色のエラートースト |
sileo.warning(options) | string(id) | 琥珀色の警告トースト |
sileo.info(options) | string(id) | 青色の情報トースト |
sileo.action(options) | string(id) | アクションボタン付きのトースト |
sileo.show(options) | string(id) | 汎用トースト。状態には options.type を使用し、デフォルトは "success" です |
sileo.promise(promise, opts) | Promise<T> | ローディングから成功/エラーへ移行するフロー。元の promise を返します |
sileo.dismiss(id) | void | id を指定して特定のトーストを閉じます |
sileo.clear(position?) | void | すべてのトースト、または指定した位置のトーストのみを消去します |
SileoOptions
すべての sileo.*() 呼び出しに渡します。
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | -- | トーストの見出し(ピル内に表示) |
description | ReactNode | string | -- | 本文(展開時に表示)。リッチコンテンツには JSX を使用できます |
type | SileoState | -- | sileo.show() の動的な状態。"success" | "loading" | "error" | "warning" | "info" | "action" のいずれかです |
position | SileoPosition | Toaster のデフォルト | このトーストの位置を個別に上書きします |
duration | number | null | 6000 | 自動で閉じるまでの時間(ミリ秒)。null = 固定(自動では閉じません) |
icon | ReactNode | null | 状態アイコン | バッジの円内にあるデフォルトアイコンを置き換えるカスタムアイコン |
fill | string | "#FFFFFF" | トーストの背景シェイプに使用する SVG の塗りつぶし色 |
styles | SileoStyles | -- | サブ要素の CSS クラスを上書きします |
roundness | number | 16 | SVG シェイプの角丸半径(ピクセル) |
autopilot | boolean | { expand?: number; collapse?: number } | true | 自動で展開・折りたたみするタイミング。false = ホバー時のみ |
button | SileoButton | -- | アクションボタンの設定 |
アクショントースト
アクショントーストには、展開領域内にクリック可能なボタンが含まれます。
sileo.action({
title: "New version available",
description: "Reload to update",
button: {
title: "Reload",
onClick: () => window.location.reload(),
},
});
SileoButton
interface SileoButton {
title: string;
onClick: () => void;
}
Promise トースト
sileo.promise は、1 つの Promise からローディング状態から成功/エラー状態への遷移を連鎖させます。元の Promise を返すため、さらにチェーンをつなげられます。
- 最初の引数には、
Promise<T>または関数() => Promise<T>を指定できます(遅延実行に便利です)。 successとerrorには、静的なオプション、または解決/拒否された値を受け取るコールバックを指定できます。- オプションの
actionフィールドを指定すると、成功トーストがアクション状態のトーストに置き換わります。
type User = { name: string };
const result = await sileo.promise<User>(createUser(data), {
loading: { title: "Creating account..." },
success: (user) => ({
title: `Welcome, ${user.name}!`,
}),
error: (err: any) => ({
title: "Signup failed",
description: err?.message ?? "Unknown error",
}),
});
// `result` is the resolved User object
遅延 Promise(関数)を使用する場合:
sileo.promise(() => fetch("/api/data").then((r) => r.json()), {
loading: { title: "Fetching data..." },
success: { title: "Data loaded" },
error: { title: "Failed to load" },
});
成功状態をアクションに置き換える場合:
sileo.promise<{ url: string }>(uploadFile(file), {
loading: { title: "Uploading..." },
success: { title: "Uploaded" }, // Ignored when `action` is present
error: { title: "Upload failed" },
action: (data) => ({
title: "File ready",
description: "Click to open",
button: {
title: "Open",
onClick: () => window.open(data.url),
},
}),
});
SileoPromiseOptions<T>
interface SileoPromiseOptions<T = unknown> {
loading: SileoOptions;
success: SileoOptions | ((data: T) => SileoOptions);
error: SileoOptions | ((err: unknown) => SileoOptions);
action?: SileoOptions | ((data: T) => SileoOptions);
position?: SileoPosition;
}
位置
6 つの位置を使用できます。<Toaster /> にデフォルトを設定するか、トーストごとに上書きします。
type SileoPosition =
| "top-left"
| "top-center"
| "top-right" // default
| "bottom-left"
| "bottom-center"
| "bottom-right";
<Toaster position="bottom-center" />
// Override for a specific toast
sileo.success({ title: "Saved", position: "top-left" });
SILEO_POSITIONS 定数配列も、反復処理用にエクスポートされています。
import { SILEO_POSITIONS } from "sileo"; // Not exported from index (internal)
Toaster(ビューポートコンポーネント)
<Toaster /> はトーストをレンダリングするビューポートコンポーネントです。ルートレイアウトに 1 回だけ追加します。
import { Toaster } from "sileo";
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | -- | トーストと一緒にレンダリングするアプリのコンテンツ |
position | SileoPosition | "top-right" | すべてのトーストのデフォルト位置 |
offset | number | string | { top?, right?, bottom?, left? } | -- | ビューポートの端からの距離 |
options | Partial<SileoOptions> | -- | すべてのトーストにマージされるデフォルトオプション |
theme | "light" | "dark" | "system" | -- | カラースキームに基づいて塗りつぶし色を自動設定します。"system" は OS の設定に従います |
テーマ
theme prop は、選択したスキームに基づいてトーストの fill 色を自動設定するため、ダーク/ライト用の塗りつぶし色を手動で設定する必要はありません。
"light"-> 塗りつぶし色は#1a1a1a(明るい背景に暗いトースト)+明るい説明テキスト"dark"-> 塗りつぶし色は#f2f2f2(暗い背景に明るいトースト)+暗い説明テキスト"system"->prefers-color-schemeメディアクエリに従い、OS の設定変更に応じて更新されます
<Toaster position="top-right" theme="system" />
theme を設定すると、ビューポートは data-theme="light" または data-theme="dark" をレンダリングします。CSS はこれを使って説明テキストの不透明度を自動調整します。
themeと個々のトーストのfillの両方を設定した場合は、トーストごとのfillが優先されます。
オフセット
数値(px)、CSS 文字列、または辺ごとのオブジェクトを指定できます。
<Toaster offset={20} />
<Toaster offset="1.5rem" />
<Toaster offset={{ top: 20, right: 16 }} />
デフォルトオプション(グローバル)
<Toaster
options={{
fill: "#171717",
styles: { description: "text-white/75!" },
}}
/>
すべてのトーストがこれらのデフォルトを継承します。トーストごとのオプションは、これらを上書きします。styles オブジェクトは浅くマージされます(トーストごとのスタイルがグローバルスタイルを上書きします)。
スタイリング
Sileo は初期状態のままでも見栄えよく使えます。カスタマイズが必要な場合に備えて、いくつかの調整方法が用意されています。
塗りつぶし色
fill は、トーストの形状の SVG 背景色を設定します。デフォルトは "#FFFFFF" です。
暗いトーストには、暗い fill を使用し、styles で明るいテキストを組み合わせます。
sileo.success({
title: "Dark toast",
fill: "#171717",
styles: {
title: "text-white!",
description: "text-white/75!",
},
});
スタイルの上書き(styles)
個々のサブ要素の CSS クラスを上書きします。Tailwind を使用する場合は、詳細度を高めるために ! を追加してください。
SileoStyles
interface SileoStyles {
title?: string; // The heading text
description?: string; // The body/description area
badge?: string; // The icon badge circle
button?: string; // The action button
}
使用可能なデータ属性セレクター
| キー | 要素 | CSS セレクター |
|---|---|---|
title | 見出しテキスト | [data-sileo-title] |
description | 本文/説明エリア | [data-sileo-description] |
badge | アイコンのバッジ円 | [data-sileo-badge] |
button | アクションボタン | [data-sileo-button] |
CSS のターゲット指定に使用できるその他のデータ属性:
| セレクター | 説明 |
|---|---|
[data-sileo-toast] | 最も外側のトースト要素(<button>) |
[data-sileo-toast][data-state="success"] | 状態で絞り込んだトースト |
[data-sileo-toast][data-expanded="true"] | 展開されたトースト |
[data-sileo-toast][data-exiting="true"] | 終了アニメーション中のトースト |
[data-sileo-viewport] | 固定されたビューポート <section> |
[data-sileo-viewport][data-position="top-right"] | 位置で絞り込んだビューポート |
[data-sileo-viewport][data-theme="dark"] | テーマが適用されたビューポート |
[data-sileo-canvas] | SVG キャンバスのラッパー |
[data-sileo-svg] | 内側の SVG 要素 |
[data-sileo-pill] | アニメーションする折りたたみ時のピル型矩形 |
[data-sileo-body] | アニメーションする展開時のボディ矩形 |
[data-sileo-header] | ヘッダー行のコンテナー |
[data-sileo-content] | 展開可能なコンテンツ領域 |
例:Tailwind によるダークテーマの完全な設定
sileo.success({
title: "Custom styled",
fill: "black",
styles: {
title: "text-white!",
description: "text-white/75!",
badge: "bg-white/20!",
button: "bg-white/10!",
},
});
カスタムアイコン
icon に任意の React ノードを渡すと、デフォルトの状態アイコンを置き換えられます。
sileo.info({
title: "Custom icon",
icon: <MyIcon />,
});
アイコンを表示しない場合は、icon: null を渡します。
状態ごとのデフォルトアイコン(インライン SVG の Lucide スタイル):
success-> チェックマークerror-> Xwarning-> 感嘆符付きの円info-> 救命浮輪loading-> 回転する円(CSS アニメーション)action-> 右矢印
カスタム説明(JSX)
description は JSX を受け付けるため、展開領域内にリッチなコンテンツを表示できます。
sileo.info({
title: "Rich content",
description: (
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<span>Multiple elements supported</span>
<img src="/preview.png" alt="Preview" width={120} />
</div>
),
});
角の丸み
roundness で境界線の角丸を調整できます(デフォルトは 16)。
sileo.success({ title: "Sharp", roundness: 8 }); // Sharper corners
sileo.success({ title: "Pill", roundness: 24 }); // More pill-like
パフォーマンス:
roundnessを大きくすると、グーイーな変形エフェクトの SVG ぼかし半径(blur = roundness * 0.5)が大きくなり、描画コストが増加します。推奨値は16です。
自動制御
デフォルトでは、トーストは約 150ms 後に自動で展開され、閉じる約 4 秒前に折りたたまれます。この動作を制御します。
// Disable entirely (hover to expand, click away to collapse)
sileo.info({ title: "Manual", autopilot: false });
// Custom timing (milliseconds)
sileo.info({
title: "Custom timing",
autopilot: { expand: 250, collapse: 300 },
});
内部のデフォルト値(6000ms の DEFAULT_TOAST_DURATION から算出):
AUTO_EXPAND_DELAY= 150ms(6000 * 0.025)AUTO_COLLAPSE_DELAY= 4000ms(6000 - 2000)
autopilot が false の場合、または duration が null/0 の場合、自動展開/折りたたみは無効になります。
閉じる/クリア
// Dismiss a specific toast
const id = sileo.success({ title: "Will dismiss" });
sileo.dismiss(id);
// Clear all toasts
sileo.clear();
// Clear only toasts at a specific position
sileo.clear("bottom-center");
トーストは垂直方向にスワイプ(しきい値 30px)して閉じることもできます。これはポインターイベントによるスワイプジェスチャーの組み込み動作です。
固定トースト
自動で閉じないようにするには、duration: null を設定します。プログラムから閉じるか、スワイプするまでトーストが表示されます。
sileo.warning({
title: "Requires attention",
description: "This won't go away on its own.",
duration: null,
});
グローバルデフォルト(統一されたダークテーマ)
<Toaster
position="top-right"
options={{
fill: "#171717",
roundness: 16,
styles: {
title: "text-white!",
description: "text-white/75!",
badge: "bg-white/10!",
button: "bg-white/10! hover:bg-white/15!",
},
}}
/>
CSS 変数
Sileo はグローバルな上書き用に CSS カスタムプロパティを公開しています。:root または任意の親要素で上書きします。
:root {
/* State colors (oklch format) */
--sileo-state-success: oklch(0.723 0.219 142.136);
--sileo-state-loading: oklch(0.556 0 0);
--sileo-state-error: oklch(0.637 0.237 25.331);
--sileo-state-warning: oklch(0.795 0.184 86.047);
--sileo-state-info: oklch(0.685 0.169 237.323);
--sileo-state-action: oklch(0.623 0.214 259.815);
/* Dimensions */
--sileo-width: 350px;
--sileo-height: 40px;
/* Animation */
--sileo-duration: 600ms;
}
例:ブランド用のカスタム成功色:
:root {
--sileo-state-success: oklch(0.7 0.2 200);
}
内部 CSS 変数(トーストごと、インラインスタイルで設定)
これらはトーストごとに計算され、[data-sileo-toast] の CSS カスタムプロパティとして設定されます。
| 変数 | 説明 |
|---|---|
--_h | 現在のトーストの高さ(折りたたみ時または展開時) |
--_pw | ピルの幅 |
--_px | ピルの X オフセット |
--_ht | ヘッダーの変形(移動+拡大縮小) |
--_co | コンテンツの不透明度(0 または 1) |
内部カラー変数(状態ごとにCSSで設定)
| 変数 | 説明 |
|---|---|
--sileo-tone | バッジ/タイトルに使用する、解決済みの状態色 |
--sileo-tone-bg | バッジの背景に使用する、状態色の不透明度20%の色 |
--sileo-btn-color | ボタンのテキスト色(状態色と同じ) |
--sileo-btn-bg | ボタンの背景色(状態色の15%) |
--sileo-btn-bg-hover | ボタンのホバー時の背景色(状態色の25%) |
TypeScript エクスポート
すべての型は "sileo" からエクスポートされています。
import type {
SileoButton,
SileoOptions,
SileoPosition,
SileoState,
SileoStyles,
} from "sileo";
// SileoState = "success" | "loading" | "error" | "warning" | "info" | "action"
SileoPromiseOptions<T> 型もtoastモジュールからエクスポートされています。
アクセシビリティ
- ビューポートでは
<section>とaria-live="polite"を使用しているため、スクリーンリーダーはユーザーを中断せずに新しいトーストを読み上げます。 - トーストのルート要素には、キーボードでフォーカスできる
<button>を使用しています。 - 各SVGアイコンには、スクリーンリーダー用のラベルとなる
<title>要素があります。 - Sileoは、OSで設定されている場合、
prefers-reduced-motion: reduceに従ってすべてのアニメーションとトランジションを無効にします。
アーキテクチャ(内部の詳細)
Sileoの内部の仕組みを理解しておくと、デバッグや詳細なカスタマイズに役立ちます。
-
グローバルストア: モジュールレベルのシングルトン(
store)がすべてのアクティブなトーストを保持し、リスナーのSetを介してReactに通知します。Toasterコンポーネントはこのストアを購読し、トーストが変更されると再レンダリングします。 -
トーストID: ユーザーが
idを指定しない場合、トーストのIDには"sileo-default"が使用されます。そのため、idを指定せずにsileo.success(...)を繰り返し呼び出すと、前のトーストが置き換えられます(同じIDの更新動作)。同じ状態のトーストを複数同時に表示するには、一意のidを指定してください。 -
SVGのグーイー効果: 各トーストは次の要素を含む
<svg>をレンダリングします。feGaussianBlur(stdDeviation =roundness * 0.5)+feColorMatrix+feCompositeを含む<filter>motion/reactのスプリングトランジションでアニメーションする2つの<motion.rect>要素(ピル+本体)- グーイーフィルターにより、ピルと展開後のカードの間に有機的な融合効果が生まれます
-
スプリング物理: アニメーションには、
bounce: 0.25と算出されたduration(デフォルトは0.6s)を指定したmotion/reactのスプリングトランジションを使用します。CSSトランジションでは、同じスプリングカーブを近似するlinear()イージングを使用します。 -
展開方向:
top-*の位置にあるトーストは下方向に展開し、bottom-*の位置にあるトーストは上方向に展開します(キャンバスにCSSのscaleY(-1)トランスフォームを適用)。 -
タイマー管理: 各Toasterインスタンスは、トーストごとの自動非表示タイマーを管理します。いずれかのトーストにホバーするとすべてのタイマーが一時停止し、ホバーを解除すると再開します。このホバー時の一時停止は、トースト単位ではなくToaster単位の動作です。
-
ヘッダーのモーフィング: トーストの状態が変わると(例:プロミス経由で loading から success に変化)、2つのレイヤー(
current+prev)を使い、ぼかしを利用したクロスフェードアニメーションでヘッダーが切り替わります。
統合チェックリスト
-
sileoをインストールする(また、ピア依存関係のmotionが利用可能であることを確認する) - ルートレイアウトに
<Toaster />を1つだけマウントする - 状況に応じて
sileo.success/error/warning/info/show/actionを使用する - 非同期処理では、
sileo.promise(...)を優先して使用する - テーマ設定には、
themeプロパティを使用するか、fill+styles+ CSS変数を手動で設定する - プログラムから非表示にするには、
dismiss(id)またはclear(...)を使用する - トーストを複数同時に表示する場合は、一意の
id値を指定する
よくあるパターン
フォーム送信のフィードバック
const handleSubmit = async (data: FormData) => {
await sileo.promise(saveForm(data), {
loading: { title: "Saving..." },
success: { title: "Form saved" },
error: (err: any) => ({
title: "Save failed",
description: err?.message,
}),
});
};
操作を取り消すトースト
const id = sileo.action({
title: "Item deleted",
description: "This action can be undone",
duration: 8000,
button: {
title: "Undo",
onClick: () => {
restoreItem(itemId);
sileo.dismiss(id);
},
},
});
複数のトーストを同時に表示
// Use unique ids to prevent replacement
sileo.info({ title: "Downloading file 1...", id: "download-1", duration: null });
sileo.info({ title: "Downloading file 2...", id: "download-2", duration: null });
// Dismiss individually
sileo.dismiss("download-1");
sileo.dismiss("download-2");