メインコンテンツへスキップ
フロントコンポーネントは、Twenty の UI 内で直接レンダリングされる React コンポーネントです。 フロントコンポーネントは Remote DOM を使用する分離された Web Worker内で実行されます。コードはサンドボックス化され、不透明なオリジンの iframe 内で動作しますが、その UI はその iframe 内に制限されるのではなく、ページ内でネイティブにレンダリングされます。

フロントコンポーネントを使用できる場所

フロントコンポーネントは、Twenty 内の2つの場所でレンダリングできます:
  • サイドパネル — ヘッドレスでないフロントコンポーネントは、右側のサイドパネルで開きます。 フロントコンポーネントがコマンドメニューからトリガーされた場合のデフォルトの動作です。
  • ウィジェット(ダッシュボードとレコードページ) — フロントコンポーネントは、ページレイアウト内にウィジェットとして埋め込めます。 ダッシュボードやレコードページのレイアウトを設定する際、ユーザーはフロントコンポーネントのウィジェットを追加できます。
フロントコンポーネント単体では UI から直接アクセスできないため、それを表示する必要があります。 それを行う方法は次の 2 つです。
  • コマンドメニュー項目とペアにする — コマンドメニュー(Cmd+K)に登録し、必要に応じてピン留めされたクイックアクションとして登録します。
  • ページレイアウト内のウィジェットとして埋め込む — レコードの詳細ページまたはダッシュボード上に配置します。

基本的な例

フロントコンポーネントの動作を手早く確認するには、defineCommandMenuItemとペアにして、ページ右上隅にクイックアクションボタンとして表示させるのが最も簡単です。
src/front-components/hello-world.tsx
src/command-menu-items/hello-world.command-menu-item.ts
yarn twenty dev で同期するか(または 1 回限りで yarn twenty apply を実行すると)、ページ右上にクイックアクションが表示されます:
右上のクイックアクションボタン
クリックすると、コンポーネントがインラインでレンダリングされます。

設定フィールド

フロントコンポーネントをページに配置する

コマンド以外にも、ページレイアウトでウィジェットとして追加することで、フロントコンポーネントをレコードページに直接埋め込めます。 詳しくはページレイアウトを参照してください。

ヘッドレスと非ヘッドレス

フロントコンポーネントには、isHeadless オプションで制御される2つのレンダリングモードがあります: 非ヘッドレス(デフォルト) — コンポーネントは可視のUIをレンダリングします。 コマンドメニューからトリガーされた場合、サイドパネルで開きます。 isHeadlessfalse または省略された場合のデフォルトの動作です。 ヘッドレス (isHeadless: true) — コンポーネントはバックグラウンドで不可視のままマウントされます。 サイドパネルは開きません。 ヘッドレスコンポーネントは、ロジックを実行して自動的にアンマウントするアクション向けに設計されています。例えば、非同期タスクの実行、ページへのナビゲーション、確認モーダルの表示などです。 以下で説明する SDK の Command コンポーネントと自然に組み合わせて使用できます。
src/front-components/sync-tracker.tsx
このコンポーネントが null を返すため、Twenty はそのためのコンテナのレンダリングをスキップします—レイアウトに空白は発生しません。 コンポーネントは引き続き、すべてのフックとホスト通信 API にアクセスできます。

SDK の Command コンポーネント

twenty-sdk パッケージは、ヘッドレスのフロントコンポーネント向けに設計された4つの Command ヘルパーコンポーネントを提供します。 各コンポーネントは、マウント時にアクションを実行し、エラーをスナックバー通知で処理し、完了時にフロントコンポーネントを自動的にアンマウントします。 twenty-sdk/front-component からインポートします:
  • Commandexecute プロップ経由で非同期コールバックを実行します。
  • CommandLink — アプリのパスにナビゲートします。 Props: to, params, queryParams, options.
  • CommandModal — 確認モーダルを開きます。 ユーザーが確認すると、execute コールバックを実行します。 Props: title, subtitle, execute, confirmButtonText, confirmButtonAccent.
  • CommandOpenSidePanelPage — サイドパネルページを開きます。 Props は page に依存します。たとえば、ViewRecordrecordIdobjectNameSingular(さらに任意で、特定のタブでレコードを開くための tab id)を受け取り、他のページは pageTitlepageIcon を受け取ります。
Command を使用してコマンドメニューからアクションを実行するヘッドレスのフロントコンポーネントの完全な例です:
src/front-components/run-action.tsx
src/command-menu-items/run-action.command-menu-item.ts
さらに、実行前に確認を求めるために CommandModal を使用する例です:
src/front-components/delete-draft.tsx
そして、CommandOpenSidePanelPage を使用して、現在のレコードを特定のタブのサイドパネルで開く例です。 tab はページレイアウトのタブ id です(デフォルトのレイアウトでは company-tab-emailscompany-tab-timeline のような id を使用し、カスタムレイアウトではタブ自身の id を使用します)。 その id がレコードのレイアウト内に存在しない場合は、代わりにデフォルトのタブが開きます。
src/front-components/open-company-emails.tsx

