mcpField
T
thinking-orbs

thinking-orbs

github.com/mengtoデザイン・UI7.1k1.4k 回インストール3 日前に更新
リポジトリ

thinking-orbs について

thinking-orbsは、アニメーションするモノクロのドットで不確定なAIの活動状況を示すReactコンポーネントパッケージです。6種類の状態と2つの固定サイズを備え、テーマや表示状態、視差効果の低減にも対応します。

主な機能

  1. 01AIの作業に対応する6種類の状態
  2. 022種類の固定キャンバスサイズ
  3. 03テーマと表示状態の自動処理
  4. 04視差効果の低減時に静止画を表示
  5. 05キャンバス描画用の低レベルAPI

活用シーン

  1. 01React画面で検索や推論の状態を表示
  2. 02AI生成の応答にステータスを添える
  3. 03視差効果を抑えた活動フィードバックの提供

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mengto/skills --skill thinking-orbs

インストール後、Claude Code で/thinking-orbsを入力して読み込まれたか確認します。

同梱ファイルagents/openai.yamlREFERENCES.md

詳細

Thinking Orbs

基本契約

  1. 不定の AI アクティビティを示すフィードバックが必要な React 18 以降のインターフェースでは、thinking-orbs を使用してください。
  2. 実際のプロダクトのライフサイクルを、用意されている 6 つの状態のいずれかに対応付けてください。
  3. 調整済みの 20 ピクセルまたは 64 ピクセルのサイズのみを使用してください。一方のプリセットを引き伸ばして、もう一方のサイズにしないでください。
  4. 周囲の表示領域に既知の固定テーマがない限り、theme="auto" を使用してください。
  5. アクティビティがユーザーにとって重要な場合は、オーブに簡潔な表示ステータステキストを添えてください。
  6. タスク固有のラベルで aria-label を上書きするか、隣接するライブテキストが同じ状態をすでに通知している場合は、支援技術からオーブを隠してください。
  7. 現在のフレームを固定するには paused を使用してください。speed={0} で一時停止を再現しないでください。
  8. オーブは不定のフィードバックとして扱い、進捗率や完了通知として使用しないでください。

パッケージは、透明な 2D キャンバスに単色のドットを描画します。カスタムカラー、任意のサイズ、確定的な進捗には対応していません。

インストール

プロジェクトのパッケージマネージャーを確認してから、インストールします。

npm install thinking-orbs

このパッケージでは、ピア依存関係としてバージョン 18 以降の react と react-dom を宣言しています。コンポーネントとエクスポートされた型は、パッケージのルートからインポートしてください。

import {
  ThinkingOrb,
  type OrbSize,
  type OrbState,
  type OrbTheme,
  type ThinkingOrbProps,
} from "thinking-orbs";

状態を選ぶ

  • working — 一般的なツールの実行、複数ステップの作業、またはより適切な状態がないアクティビティ。
  • searching — 情報の取得、ウェブ検索、ファイル検索、またはナレッジの検索。
  • solving — 推論、分析、計算、または計画。
  • listening — マイク入力、音声の取り込み、または発話ターンの待機。
  • composing — テキストの回答の執筆、要約、下書き作成、または生成。
  • shaping — 画像、レイアウト、構造化された成果物、またはその他の形式のある出力の作成や改良。

見た目の面白さを優先した不正確な状態ではなく、実態に即した一般的な working 状態を選んでください。基盤となるアクティビティが変化したときのみ、状態を変更してください。

サイズを選ぶ

  • テキスト内、ボタン内、またはコンパクトなステータス行では、size={20} を使用してください。
  • チャットのアバター程度の大きさ、空の状態、またはメインの視覚的ステータスには、size={64} を使用してください。

プリセットごとにドットの数、サイズ、速度の調整が異なります。これらは単なる拡大縮小ではなく、別々のデザインです。周囲により広いスペースが必要な場合は、キャンバスに CSS 変換を適用するのではなく、ラッパーのサイズを調整してください。

基本的な使い方

import { ThinkingOrb } from "thinking-orbs";

