0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Copilot内にReactのカードを出す前に、表示モードの主導権を確かめる

0
Posted at

Copilot UX componentのサンプルで気になったのは、Reactでカードを描く部分より、カードを広げたり戻したりする操作の持ち主だった。普通のWebページなら自分のstateで表示を切り替えられる。Copilot内ではレイアウトを決めるのはホストだ。

たとえば作業項目カードをチャットに出すなら、inlineでは件名と状態だけ、fullscreenでは詳細も見せたい。ここで拡大ボタンを押した直後にReactのstateをfullscreenへ変えると、ホストが拡大要求を受けなかった場合に表示がずれる。最初に確かめるべきなのは、カードの見た目より表示モードの往復だと思う。

以下はMicrosoftの公開資料を基にしたプレビュー検証手順。Microsoft 365テナントでWorkbenchを実行した結果ではない。2026年10月8日時点でCopilot UX componentsはプレビューで、本番環境への投入は案内されていない。10月のGAは予定であり、完了済みという意味ではない。

まずカードの入力を固定する

実データや承認APIをつなぐ前に、架空の作業項目を1件だけ用意する。

const workItem = {
  id: 'TASK-142',
  title: '請求画面の空状態を直す',
  status: 'レビュー待ち',
  detail: 'データが0件のとき、次の操作が分かる文言と導線を追加する',
};

inlineではid、title、statusを表示し、fullscreenではdetailを足す。このfixtureなら、モード切り替えの問題とデータ取得の問題を混ぜずに済む。生成されたテンプレートのmessageプロパティを件名として使えば、Workbenchから長い文字列も渡せる。空のdetailはfixtureを変えて確かめる。

SPFxのプレビュー雛形を作る

SPFxの開発環境とYeomanを用意した上で、公式ロードマップにあるプレビュー用generatorを入れる。

npm install @microsoft/generator-sharepoint@next --global
mkdir copilot-work-item
cd copilot-work-item
yo @microsoft/sharepoint

生成時はコンポーネント種別にCopilot Component、テンプレートにReactを選ぶ。まずは生成された雛形でWorkbenchまで到達できるかを見る。SharePointのテナントが必要で、App Catalogへの配布まで進める場合はアップロード権限も必要になる。プレビュー版のバージョンと対応Node.jsは作業時点の公式要件に合わせる。

生成されたCopilot componentのmanifestで、表示可能なモードを確認する。

{
  "capabilities": {
    "availableDisplayModes": ["inline", "fullscreen"]
  }
}

これはmanifest全体ではなくcapabilitiesの抜粋。宣言があっても、描画コードが現在のモードを読んでいなければ、広げた先で同じ小さなカードを出すだけになる。

displayModeを描画のたびに読む

生成されたクラスでは、現在のモードをthis.hostContext.displayModeから読む。React側にはその値をpropsとして渡し、inline用とfullscreen用の情報量を切り替える。次はSPFx側に置く処理の要点だけを抜き出したもの。

protected render(): void {
  const mode = this.hostContext.displayMode;
  const canExpand = this.hostContext.availableDisplayModes.includes('fullscreen');
  const title = this.properties.message?.trim() || workItem.title;

  // Reactのカードにmode、canExpand、titleを渡して描画する。
  // mode === 'fullscreen'のときだけdetailを表示する。
}

private requestExpansion = async (): Promise<void> => {
  try {
    await this.requestDisplayModeAsync('fullscreen');
  } catch (error) {
    console.error('fullscreenへの切り替え要求に失敗しました', error);
  }
};

拡大ボタンはcomponent側で描き、ホストがfullscreenを利用可能としているときだけ出す。requestDisplayModeAsyncの後にローカルstateを先回りして切り替えない。ホストがモードを更新するとSPFx側が再描画するので、その時点のdisplayModeを読み直す。inlineへ戻すAPIはなく、ユーザーがホストの縮小操作を行う。

Workbenchで確認する順番

ローカル開発サーバーを起動し、テナント内のSharePointサイトからCopilot Workbenchを開く。

heft start --nobrowser
https://<your-tenant>.sharepoint.com/_layouts/15/copilotworkbench.aspx

Workbenchではデバッグ用manifestの読み込みを許可し、componentを選んでプロパティJSONを渡す。まず{"message":"請求画面の空状態を直す"}で起動し、次を記録する。表の「結果」は実行時に埋める欄だ。

操作・入力 確認すること 結果
初期表示 inlineで件名と状態が読める
拡大ボタン fullscreenになり、詳細が増える
ホスト側の縮小 inlineに戻り、カードも縮む
detailが空 空欄でレイアウトが崩れない
長いmessage inlineで切れ方や折り返しが破綻しない
message欠落 スキーマが拒否するか、代替件名を表示するか
再表示 前回のローカル表示状態を引きずらない

messageが必須なら、欠落した入力はUIに届く前にスキーマで拒否される可能性がある。その場合は拒否されたことを記録する。拡大後の縮小も、component内に「閉じる」ボタンを足して済ませたくなるところだが、操作はホストが持つ。この非対称さを確かめてからカードの細部を作り込む。

配布経路も区別しておく

この手順はSPFx製Copilot UX component向け。最終的には.sppkgをSharePoint App Catalogに配布し、宣言型エージェントをテナントのagent catalogへ同期する。外部MCPサーバーがwidgetを返すMCP Apps経路とは実装と配布の入口が違う。MCP Apps向けのwindow.openai.*対応表を、このSPFx componentのAPI表として使わないようにしたい。

隣接する方式のSDKや実装例を探すなら、MCP Apps UIの実装リソースを比較の入口にできる。ただし、今回のmanifestとホストAPIの確認先はSPFxの公式資料だ。

AIに実装を頼むなら、検収条件まで渡す

コード生成エージェントへの依頼も、この検証範囲に絞る。

生成済みのSPFx Copilot Component(React)に、架空の作業項目カードを実装してください。
inlineではid・件名・状態、fullscreenでは詳細も表示してください。
manifestのavailableDisplayModesを確認し、拡大要求はhostContextの対応モードを確認してから行ってください。
返答には変更ファイル、Workbenchで確認する操作、未確認の点を列挙してください。
実データ接続、承認送信、テナントへの配布は今回の作業に含めません。

コードが生成できても、ホストが拡大要求を受けたか、縮小後に表示が戻るかは分からない。上の表をWorkbenchで埋めてから、データ接続へ進む。GA状況、ライセンス、対応する描画先は公開前にもう一度確認する。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?