ロジック関数の呼び出し

フロントコンポーネントは不透明なオリジンの iframe 内にサンドボックス化された Web Worker 内でブラウザーサイドで実行され、一方でロジック関数はサーバーサイドで実行されます。 両者の間にプロセス内での直接呼び出しはありません。その代わり、フロントコンポーネントは HTTP 経由でロジック関数にアクセスします。 httpRouteTriggerSettings で宣言されたロジック関数は、そのルートパスで HTTP 経由でアクセスできます。 RestApiClient は、/s/ で始まるパスをアプリのルートとして扱い、それらをあなたの関数が提供されている URL に解決し、TWENTY_APP_ACCESS_TOKEN で認証します。
Twenty Cloud では、HTTP トリガーのロジック関数はワークスペースごとの専用ドメインで提供されますhttps://\<your-workspace-subdomain>.withtwenty.com\<path> で提供されます。 外部から呼び出す場合は、関数の HTTP trigger 設定、もしくはアプリケーションの Settings タブから、正確な URL をコピーしてください。
ヘッドレスフロントコンポーネントは、Command コンポーネント経由でマウント時に呼び出しを実行し、その後自動的にアンマウントできます。
src/front-components/sync-prs.tsx
RestApiClient に渡されるパスは、ロジック関数の httpRouteTriggerSettings.path/s を付加したものです。 isAuthRequired: true のままにしておいてください。コンポーネント用に Twenty が発行する TWENTY_APP_ACCESS_TOKEN によってリクエストが認証されます。
src/logic-functions/fetch-prs.logic-function.ts
TWENTY_APP_ACCESS_TOKEN は自動的に挿入されます。詳しくは Application variables を参照してください。 秘匿アプリケーション変数はフロントコンポーネントに公開されることがないため、API キーやその他の機密性の高いロジックはフロントコンポーネントではなく、ロジック関数側に保持してください。

Twenty REST API の呼び出し

アプリの HTTP ルートを呼び出したり、フロントコンポーネントから Twenty のレコードを読み書きしたりするには、twenty-client-sdk/restRestApiClient を使用します。 これは、/s/... のパスをワークスペースの関数のベース URL に送り、/rest/... を含むそれ以外のすべてのパスを TWENTY_API_URL に送信します。 options には、headersquery(クエリ文字列パラメーターのレコード。null 相当の値はスキップされます)、および signal 経由の AbortSignal を指定できます。 FormData ではないオブジェクト body は、自動的に JSON シリアル化されます。 401 が発生した場合、クライアントはホスト経由で一度だけアクセス トークンを更新し、そのリクエストを再試行します。 ベース URL とトークンは、デフォルトで環境から解決されます。 必要に応じてコンストラクターに上書き設定を渡します — たとえばテスト時などです:
失敗したリクエストは RestApiClientError をスローし、statusstatusTexturl、および解析済みの body を公開します:

ランタイムコンテキストへのアクセス

コンポーネント内で、SDK のフックを使用して現在のユーザー、レコード、コンポーネントインスタンスにアクセスします:
src/front-components/record-info.tsx
利用可能なフック:

アプリケーション変数

isSecret: false が設定された defineApplication() 内で定義されたアプリケーション変数は、getApplicationVariable ユーティリティを通じてフロントコンポーネント内で利用できます。
src/front-components/greeting.tsx
シークレット変数(isSecret: true)はフロントコンポーネントには公開されません。 それらは、サーバーサイドで実行されるロジック関数でのみ利用できます。 これにより、API キーなどの機密値がブラウザーに送信されるのを防ぎます。
getApplicationVariable は、変数に宣言されている type に関係なく、常に string(または undefined)を返します。 文字列は型に応じて一貫した方法でシリアライズされます(boolean は "true" / "false"、number は 10 進数の文字列、配列 / オブジェクトは JSON)。これはロジック関数の process.env で使用されているのと同じ形式です。各自でパースしてください(Number(...)JSON.parse(...)=== 'true' など)。 Variable types を参照してください。 次のシステム変数は、常に process.env 経由で利用できます。

TWENTY_FUNCTIONS_URL