export function AgentStatus() {
  return (
    <ThinkingOrb
      state="searching"
      size={20}
      theme="auto"
      aria-label="Searching project files…"
    />
  );
}

className、style、data-*、イベントハンドラー、ARIA 属性など、その他すべてのキャンバスプロパティはそのまま渡されます。

プロダクトのライフサイクルをモデル化する

対応付けを明示できるよう、プロダクトのフェーズと視覚的な状態は分けてください。

import { ThinkingOrb, type OrbState } from "thinking-orbs";

type AgentPhase =
  | "idle"
  | "retrieving"
  | "reasoning"
  | "writing"
  | "creating"
  | "done"
  | "error";

const ORB_BY_PHASE: Partial<Record<AgentPhase, OrbState>> = {
  retrieving: "searching",
  reasoning: "solving",
  writing: "composing",
  creating: "shaping",
};

export function AgentActivity({ phase }: { phase: AgentPhase }) {
  const state = ORB_BY_PHASE[phase];
  if (!state) return null;

  return <ThinkingOrb state={state} size={20} />;
}

done、error、キャンセル、またはアイドル状態ではオーブを取り除いてください。最後のアクティビティのアニメーションを動かしたままにせず、適切な結果、再試行、またはエラーの UI を表示してください。

ステータスの通知は一度だけにする

コンポーネントのデフォルトは role="img" で、状態ごとの「Searching…」のようなラベルが設定されています。表示されるテキストが同じ状態を説明している場合は、そのテキストを唯一の通知元にしてください。

export function LiveAgentStatus() {
  return (
    <div role="status" aria-live="polite" className="agent-status">
      <ThinkingOrb state="solving" size={20} aria-hidden="true" />
      <span>Reviewing the repository…</span>
    </div>
  );
}

通常のフェーズ変更には aria-live="polite" を使用してください。ラベルが頻繁に変わらないようにしてください。role="status" がすでに通知を担っている場合は、別の非表示ライブリージョンを追加しないでください。

テーマ

次のいずれかを使用してください。

<ThinkingOrb theme="auto" />
<ThinkingOrb theme="dark" />
<ThinkingOrb theme="light" />
  • auto は、まず祖先要素の data-theme="dark|light" 属性、または dark/light クラスを確認します。
  • 祖先要素にテーマがない場合、auto は prefers-color-scheme に従います。
  • テーマの変更は即座に反映されます。
  • dark は、暗い背景向けの明るいドットを意味します。
  • light は、明るい背景向けの暗いドットを意味します。

キャンバスは透明です。ページのルート要素だけでなく、実際の表示領域でコントラストを確認してください。

速度と一時停止

<ThinkingOrb state="working" speed={0.85} />
<ThinkingOrb state="composing" paused={isWaitingForApproval} />

speed は、選択した状態とサイズに設定済みの速度に乗算します。まずは 1 から始め、プロダクトに合わせた微調整にはおおむね 0.75–1.25 を使用してください。極端な値にすると、細かく調整された動きが慌ただしくなったり、停止したように感じられたりすることがあります。

paused は、視覚的なステータスを維持しながら現在のフレームを固定します。アクティビティが実際に終了したら、コンポーネントを取り除いてください。

Next.js とクライアントレンダリング

このコンポーネントは、React エフェクト、canvas、requestAnimationFrame、メディアクエリ、オブザーバーを使用します。Next.js App Router では、インポートをクライアント境界の内側に配置してください。

"use client";

import { ThinkingOrb } from "thinking-orbs";

export function ThinkingStatus() {
  return <ThinkingOrb state="working" size={20} />;
}

このライブラリは、テーマの解決後にクライアント側でのみ描画するため、SSR に安全です。ただし、フレームワークがサーバーコンポーネントとクライアントコンポーネントの分離を強制する箇所では、クライアント境界が引き続き必要です。

