ドキュメント
目標と設計原則
Native Shell は、iOS、Android、macOS、Windows、Linux、Web にまたがってネイティブのビューとインタラクションを提供します。ビジュアルデザインはアプリが所有します。1 つのコンポーネントモデルで、アプリ全体、埋め込み機能、動的に配信される UI をまかなえます。
#ネイティブな基盤とアプリが所有するデザイン
NSH は各プラットフォームのビュー、テキスト、入力のインフラストラクチャを土台とし、キーボードナビゲーション、ポインターとタッチ入力、テキスト編集、スクロール、アクセシビリティといったインタラクションをデバイスに合わせて適応させます (はじめに)。
色、タイポグラフィ、余白、形状、状態のフィードバック、アニメーションはアプリが定義します。設定画面は iOS と Android でアプリのブランドに従いつつ、入力とナビゲーションは各デバイスの慣習に従えます。デザイナーは、スタイルとコンポーネントのパーツを通じてそのビジュアル言語を磨き上げます。
ネイティブビューは描画の基盤です。システムスタイルのコントロールは、特定の見た目と振る舞いを選択したものにすぎません。NSH の共通コントロールは、共有される振る舞いとカスタマイズ可能なパーツを公開しており、アプリケーションは独自のデザインシステムを構築できます。
#ネイティブ統合の実際
ネイティブ基盤には、描画、フレーム駆動のアニメーション、入力、アクセシビリティのセマンティクスが含まれます。iOS と Android では、Input はプラットフォームのテキストフィールドを使用します。編集、選択メニュー、入力メソッド、対応する自動入力サービスはプラットフォームが処理します。アプリは autoComplete (たとえば current-password や postal-code) を通じてフィールドを記述し、システムは設定とサービスに応じて利用可能な候補を提供します (フォームとキーボード)。フィールドにスタイルを適用しても、このシステム統合は維持されます。
これは、カスタムレンダラー内でテキストフィールドをすべて描画する方式とのアーキテクチャ上の違いです。カスタムレンダラーはシステムの編集サービスやアクセシビリティサービスとの統合を独自に用意する必要がありますが、NSH はバックエンドが提供している場合にプラットフォームのテキストコントロールを使用します。Windows 上の NSH 独自エディターや GPUI 埋め込みバックエンドを含め、各バックエンドの統合方法はそれぞれのドキュメントで定義されています (プラットフォーム)。
GPUI Kit におけるコンポーネントの振る舞いとビジュアルデザインの分離は、NSH のレイヤー構成の着想元です。NSH はこの原則を、プラットフォームのビューと入力のインフラストラクチャの上に発展させています。このモデルでは、ネイティブ統合とアプリが所有するデザインが一貫して両立します。
#プラットフォームをまたぐ 1 つのコンポーネントモデル
スイッチは、スマートフォンでもデスクトップでも Web でも同じ意味を持ちます。nsh/base は状態、入力処理、フォーカス、アクセシビリティを提供し、アプリは Switch のトラック、サム、状態にスタイルを適用します。ボタン、チェックボックス、ラジオも同じ原則に従います。
| 責務 | 配置先 | 例 |
|---|---|---|
| 描画、レイアウト、リアクティビティ、環境 | nsh-core、nsh、およびランタイムモジュール | ビュー、テキスト、シグナル、スタイル |
| 共有される振る舞いとアクセシブルな構造 | nsh-base (TSX では nsh/base としてインポート) | Button、Checkbox、Switch、Tabs |
| ビジュアルデザインとスタイル付きコンポーネント | アプリまたはコミュニティライブラリ | ブランド化されたコントロール、カード、フォーム行 |
| プラットフォーム固有の機能 | nsh/mobile、nsh/desktop | モバイルのナビゲーションバー、デスクトップのウィンドウコントロール |
共通コントロールは、nsh/base にクロスプラットフォームの拠点を 1 つ持ちます。プラットフォームモジュールは、目的とプラットフォームのセマンティクスによってスコープが定められています。TabBar はモバイルのトップレベルナビゲーションを担い、Tabs はプラットフォームをまたいでタブ付きコンテンツを切り替えます。両者の役割は異なります。nsh/mobile が受け入れるのは、モバイル固有のインタラクションセマンティクスを持つ機能です。共通コントロールの外観、サイズ、色合い、アニメーションの違いは、その共有コンポーネントとアプリのスタイルの中で扱います。共通の役割を持つ通知やトーストは、まず 1 つのクロスプラットフォームのコントラクトを軸に設計し、表示方法は内部で適応させます。
共有コンポーネントは、インタラクションを内部で適応させられます。たとえばメニューは、デスクトップではポップアップとして、スマートフォンではシートとして開きます。アプリは 1 つの API を使い、外観を自ら指定します。ナビゲーションヘッダーやアラートのようなシステム管理のプレゼンテーションは、ドキュメントに記載されたプラットフォームごとの表示ルールに従います。アプリは、埋め込みインターフェースを通じて独自のネイティブコンポーネントやサービスを公開できます。
#スタイルなしの基盤とコンポーネントライブラリ層
NSH は、プリミティブとスタイルなしの基盤 (nsh-core と nsh-base) を所有します。スタイル付きのコンポーネントライブラリ層は、アプリケーションとサードパーティのライブラリが所有します。これは、GPUI Kit において gpui-component が担っている役割です。この分担により、各プロダクトはビジュアル言語を自ら制御しながら、コンポーネント実装の難しい部分を再利用できます。
この選択の背景にある経験は、GPUI Kit から得られたものです。そのスタイル付きコンポーネントは、Longbridge Pro の開発から生まれました。アプリケーションに求められるデザインがますます多様になるにつれ、カスタマイズの要求が高まり、ユーザーはコンポーネントをフォークするようになりました。共通の基盤を gpui-base として切り出したことで、振る舞いをそれらのデザイン間で再利用できるようになりました。スタイル付きコンポーネントは、デザインの参考として、またカスタマイズの範囲で要件を満たせるアプリケーションにとって、今も有用です。基盤を使えば、それ以外のアプリケーションはプレゼンテーションを直接制御できます。
NSH は、この教訓を最初から適用しています。nsh/base は、複雑な振る舞い、インタラクション、リアクティブな状態、フォーカス、アクセシビリティ、適応型プレゼンテーションを所有し、各振る舞いを所有するレイヤーでテストを行います。これには Dock のような大きな構造も含まれます。アプリケーションは、スタイル、状態、スロット、パーツを通じて、この基盤の上に多様なデザインを構築します。コンポーネントへの貢献も同じ境界に従います。ビジュアルのデフォルトやブランド化されたバリアントは、アプリケーションまたはサードパーティのコンポーネントに属します。ドキュメント化されたシステム管理のプレゼンテーションと TextView の読み取りに関するデフォルトは、それぞれ固有のコントラクトを保持します (アーキテクチャ)。
#Gallery が示すもの
Web サイトのデモと Gallery は、スタイルを施したサンプルアプリケーションです。グラデーション、シャドウ、角丸、トランジション、モーションは、NSH のカスタマイズ機能を実際に使ってみせるものであり、ソースコードの例にもなります。これらの選択はデモと Gallery に属するもので、再利用可能な基本コンポーネントは、その下にある振る舞いとパーツを公開します。アプリケーションは例を取り入れることも、まったく別のビジュアル言語を構築することもできます。
独立して配布されるスタイル付きライブラリは、前述のアプリケーション/コミュニティ層に属します。Gallery のスタイルは 1 つのデザインの方向性を示すものであり、特定のプロダクトに適しているかどうかは、そのプロダクトのデザイン上の判断です。
#1 つのエンジン上の Rust と TSX
Rust アプリ、TSX 画面、そして両者が混在するプロジェクトは、プリミティブ、基本コンポーネント、シグナル、レイアウトを共有します。Rust はコンパイル済みのアプリケーションロジックと再利用可能なネイティブコンポーネントを提供します。TSX は、迅速なイテレーションと実行時に配信されるモジュールを支えます (Rust でのビルド)。
エンジンは、変更されたシグナルに依存するバインディングを更新し、ビュー操作をバッチ処理します。テキストレイアウト、ネイティブアニメーション、入力は、エンジンとそのプラットフォームバックエンドが担います (アーキテクチャ)。パフォーマンスは、再現可能なアプリケーションのワークロードで評価されます (パフォーマンス)。
#埋め込み、動的配信、AI
既存のネイティブアプリは、機能を置きたい場所に NSH のビューを配置し、独自のネイティブコンポーネントとホストサービスを公開します。スタンドアロンアプリも、同じランタイムとコンポーネントモデルを使用します (プラットフォーム)。
動的に配信される TSX モジュールは、自身の状態、ロジック、レイアウトを所有します。署名付きパッケージは、ホストがどの発行元を信頼するかを確立し、サンドボックスの制限とケイパビリティは、モジュールに許可される操作を定義します。信頼と権限の両方を決定するのはホストです (署名付きパッケージ、サンドボックスとケイパビリティ)。
AI が生成する UI もこのコントラクトに従います。宣言された API に対して TSX を生成し、チェックとテストを行い、モジュールをビルドして署名し、ホストのポリシーのもとで検証して実行します。生成された宣言、モデルが読めるドキュメント、CLI テストにより、このワークフローは検査可能で再現可能になります (テストとトレース)。
#これらの目標が追加の指針となる仕組み
- ユーザーの振る舞いを明確にし、それがプラットフォーム間で共有されるものかどうかを確認します。
- 共有される振る舞いは、既存のプリミティブまたは基本コンポーネントに置き、アプリがカスタマイズできるように状態とパーツを公開します。
- プラットフォーム固有のセマンティクスを持つ機能は、そのプラットフォームのモジュールに置き、適用範囲と共有 UI との組み合わせ方を文書化します。
- スタイル付きコンポーネントは、アプリまたはコミュニティライブラリで構築します。
- 影響を受けるプラットフォームで、振る舞い、アクセシビリティ、レイアウト、入力を検証し、公開コントラクトを両方の言語で文書化します。
これらの原則により、NSH が成長しても、ビジュアルデザインの柔軟性、共有コンポーネント API の一貫性、プラットフォーム統合の明確さが保たれます。