Community画像github.com

RevanthThota55/FreeFrame-Studio

Sonner(React トーストライブラリ)の完全ガイド — Toaster のインストールと設定、適切な toast() 呼び出しの選択、プロミス/ローディングトースト、更新/破棄/永続化、スタイリング、テーマ設定、アイコン設定、配置、複数 Toaster の管理までをカバー。Sonner を使用する際や、トーストが表示されない、重複する、スタイルが消える、Tailwind クラスが効かない、モーダルの裏に隠れる、ダークモードに対応しないといったトラブルシューティングに最適。

FreeFrame-Studio とは?

このスキルは、React エコシステムにおけるトースト通知ライブラリ「Sonner」の包括的なガイドです。インストールから高度なカスタマイズ、トラブルシューティングまでを網羅しており、Next.js をはじめとするあらゆる React フレームワークで動作します。主な機能として、基本的なトースト表示、成功/エラー/情報などの種類別メソッド、ローディング状態の管理、Promise ベースのトースト(toast.promise)、トーストの更新・破棄・永続化、カスタムJSX による完全なスタイル制御(headless モード)、複数 Toaster の同時利用などが含まれます。スタイリングに関しては、デフォルト設定から richColors、インラインスタイル、クラスベース(!important 必須)、そして最も柔軟な headless カスタムトーストに至るまでの段階的なアプローチを提供。さらに、トーストが表示されない、重複する、Tailwind クラスが効かない、Shadow DOM 内でスタイルが適用されない、モーダルの裏に隠れる、ダークモードが効かないなど、よくある問題の原因と解決策を詳しく解説しています。API の詳細なプロップテーブルは別ファイル API.md に記載されています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/RevanthThota55/FreeFrame-Studio/tree/HEAD/.claude/skills/ask-sonner

Installed? Explore more 画像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Sonner の操作ガイド

初回応答

このスキルが特定の質問なしで最初に呼び出された場合、次のようにのみ応答します:

Sonner のセットアップ、スタイリング、トラブルシューティングのお手伝いをします。知識は作者の Emil Kowalski から得ています。

ユーザーが質問するまで、それ以上の情報は提供しないでください。

これは Sonner(トーストライブラリ)のガイドスキルです。Sonner に関連するタスク(配線、トーストのレンダリング、スタイリング、修正)が発生した場合は、最初にこのファイルから回答してください。<Toaster /> と toast() の完全なプロップテーブルは API.md にあります。正確なプロップ名、型、デフォルト値が必要な場合はそれを参照してください。

セットアップ

2つの要素だけです:

  1. 1つの <Toaster /> を1回だけマウントし、可能な限りルートに近い場所に配置します(Next.js では layout.tsx — サーバーコンポーネント内でも動作します)。ページごとや条件付きでレンダリングしないでください。2つ目の Toaster をマウントすると、すべてのトーストが重複します。
  2. クライアントコードから toast() を呼び出します — イベントハンドラ、エフェクト、コールバックなど。これは単なる関数であり、フックやプロバイダーは不要ですが、サーバー側では何も行いません。サーバーアクション内では、結果を返し、それを受け取るクライアントコードで toast() を呼び出してください。
import { Toaster } from 'sonner'; // 1回、レイアウトで
import { toast } from 'sonner';   // クライアント側のどこでも

適切な呼び出しの選択

やりたいこと呼び出し方法
プレーンメッセージtoast('Title') — 2行目には { description } を追加
成功/エラー/情報/警告アイコンtoast.success('…')、toast.error('…') など
自分で状態管理しながらスピナー表示toast.loading('…')、その後 ID で更新
Promise に連動したローディング→成功/エラーtoast.promise(promise, { loading, success, error }) — success/error は解決値/エラーを受け取る関数も可
アクション付きボタン{ action: { label, onClick } } — event.preventDefault() を呼ばない限り、クリックでトーストを閉じる。cancel はセカンダリーバリアント
カスタム JSX(デフォルトのトーストシェル付き)toast(<jsx />)
カスタム JSX(スタイルなし)toast.custom((t) => <jsx />) — ヘッドレス。t は破棄用の ID

レシピ集

トーストの更新 — 同じ id で toast() を再度呼び出します。渡したプロップだけが変更されます。toast.success(…, { id }) に切り替えるとタイプが変わります。これが toast.promise を使わずにローディング→成功のフローを実現する方法です:

const id = toast.loading('アップロード中…');
toast.success('アップロード完了', { id });

永続化 — { duration: Infinity }。破棄 — toast.dismiss(id)、またはすべてを破棄する場合は toast.dismiss()。アクティブなトーストの読み取り — React 内では useSonner()、それ以外では toast.getActiveToasts()。

テキスト内のリンクやコンポーネント — タイトルまたは説明に関数を渡します:toast(() => <a href="…">表示</a>)。

複数の Toaster — それぞれに id を付け、toast('…', { toasterId: 'canvas' }) でターゲット指定します。toasterId がない場合、すべての Toaster がトーストをレンダリングします。

クローズコールバック — onDismiss は閉じるボタンまたはスワイプで発火。onAutoClose はタイムアウトで発火。これらは別々であり、単一の「閉じた」コールバックはありません。

スタイリング — エスカレーションラダー