Twenty はまた、TWENTY_FUNCTIONS_URL をフロントコンポーネントとロジック関数に挿入します。これは、アプリの HTTP トリガーのロジック関数が提供されるベース URL です。 この変数が存在するのは、その URL が必ずしも Twenty サーバー自体とは限らないためです。 Twenty Cloud では、アプリのルートはワークスペースごとの専用ドメイン(https://\<your-workspace-subdomain>.withtwenty.com、または設定されている場合はアプリケーションのプライマリ公開ドメイン)で提供されます。これにより、アプリで作成されたレスポンスが Twenty アプリのオリジンではなく分離されたオリジン上で実行されます。 セルフホストおよびローカルインスタンスでは、アプリのルートはサーバー自体の /s プレフィックスの下で提供され、この変数がまったく設定されない場合もあります。 ベース URL はワークスペースやインスタンスごとに異なるため、コードでハードコードすることはできません。サーバーが実行時に正しい値を挿入します。 この変数を直接読む必要があることはほとんどありません。 /s/ プレフィックス付きのパスで RestApiClient を通じてルートを呼び出すと、クライアントが URL を解決します。/s プレフィックスを取り除き、TWENTY_FUNCTIONS_URL をターゲットにし、この変数が設定されていない場合は \<TWENTY_API_URL>/s をフォールバックとして使用します。 リクエストを送信せずに絶対 URL を取得するには、resolveUrl('/s/\<path>') を使用します(リンクなどの用途)。 URL を手作業で組み立てる場合にのみ、この変数を直接読み取ってください。

ホスト通信 API

フロントコンポーネントは、twenty-sdk の関数を使用してナビゲーション、モーダル、通知をトリガーできます: アクション完了後にホスト API を使用してスナックバーを表示し、サイドパネルを閉じる例です:
src/front-components/archive-record.tsx

複数のレコードを扱う

複数の選択されたレコードを処理するには useSelectedRecordIds() を使用してください。 これは一括操作に役立ちます:
src/front-components/bulk-export.tsx
レコードの選択に制限されたコマンドメニューアイテムとして表示します:
src/command-menu-items/bulk-export.command-menu-item.ts

公開アセット

フロントコンポーネントは、getPublicAssetUrl を使用してアプリの public/ ディレクトリ内のファイルにアクセスできます:
詳細は公開アセットのセクションを参照してください。

スタイリング

フロントコンポーネントは複数のスタイリング手法をサポートしています。 次のものを使用できます:
  • インラインスタイルstyle={{ color: 'red' }}
  • Twenty UI コンポーネント — Twenty 独自のコンポーネントライブラリです。以下の Using Twenty UI components を参照してください
  • Emotion@emotion/react による CSS-in-JS
  • styled-componentsstyled.div パターン
  • Tailwind CSS — ユーティリティクラス
  • React と互換性のある任意の CSS-in-JS ライブラリ

Twenty UI コンポーネントの使用

Twenty はコンポーネントライブラリを twenty-ui パッケージとして提供しています。 フロントエンドコンポーネントでは、ボタン、タグ、ステータスピル、チップ、アバター、アイコン、タイポグラフィ、そしてワークスペースのライト/ダークテーマに自動で合わせてくれるテーマトークンなどに利用できます。

インストール

Twenty インスタンスに同梱されているバージョンに固定して、そのパッケージをアプリに追加します。
twenty-ui はビルド時にフロントエンドコンポーネントへバンドルされるため、アプリの依存関係に追加するだけで済み、実行時に設定することは何もありません。

コンポーネントのインポート

パッケージのルートではなく、対応するサブパスからインポートすることで、使用しているコンポーネントだけがバンドルに含まれるようにします。

アイコン

twenty-ui/icon から個別のアイコンをインポートします:
それぞれの名前付きアイコンはツリーシェイクされるため、少数をインポートしてもバンドルサイズへの影響はわずかです。 IconsProvideruseIconsiconsState の使用は避けてください。これらは Tabler アイコンセット全体(数 MB)を読み込みます。

テーマ設定とテーマトークン

Twenty UI コンポーネントはワークスペースのライト/ダークテーマに自動的に追従します。レンダラーがホスト上のアクティブなカラースキームを適用し、コンポーネントはそれに基づいて色を決定します。 独自のインラインスタイルでも同じデザイントークンを使うには、useTheme() フックを呼び出します。 これにより、アクティブなテーマに紐づいた Twenty のテーマトークン(スペーシング、カラー、角丸、フォント)が返されます。コンポーネント側で ThemeProvider をセットアップする必要はありません。
useTheme() はフックなので、コンポーネント本体の中でトークンを読み取り、値が常に現在のテーマを反映するようにできます。 同じトークンマップは themeCssVariables 定数としてもエクスポートされていますが、フロントエンドコンポーネントでは useTheme() を優先してください。アプリのマニフェストを抽出している間は、themeCssVariables を参照するモジュールレベルの定数が未定義になる可能性があります。 アクティブなスキームを明示的に分岐させるには、twenty-sdk/front-componentuseColorScheme() を使って取得します。このフックは 'light' または 'dark' を返します。