tui-design について
実際のタスク、端末機能、アクセシブルな操作を踏まえて TUI を設計するスキルです。レイアウト、入力とフォーカス、非同期状態、描画、ライフサイクル、検証を扱い、特定のフレームワークを指定しません。
主な機能
- 01タスクに基づく端末レイアウト
- 02キーボード、フォーカス、モーダルの挙動
- 03非同期状態とリクエスト処理
- 04端末機能とライフサイクルの指針
- 05アクセシビリティと検証の実践
活用シーン
- 01端末ピッカーやダッシュボードの設計
- 02遅延・古い非同期結果への対応
- 03さまざまな端末機能への対応
- 04リサイズ、入力、端末復元のテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hyperb1iss/ hyperskills --skill tui-designインストール後、Claude Code で/tui-designを入力して読み込まれたか確認します。
同梱ファイルreferences/app-patterns.mdreferences/visual-catalog.md
詳細
TUI デザインシステム
ユーザーが繰り返し行う操作、常に表示しておく必要があるデータ、実際に利用できるターミナル機能を中心に設計します。I/O が遅いときも入力への応答性を保ち、選択状態、フォーカス、操作状態を明示します。
主なドキュメントの確認日:2026-09-04。 フレームワークの API は変更されます。プロジェクトで使用しているバージョンを利用してください。サンプルの配色をあらゆる場面で使えるテーマとして扱うのではなく、プロジェクトのビジュアルアイデンティティ(Bliss の個人用ツールでは SilkCircuit Neon)に従ってください。
作業内容に合わせてレイアウトを選ぶ
| 作業 | レイアウト | 役立つ不変条件 |
|---|---|---|
| 関連するリストと詳細を閲覧する | 複数パネルを常時表示 | パネルの役割を固定し、フォーカスを見えるようにする |
| 階層を移動する | Miller カラムまたはドリルダウンスタック | 戻る操作で選択状態とスクロール位置を復元する |
| 変化する測定値を監視する | ウィジェットダッシュボード | ラベル、単位、更新状況、詳細への導線 |
| リクエスト、クエリ、設定を編集する | サイドバー、エディター、結果 | パネルを切り替えても編集状態を維持する |
| シェルコマンドの値を選択する | インラインピッカーまたはオーバーレイ | クリーンな値を返し、シェルのスクロールバックを保持する |
| ログまたはイベントを読む | 固定コントロールと仮想化リスト | 追従モードを明示し、上にスクロールすると自動追従を停止する |
例とトレードオフについてはapp-patterns.mdをお読みください。グリフ、境界線、チャート、インジケーターを選ぶ場合に限り、visual-catalog.mdをお読みください。
レスポンシブ動作
制約とコンテンツの優先度を活用します。セカンダリパネルを折りたたむ際も、選択中の項目が見える状態を保ちます。パネルを再表示したときに状態を復元します。サイズ変更時にレイアウトを再計算し、一時的に領域がゼロになってもエラーとして扱わないでください。フィルタリング、削除、またはビューポートの縮小後は、スクロール範囲を調整します。
狭い幅、通常の幅、広い幅のレイアウトをテストし、急なサイズ変更も確認します。使用可能な最小サイズはタスクによって異なります。80x24 は有用なテストケースですが、40 列でも動作するピッカーを無効にしてよいという意味ではありません。サイズに関するメッセージが表示されても、終了と復旧のための入力は受け付けられるようにします。
入力、フォーカス、編集
| 懸念事項 | 方針 |
|---|---|
| 基本操作 | 矢印キー、Enter、Escape、および分かりやすいフォーカス移動をサポートします |
| 熟練者向けショートカット | 繰り返し行う作業の効率が上がる場合は、vim モーションやコマンドパレットを追加します |
| テキストフィールド | 印字可能なキーでテキストを編集できるようにします。q、j、/、ニーモニックアクションはグローバルに実行されないようにします |
| 複数キーのショートカット | 保留中のコンテキストを表示し、入力ライブラリを通じてEscapeとプレフィックスの曖昧さを解決します |
| モーダルダイアログ | 入力をモーダルのみに振り分け、閉じるときに以前の有効なフォーカスターゲットに戻します |
| 破壊的な操作 | 対象と結果を正確に示し、取り消し可能性に応じた確認を求めます |
| マウス操作 | キーボード操作と同等の機能を用意し、端末でテキストを選択する際に入力の捕捉を無効にできるようにします |
入力解析を担当する箇所は一つにします。Crossterm を使う場合は、EventStream と read/poll を混在させたり、複数のリーダーを同時に動かしたりしないでください。キーの押下、リピート、解放を意図的に処理し、物理的な1回の押下で二重に送信されないようにします。
拡張キーボードプロトコルを使うと、従来の端末では同一にエンコードされるキーを区別できます。対応状況をネゴシエートし、実用的な代替バインディングも用意してください。どの環境でもCtrl+IとTab、またはCtrl+MとEnterが異なるとは限りません。ブラケット付きペーストはテキストイベントとして扱い、貼り付けた改行によって破壊的なコマンドが誤って送信されないようにします。
Rawモードでは端末の通常のシグナル処理が無効になることがあります。Ctrl+Cやサスペンド/再開はフレームワークを通じて意図的に実装し、OSが通常どおり処理してくれると想定しないでください。エディター、ページャー、シェル、またはサスペンドされたプロセスに制御を渡す前に端末の状態を復元し、戻ってきたら状態を再取得して画面を再描画します。
現在利用できる操作を示す短いフッターと、状況に応じたヘルプ画面を表示します。タスクの実行中も、重要な手順が見えるようにします。後から確認できる場所にエラーを保存します。消えてしまうトーストだけを唯一の記録にしてはいけません。
状態と非同期処理
入力イベント、状態遷移、副作用、描画を分離します。状態のスナップショットを描画し、描画関数からネットワーク呼び出しを開始したり、ドメインモデルを変更したりしないようにします。
digraph tui_state {
rankdir=LR;
event -> update;
update -> state;
update -> effect;
effect -> event [label="result + request identity"];
state -> render;
}
| 障害モード | 設計上の対応 |
|---|---|
| 検索Aが検索Bより後に完了する | リクエストにタグを付け、アクティブなクエリと一致しない結果は破棄します |
| 更新後に行の位置が変わる | 行インデックスだけでなく、安定した識別子で選択状態を管理します |
| 処理中にビューが閉じる | 所有する処理をキャンセルするか、意図的に切り離します。遅れて届いた結果でビューを復元しないようにします |
| キャンセルした書き込みがすでにサーバーに届いている可能性がある | キャンセルされた待機と、確認済みのロールバックを区別し、リモート状態を調整します |
| 画面更新より速くログが届く | 必要なイベントはデータレイヤーに保持し、仮想化されたビューポートに描画します |
async 構文でも処理がUIをブロックする | ブロッキング呼び出しやCPU負荷の高い処理を特定し、入力/描画経路から移します |
| 繰り返し操作で重複した書き込みが始まる | 保留中の操作の識別情報を追跡し、競合する操作を受け付ける前に結果を表示します |
状態の更新をまとめ、変更されたフレームを描画します。置き換え可能な表示スナップショットはまとめてもかまいませんが、監査イベントや変更処理はまとめないでください。データを破棄したり同時実行数を制限したりする前に、キューの増大、インデックス作成、アロケーションのコストを調査します。
ターミナル機能ポリシー
明示的に設定されたアプリケーションの設定を優先します。自動モードでは、色を検出する前に、空でない NO_COLOR を尊重します。色の上書き設定によって、意図的に色を再度有効にできます。色を無効にしても、太字、下線、レイアウト、その他すべてのターミナル機能を無効にする必要はありません。
| 機能 | 根拠とフォールバック |
|---|---|
| インタラクティブなターミナル | 実際の入出力 TTY を確認します。プレーン出力に対応するか、TTY が必要な理由を説明します |
| トゥルーカラー | ライブラリの検出機能、terminfo、またはネゴシエーション済みのサポートを使用します。COLORTERM はヒントであり、必須条件ではありません |
| 256 色/16 色 | 意味的なスロットをサポート対象の色に割り当て、色相がなくてもラベルとフォーカスを維持します |
| 画像、ハイパーリンク、クリップボード | マルチプレクサーを介してプロトコルをネゴシエーションします。テキストまたはファイルによる代替手段を提供します |
| Nerd Font アイコン | 明示的に指定するか、ユーザーが設定できるようにします。移植性があり、信頼できるフォント検出 API はありません |
| Unicode レイアウト | 書記素クラスタを区切り、ターミナルセル幅を測定します。バイト数やコードポイント数を長さとして使用しないでください |
切り詰めは書記素クラスタの境界でのみ行い、全角セル、結合文字、異体字セレクタ、絵文字シーケンスを考慮してください。幅を扱うライブラリとターミナルエミュレーターの判定は一致しない場合があります。代表的なユーザーテキストでテストし、表示が不確かな場合は ASCII のインジケーターを提供してください。
ファイル名、ログ、リモートの文字列は、信頼できない表示データとして扱います。制御シーケンスを、未加工の出力 API を通じて書き込む前にエスケープしてください。そうしないと、表示値によってカーソルを移動したり、タイトルを変更したり、OSC 操作を実行したりする可能性があります。フレームワークがサポートするテキスト処理/サニタイズ経路を使用してください。
ターミナルへのクエリは、キー入力と同じ入力ストリームを共有します。1 つのパーサーで応答を対応付け、未対応のクエリに対する待機時間を制限し、ユーザー入力を読み飛ばさないフォールバックを選択してください。
視覚的な階層とアクセシビリティ
前景色、控えめなテキスト、フォーカス、選択、警告、エラーなどの意味的なスロットを定義します。テーマ値をウィジェットのコードに含めないでください。枠線を増やす前に、一貫した余白とラベルを使用します。アプリケーションが独自の背景色を設定する場合は、ダークテーマとライトテーマのバリエーションを用意します。透明またはデフォルトの背景は、ユーザーのテーマに対してテストする必要があります。
ステータスの色には、テキストまたは形状も併用してください。モノクロモードでも判別できるフォーカスインジケーターを使用し、重要な値が読めなくなるほど暗くしないでください。WCAG の通常テキストに対する 4.5:1 のコントラスト比は、有用な設計目標です。ただし、ターミナルのフォントサイズと ANSI カラーはユーザーが制御するため、ターミナルの見出しを太字にしても、自動的に大きなテキストの例外に該当するわけではありません。配色だけを根拠に、正式なアクセシビリティ基準への適合を主張しないでください。
全画面インターフェースによってスクリーンリーダーでのナビゲーションが妨げられる場合は、プレーンな表示または直線的な表示を提供してください。意味のあるラベル、キーボード操作への対応、アニメーションを使わないモードも、対象とするターミナルおよび支援技術を使ってテストする必要があります。点滅する警告や、急速に点滅するステータス表示は避けてください。ユーザーが動きを抑えられるようにしてください。アニメーションによって入力を遅らせたり、最終状態を隠したりしてはなりません。
描画とターミナルのライフサイクル
フレームワークのバッファリング描画とセル差分処理を使用します。書き込みはまとめ、同期出力は対応している場合にのみ使用し、エラー時も必ず開始と終了を対にします。単一の書き込みだけでは描画の原子性は保証されません。また、同期出力は使いやすい TUI の必須条件ではなく、機能を強化するものです。
状態が変化したとき、またはアクティブなアニメーションの期限に達したときに描画します。想定するデータレートで、SSH やマルチプレクサーも含めて入力遅延、出力帯域幅、再描画コストを測定します。実際のワークロードに合わせて更新頻度を選び、一律の FPS 上限を設けたり、ストリーミングされたテキストを人為的に遅延させたりしないでください。
スコープを持つ所有者を通じてターミナルモードを取得し、アプリが有効にしたすべての設定を復元します。対象は、raw モード、代替画面、カーソルの表示状態、マウスキャプチャ、ブラケット付きペースト、キーボードプロトコルの状態です。通常終了、初期化の失敗、例外やパニック、処理対象のシグナルを網羅します。フレームワークの復元ヘルパーが対象とするのは一部の設定だけの場合があります。仕様を確認してください。SIGKILL ではクリーンアップを実行できません。
信頼度を高める検証
削除後の選択状態、古くなった非同期結果、モーダルからのフォーカス復元、キャンセルされた操作について、決定論的な状態遷移テストを行います。レイアウトの境界値にはフレームワークのテストバックエンドを使用し、スナップショットではターミナルモードや入力プロトコルを検証できないため、少なくとも 1 回は実際の PTY セッションを確認します。
起動、文字入力、貼り付け、サイズ変更、モーダルの開閉、低速または失敗する I/O、終了をテストします。ライトテーマとダークテーマ、色無効、幅広文字や結合文字、実際にサポートするターミナル/マルチプレクサーの経路も含めます。終了後、シェルのカーソルとエコー動作が復元されていることを確認します。移植性の要件や障害によって必要性が生じた場合は、テストマトリクスを拡張します。
アンチパターン
| アンチパターン | より適切な対応 |
|---|---|
true-color の検出後に NO_COLOR を確認する | 機能選択の前にユーザーの設定を解決する |
| グローバルなニーモニックショートカットがテキスト入力を消費する | フォーカスとアクティブなモードに基づいてイベントを振り分ける |
| Unicode のリリース時期を互換性の目安として示す | 書記素クラスタとセルを測定し、サポート対象のエミュレーターでテストする |
| 非同期リクエストの完了によって新しい状態が上書きされる | 結果の識別情報を現在のビュー/クエリと照合する |
| バックグラウンドログが画面を消去したりエスケープコードを出力したりする | ログを状態経由または別の出力先に送る |
| FPS や同時実行数を下げて過負荷のキューを隠す | プロデューサー、状態処理、レンダラーを個別にプロファイリングする |
| 通常終了時にしかターミナルを復元しない | ライフサイクルガードとフレームワークのパニック/シグナル処理を使う |
主な情報源
確認日 2026-09-04:Ratatui のアプリケーションパターン、Ratatui の復元仕様、Crossterm の入力所有権、kitty キーボードプロトコル、NO_COLOR、Unicode 書記素クラスタの分割、コントラストに関するガイダンス。
状態の所有権と検証に関するガイダンスは、これらの仕様を踏まえたエンジニアリング上の統合知見であり、プロトコルがアプリケーションの正しさを保証するという主張ではありません。
このスキルの対象外
- フレームワークの API マニュアルでも、新しいツールキットの採用を義務付けるものでもありません。
- シンプルなピッカーにアニメーション、アイコン、モードを追加する理由にはなりません。
- 実際のターミナルとアクセシビリティの経路をテストする代わりにはなりません。