変更の必要に応じてのみ段階を上がってください。最上位に早期にジャンプしても問題ありません(推奨される最終状態です)、中間で留まるのは避けてください。

  1. デフォルト — さらに Toaster に richColors を追加してカラフルな成功/エラー表示、invert でテーマに合わせて反転。
  2. インライン調整 — Toaster の toastOptions={{ style: {…} }} ですべてのトーストに適用、または toast() 呼び出しごとに style を指定。
  3. パーツへのクラス適用 — toastOptions={{ classNames: { toast, title, description, actionButton, cancelButton, closeButton } }}。Sonner の注入スタイルがカスケードで優先されるため、すべてのクラスに !important が必要です(Tailwind: !text-red-900)。多くに important を付けているなら、やめてヘッドレスに移行しましょう。
  4. ヘッドレス — toast.custom() で独自の JSX を使用し、Sonner の配置、スタック、スワイプ機能は維持します。デザインシステムのトーストに推奨されるアプローチ:独自の toast() 抽象化でラップします。(unstyled: true は中間的な選択肢として存在しますが、同じ労力ならヘッドレスの方が制御性が高いです。)

アイコン — Toaster の icons プロップでタイプごとにデフォルトを交換、トーストごとに icon で交換、null で削除。

テーマ — theme はデフォルトで 'light' であり、OS の設定を追跡しません。theme="system" を渡すか、テーマプロバイダーと連携します:next-themes から <Toaster theme={resolvedTheme} />。

トラブルシューティング

症状原因 → 修正
トーストが表示されない<Toaster /> がマウントされていないか、アンマウントされた(条件付きレンダリング、ページごとの配置)。ルートに 1 つマウントしてください。サーバーアクションから呼び出す場合:toast() はクライアント専用です — アクションの結果をクライアントで受け取ったときに呼び出してください。
同じトーストが 2 つ表示される2 つの Toaster がマウントされている(レイアウト と ページ) — 1 つにしてください。または、React StrictMode の開発時ダブル呼び出しによりエフェクト内で toast() が 2 回発火している — イベントハンドラから呼び出すか、安定した id を渡して 2 回目の呼び出しが重複ではなく更新になるようにしてください。
Tailwind/CSS クラスが効かないデフォルトスタイルが上書きします。!important を付けるか、unstyled / ヘッドレスを使用してください(上のラダーを参照)。
トーストが完全にスタイルなしで表示される(Astro、ビュートランジションでよくある)Sonner の注入されたスタイルシートが失われた — レイアウトで明示的にインポート:import 'sonner/dist/styles.css'。
Shadow DOM 内でスタイルなしスタイルは document.head に配置され、シャドウルートには適用されません。テキストに [data-sonner-toaster] を含むスタイルタグをコピーしてシャバドウルートに配置してください。
トーストがモーダル/オーバーレイの背後に隠れる、またはクリップされる祖先要素が重ね合わせコンテキストを作成している(transform、filter、overflow)か、オーバーレイの z-index が Toaster より高い。<Toaster /> をドキュメントルートに移動し、ダイアログやポータルコンテナの外に配置してください。
ダークモードが無視されるtheme はデフォルトで 'light' — theme="system" を設定するか、解決されたテーマを渡してください(上記のテーマを参照)。
成功/エラーがグレーで表示され、緑/赤にならないそれがデフォルトです。Toaster に richColors を追加してください。
トーストが閉じないduration: Infinity、dismissible: false、または toast.promise の Promise が解決されない — ローディングトーストが永遠に待機します。
toast.promise がローディングのまま止まる第一引数に Promise(または Promise を返す関数)が必要であり、その Promise が実際に resolve/reject する必要があります。
スワイプで閉じる方向が間違っている/動作しない方向は position から派生します。Toaster の swipeDirections で上書きしてください。
すべての Toaster にトーストが表示される複数の Toaster にはターゲット指定が必要です:各 Toaster に id を付け、toast() 呼び出しで toasterId を渡してください。
モバイルでトーストが画面端に近すぎるoffset(デスクトップ、デフォルト 32px)と mobileOffset(<600px、デフォルト 16px)— 数値、CSS 文字列、または辺ごとのオブジェクト。

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

RevanthThota55/FreeFrame-Studio

Build an animation from scratch, making the decisions in the order that determines whether it feels right — should it animate at all, what purpose, which tool, which properties, which curve and duration, how it interrupts, how it exits. Writes the implementation. Use when asked to animate something, add motion, make a component feel alive, or build a transition. For critiquing existing motion use review-animations; for auditing a whole codebase use improve-animations.

RevanthThota55/FreeFrame-Studio

Keep web animations inside the frame budget — animate composite-only properties, keep motion off the main thread when the page is busy, and find the cause when an animation drops frames. Covers the layout/paint/composite pipeline, cheaper property swaps, CSS vs WAAPI vs requestAnimationFrame, Framer Motion's hardware-accelerated path, React re-rendering per frame, inherited CSS variable recalculation, blur cost, and when `will-change` actually helps. Use when an animation is janky, choppy, stutters, or drops frames; when choosing which property to animate; when deciding between CSS and JS animation on performance grounds; or when reaching for `will-change` or GPU layers. For choosing easing, duration, or whether to animate at all use animate; for reviewing motion as a whole use review-animations.

RevanthThota55/FreeFrame-Studio

Reverse-lookup glossary that turns a vague description of a web animation or motion effect into its exact term ("the bouncy thing when a popover opens" → Pop in; "the iOS rubber-band scroll" → Rubber-banding). Use when the user asks "what's it called when…", or describes a motion effect without knowing its name and wants the right word to prompt an AI or designer with. For naming an effect, not designing or building one.

RevanthThota55/FreeFrame-Studio

Apple's approach to interface design and fluid, physical motion, translated for the web. Use when building or reviewing gesture-driven UI, spring animations, drag/swipe/sheet interactions, momentum and interruptible transitions, translucent materials and depth, typography (optical sizing, tracking, leading), reduced-motion, or the design foundations (feedback, spatial consistency, restraint) behind Apple-style interfaces.

関連スキル