組み込みのランタイム動作

  • WebGL や SVG フィルターを使わず、標準の Canvas 2D の弧を使って描画します。
  • デバイスのピクセル比を 2 に制限します。
  • 表示中の各インスタンスにつき、requestAnimationFrame ループを 1 つ使用します。
  • 複数のオーブの動きを同期させるため、共有の performance.now() クロックを使用します。
  • canvas が画面外にスクロールすると、IntersectionObserver によって一時停止します。
  • ブラウザーのタブが非表示になると、一時停止します。
  • prefers-reduced-motion: reduce の設定時には、決定的な静止フレームを 1 つ描画します。
  • 動きを抑える設定時も、テーマの変更をリアルタイムで反映し続けます。

ラッパーでこれらの動作を再実装しないでください。コンポーネントの周囲にはプロダクトの状態管理とレイアウトを追加し、別のアニメーションループは追加しないでください。

パワーユーザー向け Canvas API

プロダクト UI では <ThinkingOrb> を使用してください。このパッケージは、React の外でカスタム canvas を使うために、解決済みのプリセットと生のフレーム描画関数もエクスポートしています。

import { MODE_DRAWS, resolvePreset } from "thinking-orbs";

const { mode, speed, opts } = resolvePreset("searching", 64);
const drawFrame = MODE_DRAWS[mode];

drawFrame(
  context,
  64,
  (performance.now() / 1000) * speed,
  true, // true draws light ink for a dark surface
  opts,
);

STATE_TO_MODE は内部マッピングを公開します。

  • working → orbits
  • searching → globe
  • solving → rubik
  • listening → wave
  • composing → ribbon
  • shaping → morph

生の API は、別のレンダラーが canvas のライフサイクルを管理する場合にのみ使用してください。提供するのはフレーム描画関数であり、コンポーネントの動作ではありません。<ThinkingOrb> を使用しない場合は、DPR のサイズ設定、クリア、アニメーションのスケジューリング、一時停止、テーマの解決、動きを抑える設定、可視性の処理、クリーンアップ、アクセシビリティを再実装してください。

検証

プロジェクトの型チェック、テスト、本番ビルド、git diff --check を実行してください。その後、実際のブラウザーで次の項目を検証してください。

  1. プロダクトの各フェーズを発生させ、マッピングされたオーブの状態が正確であることを確認します。
  2. 20 ピクセルと 64 ピクセルのインスタンスが、CSS による拡大縮小なしで鮮明に表示されることを確認します。
  3. ダーク、ライト、テーマのリアルタイム切り替えをテストします。
  4. 動きを抑える設定をテストし、オーブが代表的な静止フレームになることを確認します。
  5. オーブを画面外にスクロールしてから戻し、表示に目立った乱れなく再開することを確認します。
  6. タブを非表示にしてから再表示し、アニメーションが再開することを確認します。
  7. アクセシビリティを確認します。ステータスが正確に 1 回だけ通知され、タスク固有のラベルが使用されていることを確認します。
  8. 成功、エラー、キャンセル、アイドルの各状態で、オーブが消えることを確認します。
  9. コンソールエラー、ハイドレーション警告、レイアウトシフトが発生しないことを確認します。

よくある落とし穴

  • サイズの型エラー: 20 または 64 のみを使用してください。任意の寸法は渡さないでください。
  • コントラストの誤り: dark は暗い背景を対象とするため、明るいインクで描画することを覚えておいてください。
  • スクリーンリーダーでの読み上げ重複: 隣接する role="status" のテキストがタスクをすでに通知している場合は、canvas を非表示にしてください。
  • 誤解を招く状態: 生成中に searching を、マイクでの音声キャプチャ中に composing を表示しないでください。
  • 読み込み UI の常時表示: 作業が終了したらオーブを削除し、実際の終了状態を表示してください。
  • ハイドレーションまたはサーバーコンポーネントのエラー: インポートをクライアントコンポーネントに移動してください。
  • ブランドカラーの指定: 公開 API はモノクロです。サポートされていないスタイル設定に頼らず、別のローダーを選ぶか、意図的にライブラリをフォークしてください。

引き継ぎ

マッピングしたプロダクトのフェーズ、選択したサイズ、テーマモード、アクセシブルなラベルの方針、動きを抑える設定時の動作、ビルドとブラウザーでの検証について報告してください。ローカルでの実装とデプロイ済みリリースを区別してください。

コメント