メインコンテンツへスキップ
サイドバータブ API を使用すると、拡張機能は ComfyUI インターフェースのサイドバーにカスタムタブを追加できます。これは、継続的な表示とクイックアクセスを必要とする機能を追加する際に役立ちます。

基本的な使い方

app.extensionManager.registerSidebarTab({
  id: "customSidebar",
  icon: "pi pi-compass",
  title: "カスタムタブ",
  tooltip: "マイカスタムサイドバータブ",
  type: "custom",
  render: (el) => {
    el.innerHTML = '<div>これはカスタムサイドバーのコンテンツです</div>';
  }
});

タブ設定

各タブにはいくつかのプロパティが必要です:
{
  id: string,              // タブの一意の識別子
  icon: string,            // タブボタンのアイコンクラス
  title: string,           // タブのタイトルテキスト
  tooltip?: string,        // ホバー時のツールチップテキスト(オプション)
  type: string,            // タブタイプ(通常は "custom")
  render: (element) => void // タブコンテンツを構築する関数
}
render 関数は DOM 要素を受け取り、そこにタブのコンテンツを挿入する必要があります。

アイコンオプション

サイドバータブのアイコンには、さまざまなアイコンセットを使用できます:
  • PrimeVue アイコン:pi pi-[icon-name](例:pi pi-home
  • Material Design アイコン:mdi mdi-[icon-name](例:mdi mdi-robot
  • Font Awesome アイコン:fa-[style] fa-[icon-name](例:fa-solid fa-star
これらのアイコンを使用する前に、対応するアイコンライブラリが読み込まれていることを確認してください。

状態を持つタブの例

状態を維持するタブを作成できます:
app.extensionManager.registerSidebarTab({
  id: "statefulTab",
  icon: "pi pi-list",
  title: "メモ",
  type: "custom",
  render: (el) => {
    // 要素の作成
    const container = document.createElement('div');
    container.style.padding = '10px';
    
    const notepad = document.createElement('textarea');
    notepad.style.width = '100%';
    notepad.style.height = '200px';
    notepad.style.marginBottom = '10px';
    
    // 保存されたコンテンツがあれば読み込む
    const savedContent = localStorage.getItem('comfyui-notes');
    if (savedContent) {
      notepad.value = savedContent;
    }
    
    // コンテンツの自動保存
    notepad.addEventListener('input', () => {
      localStorage.setItem('comfyui-notes', notepad.value);
    });
    
    // UI の組み立て
    container.appendChild(notepad);
    el.appendChild(container);
  }
});

React コンポーネントの使用

サイドバータブに React コンポーネントをマウントできます:
// 拡張機能で React 依存関係をインポート
import React from "react";
import ReactDOM from "react-dom/client";

// React コンテンツを持つサイドバータブを登録
app.extensionManager.registerSidebarTab({
  id: "reactSidebar",
  icon: "mdi mdi-react",
  title: "React タブ",
  type: "custom",
  render: (el) => {
    const container = document.createElement("div");
    container.id = "react-sidebar-container";
    el.appendChild(container);
    
    // 簡単な React コンポーネントを定義
    function SidebarContent() {
      const [count, setCount] = React.useState(0);
      
      return (
        <div style={{ padding: "10px" }}>
          <h3>React サイドバー</h3>
          <p>カウント:{count}</p>
          <button onClick={() => setCount(count + 1)}>
            増加
          </button>
        </div>
      );
    }
    
    // React コンポーネントをマウント
    ReactDOM.createRoot(container).render(
      <React.StrictMode>
        <SidebarContent />
      </React.StrictMode>
    );
  }
});
サイドバータブとして統合された React アプリケーションの実際の例については、GitHub の ComfyUI-Copilot プロジェクト をご覧ください。

動的コンテンツの更新

グラフの変更に応じてサイドバーのコンテンツを更新できます:
app.extensionManager.registerSidebarTab({
  id: "dynamicSidebar",
  icon: "pi pi-chart-line",
  title: "統計",
  type: "custom",
  render: (el) => {
    const container = document.createElement('div');
    container.style.padding = '10px';
    el.appendChild(container);
    
    // 統計情報を更新する関数
    function updateStats() {
      const stats = {
        nodes: app.graph._nodes.length,
        connections: Object.keys(app.graph.links).length
      };
      
      container.innerHTML = `
        <h3>ワークフロー統計</h3>
        <ul>
          <li>ノード数:${stats.nodes}</li>
          <li>接続数:${stats.connections}</li>
        </ul>
      `;
    }
    
    // 初期更新
    updateStats();
    
    // グラフの変更をリッスン
    const api = app.api;
    api.addEventListener("graphChanged", updateStats);
    
    // タブが破棄されたときにリスナーをクリーンアップ
    return () => {
      api.removeEventListener("graphChanged", updateStats);
    };
  }
});