旅游出行 · 新しいリソース

Kiwi Orbit デザインシステム.

実際の製品カラーとスペーシング、標準の手荷物選択、統一された料金の内訳、ローカルで完結するレビューの一連の流れを備えた、旅行に特化したOrbitガイドです。

OpenDesign ガイド8章リファレンス項目 38 件オリジナルアプリケーションガイド
01

Kiwi Orbit デザインシステムのインターフェースプレビュー

旅行者数と追加オプションを変更して内訳を確認し、選択肢を編集して古い確認内容をクリアします。

手荷物を選択して合計金額を確認完全な例を開く
Native Orbit React コンポーネント 27.7.0(defaultTheme およびコンパイル済み Tailwind CSS); トークンリファレンス 11.0.0。· 実装リファレンス
02

Kiwi Orbitデザインシステムのデザインリファレンス

Native Orbit React コンポーネント 27.7.0(defaultTheme およびコンパイル済み Tailwind CSS); トークンリファレンス 11.0.0。

製品アクションの色

ソース
名前 / ルール値 / 設定用途
buttonPrimaryBackground#008F7B 主要アクションの状態リファレンス。ホバー、アクティブ、フォーカスの役割を明確に分けます。
buttonPrimaryBackgroundHover#007565 主要アクションの状態リファレンス。ホバー、アクティブ、フォーカスの役割を明確に分けます。
buttonPrimaryBackgroundActive#006153 主要アクションの状態リファレンス。ホバー、アクティブ、フォーカスの役割を明確に分けます。
buttonPrimaryForeground#FFFFFF 主要アクションの状態リファレンス。ホバー、アクティブ、フォーカスの役割を明確に分けます。
buttonPrimaryForegroundHover#FFFFFF 主要アクションの状態リファレンス。ホバー、アクティブ、フォーカスの役割を明確に分けます。
buttonPrimaryForegroundActive#FFFFFF 主要アクションの状態リファレンス。ホバー、アクティブ、フォーカスの役割を明確に分けます。
buttonPrimaryBorderColorFocusrgba(0, 143, 123, 0.5)主要アクションの状態リファレンス。ホバー、アクティブ、フォーカスの役割を明確に分けます。

コンポーネントの間隔

ソース
名前 / ルール値 / 設定用途
space502px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space1004px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space1506px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space2008px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space30012px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space40016px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space50020px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space60024px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space80032px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space100040px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
space120048px公開済みトークンパッケージで定義された、実際のピクセル単位の間隔値です。
名前 / ルール値 / 設定用途
borderRadius502px用途に応じた角丸で、コントロールと大きな旅行情報の背景面を使い分けます。
borderRadius1004px用途に応じた角丸で、コントロールと大きな旅行情報の背景面を使い分けます。
borderRadius1506px用途に応じた角丸で、コントロールと大きな旅行情報の背景面を使い分けます。
borderRadius2008px用途に応じた角丸で、コントロールと大きな旅行情報の背景面を使い分けます。
borderRadius30012px用途に応じた角丸で、コントロールと大きな旅行情報の背景面を使い分けます。
borderRadius40016px用途に応じた角丸で、コントロールと大きな旅行情報の背景面を使い分けます。
borderRadiusNone0用途に応じた角丸で、コントロールと大きな旅行情報の背景面を使い分けます。
borderRadiusFull9999px用途に応じた角丸で、コントロールと大きな旅行情報の背景面を使い分けます。

本文の文字スタイル

ソース
名前 / ルール値 / 設定用途
fontSizeTextSmall13px公開済みの本文スタイルです。ページ独自の見出しはアプリケーション側で構成します。
fontSizeTextNormal15px公開済みの本文スタイルです。ページ独自の見出しはアプリケーション側で構成します。
fontSizeTextLarge16px公開済みの本文スタイルです。ページ独自の見出しはアプリケーション側で構成します。
fontSizeTextExtraLarge18px公開済みの本文スタイルです。ページ独自の見出しはアプリケーション側で構成します。

製品カラーとニュートラルな背景面

ソース
名前 / ルール値 / 設定用途
paletteCloudLight#F5F7F9 落ち着いた背景面と読みやすいテキストで、製品アクションカラーを引き立てます。
paletteCloudNormal#E8EDF1 落ち着いた背景面と読みやすいテキストで、製品アクションカラーを引き立てます。
paletteInkDark#252A31 落ち着いた背景面と読みやすいテキストで、製品アクションカラーを引き立てます。
paletteInkLight#657890 落ち着いた背景面と読みやすいテキストで、製品アクションカラーを引き立てます。
paletteInkNormal#4F5E71 落ち着いた背景面と読みやすいテキストで、製品アクションカラーを引き立てます。
paletteProductLight#E1F4F3 落ち着いた背景面と読みやすいテキストで、製品アクションカラーを引き立てます。
paletteProductNormal#008F7B 落ち着いた背景面と読みやすいテキストで、製品アクションカラーを引き立てます。
paletteProductDark#007061 落ち着いた背景面と読みやすいテキストで、製品アクションカラーを引き立てます。
03

Kiwi Orbitデザインシステム完全ガイド

実際のインターフェースで、このデザインシステムを選び、適用し、レビューするための実践ガイドです。

DESIGN-kiwi-orbit.md

詳しいガイダンス、実装の出発点、ソースへのリンクをまとめています。

ガイドをダウンロード

Kiwi Orbitデザインシステムの旅行選択レイアウト

追加オプションの前にルートを示す

ルート概要には、追加手荷物の選択肢の前に、2つの空港コード、都市名、架空の所要時間を表示します。これにより、利用者は追加オプションを比較しながら購入内容を確認できます。点線のコネクターは独自のCSSイラストであり、航空会社のルート図でも、実在するサービスを示すものでもありません。

この OpenDesign ガイドから

選択肢と合計金額を分けて表示する

片側に搭乗者と手荷物の選択肢を、隣に料金の内訳を配置します。同じ状態から、選択中のコントロールと金額の両方を表示します。スマートフォンでは、概要を選択肢の後に文書順で配置するため、どの入力が合計金額に反映されるのかが明確です。

Kiwi Orbitデザインシステムの製品カラーとフィードバック

主要アクションには製品カラーを使う

トークンパッケージには、ホバー時とアクティブ時で異なる色合いを持つ、緑色の製品アクションカラーが用意されています。推測したブランドカラーに頼らず、リファレンスにはボタンの役割に対応する正確な値を記載します。ニュートラルなクラウドカラーの背景面で選択可能な追加オプションを囲み、確認アクションが埋もれないようにします。

結果に即したフィードバックを表示する

ネイティブの成功アラートには「選択内容をローカルで確認しました」と表示し、搭乗者数と合計金額を示します。選択肢が変更されるとアラートは消去されます。そのため、追加オプションを編集した後も、以前の緑色の確認表示が新しい選択内容を検証したかのように残ることはありません。

Kiwi Orbitデザインシステムのタイポグラフィと価格の階層

説明文にはネイティブのテキストスタイルを使う

Orbit では、13px の小サイズと 15px の通常サイズを含む、複数の本文スタイルが用意されています。このサンプルではネイティブの Text コンポーネントと Heading コンポーネントを使い、ルートコードと合計金額は独自に強調しています。ここでは文書化されたフォールバックフォントスタックをブラウザーで使用し、Kiwi.com のブランドフォントを暗黙に読み込むことはありません。

金額のそばに単位を表示する

各手荷物料金には「搭乗者1人あたり」と明記します。内訳では、選択した追加オプションごとの料金に搭乗者数を掛け、合計金額を各項目より目立たせます。金額だけでは対象範囲を誤解しやすいため、モバイルでも単位を省略しないでください。

Kiwi Orbitデザインシステムの角丸と間隔のスケール

コントロールと大きな背景面を使い分ける

現在の角丸スケールには、2、4、6、8、12、16px の段階と、なし・最大の値があります。作成したルートパネルと概要パネルには12pxの角丸を使い、ネイティブのコントロールにはそれぞれのテーマ規則を適用します。入れ子になったすべての要素に最大の角丸を適用すると、フォームの階層がわかりにくくなります。

折り返し時も選択肢の行を保つ

Kiwi Orbitデザインシステムのチェックボックスとセレクト

コンポーネントのラベルと情報フィールドを使う

Checkbox には、公開プロパティを使って表示ラベルと補足情報を渡します。Select にはラベルと、搭乗者1人から4人までの明示的な選択肢を設定します。こうしたネイティブの構成なら、手荷物コントロールを装ったクリック可能な div を使わずに、操作性とラベル付けの動作を保てます。

追加オプションを個別に扱う

機内持ち込み手荷物と預け入れ手荷物は、それぞれ独立した真偽値で管理します。一方を選択したときに、もう一方が自動的に解除されることはありません。これは意図的に簡略化したサンプル上の仕様です。実際の航空会社では、相互排他的なバンドルや搭乗者ごとの許容量に応じて、別のデータモデルが必要になる場合があります。

Kiwi Orbitデザインシステムの選択内容の計算と確認

1つの計算式から合計金額を算出する

このサンプルでは、搭乗者数に基本運賃と、選択した1人あたりの追加料金の合計を掛けて計算します。表示中の選択肢とずれる可能性がある、個別に編集可能な合計金額は保存しません。すべての料金と許容量は架空のものであり、現在の Kiwi.com の販売内容ではありません。

確認用のスナップショットを記録する

確認時には、搭乗者数、手荷物の選択内容、合計金額をまとめて記録します。いずれかのコントロールを変更すると、そのスナップショットは消去されます。これにより、ローカルでのクリックが予約、決済、リアルタイムの空席確認、確定見積もりを意味するかのように見せることなく、状態の一貫性を示せます。

Kiwi Orbitデザインシステムのアクセシブルな選択フィードバック

ラベルと再計算をあわせて確認する

キーボードでもポインターでも、ネイティブのコントロールを使って搭乗者数を選び、どちらかの手荷物オプションを切り替えられます。確認結果はステータス領域に表示されます。任意の手荷物オプションについて、存在しない入力検証を作り出すことはありません。この架空の運賃では、追加オプションをどちらも選択しない状態も正当です。

  1. 搭乗者を2人選び、機内持ち込み手荷物を追加してください。
  2. 預け入れ手荷物を追加し、内訳の3つの金額を確認してください。
  3. ローカルで選択内容を確認した後、選択肢を変更し、以前の成功メッセージが消えることを確認してください。

意図しない影響を生まない

フォームの上と合計金額の横に、このページが架空の例であることを説明します。アクション名は「ローカルで選択内容を確認」であり、「購入」や「予約」ではありません。変更はすべてページ内にとどまり、デモに不要な搭乗者の個人情報も求めません。

Kiwi Orbitデザインシステムのプロバイダーとコンパイル済みスタイル

互換性のある安定版リリースを使う

このサンプルでは、コンポーネントのバージョンを27.7.0、トークン参照のバージョンを11.0.0に固定しています。OrbitProvider、パッケージのdefaultTheme、コンパイル済みのlib/tailwind.cssを読み込みます。このスタイルシートを省略すると、Reactツリーがレンダリングされても、ユーティリティベースのコンポーネントスタイルが不完全になります。

  • OrbitProviderとパッケージのdefaultTheme。
  • components 27.7.0のコンパイル済みlib/tailwind.css。
  • パッケージのビルド環境にはNode.js 22以降が必要です。

デプロイ要件を明確にする

Kiwi Orbitデザインシステムのコンポーネント例

main.jsx — 動作するサンプル一式

手荷物を選択して、合計金額の例を確認できます。以下のソースは、すべての状態と検証処理を含むReactエントリ全体です。

jsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import {
  OrbitProvider,
  Button,
  Checkbox,
  Select,
  Alert,
  Heading,
  Text,
} from "@kiwicom/orbit-components";
import defaultTheme from "@kiwicom/orbit-components/lib/defaultTheme";
import "@kiwicom/orbit-components/lib/tailwind.css";
import "./orbit.css";
function App() {
  const [travellers, setTravellers] = useState("1"),
    [cabin, setCabin] = useState(false),
    [checked, setChecked] = useState(false),
    [saved, setSaved] = useState(null);
  const count = Number(travellers),
    extras = (cabin ? 18 : 0) + (checked ? 32 : 0),
    total = count * (96 + extras);
  function update(fn) {
    fn();
    setSaved(null);
  }
  return (
    <OrbitProvider theme={defaultTheme}>
      <main className="trip">
        <header>
          <Text size="small">ORIGINAL TRAVEL SPECIMEN</Text>
          <Heading as="h1" type="title1">Choose what travels with you</Heading>
          <Text>
            Fictional one-way fare. Prices illustrate the interface, not a
            bookable flight.
          </Text>
        </header>
        <div className="trip-grid">
          <section>
            <div className="route">
              <div>
                <strong>PRG</strong>
                <span>Prague</span>
              </div>
              <div className="route-line">
                <span>1h 45m · direct</span>
                <i></i>
              </div>
              <div>
                <strong>AMS</strong>
                <span>Amsterdam</span>
              </div>
            </div>
            <div className="options">
              <Heading as="h2" type="title3">Travellers and baggage</Heading>
              <Select
                label="Travellers"
                ariaLabel="Travellers"
                value={travellers}
                options={[1, 2, 3, 4].map((n) => ({
                  value: String(n),
                  label: n + " adult" + (n === 1 ? "" : "s"),
                }))}
                onChange={(e) => update(() => setTravellers(e.target.value))}
              />
              <div className="bag-option">
                <div>
                  <Heading as="h3" type="title4">Personal item</Heading>
                  <Text size="small">
                    Fits under the seat · included in this example fare
                  </Text>
                </div>
                <strong>Included</strong>
              </div>
              <div className="bag-option">
                <Checkbox
                  label="Add cabin baggage"
                  info="One 10 kg bag per traveller · fictional allowance"
                  checked={cabin}
                  onChange={(e) => update(() => setCabin(e.target.checked))}
                />
                <strong>
                  €18<span>/ traveller</span>
                </strong>
              </div>
              <div className="bag-option">
                <Checkbox
                  label="Add checked baggage"
                  info="One 20 kg bag per traveller · fictional allowance"
                  checked={checked}
                  onChange={(e) => update(() => setChecked(e.target.checked))}
                />
                <strong>
                  €32<span>/ traveller</span>
                </strong>
              </div>
            </div>
          </section>
          <aside>
            <Heading as="h2" type="title3">Your example selection</Heading>
            <dl>
              <dt>Base fare × {count}</dt>
              <dd>€{96 * count}</dd>
              {cabin && (
                <>
                  <dt>Cabin baggage × {count}</dt>
                  <dd>€{18 * count}</dd>
                </>
              )}
              {checked && (
                <>
                  <dt>Checked baggage × {count}</dt>
                  <dd>€{32 * count}</dd>
                </>
              )}
            </dl>
            <div className="trip-total">
              <span>Total</span>
              <strong>€{total}</strong>
            </div>
            <Text size="small">
              All amounts are illustrative. No payment or reservation will be
              created.
            </Text>
            <Button
              fullWidth
              onClick={() => setSaved({ count, cabin, checked, total })}
            >
              Review local selection
            </Button>
            {saved && (
              <div role="status" className="trip-confirm">
                <Alert type="success" title="Selection reviewed locally">
                  {saved.count} traveller{saved.count === 1 ? "" : "s"} · €
                  {saved.total}. No booking created.
                </Alert>
              </div>
            )}
          </aside>
        </div>
        <footer>
          Native Orbit 27.7.0 components and compiled package styles. Original
          layout and fictional pricing logic by OpenDesign.
        </footer>
      </main>
    </OrbitProvider>
  );
}
createRoot(document.getElementById("root")).render(<App />);

コードリファレンス

  • Vite React プロジェクトを作成し、<div id="root"></div> を残したまま、これを src/main.jsx として読み込みます。

orbit.css — 元のレスポンシブ構成

ネイティブコンポーネントを基にしたアプリケーションレイアウト。

CSS
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  background: #f5f7f9;
  color: #252a31;
  font:
    16px/1.5 Arial,
    sans-serif;
}
.trip {
  padding: 32px;
}
.trip header {
  max-width: 760px;
  margin-bottom: 28px;
}
.trip header h1 {
  margin: 8px 0 12px;
}
.trip-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(280px, 1fr);
  gap: 24px;
}
.route,
.options,
.trip aside {
  background: #fff;
  border-radius: 12px;
  border: 1px solid #e8edf1;
  padding: 24px;
}
.route {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 20px;
}
.route strong {
  font-size: 32px;
  display: block;
}
.route span {
  font-size: 14px;
  display: block;
  color: #4f5e71;
}
.route-line {
  flex: 1;
  text-align: center;
}
.route-line i {
  display: block;
  border-top: 2px dashed #bac7d5;
  margin-top: 12px;
}
.options > h3 {
  margin-bottom: 20px;
}
.options > div:first-of-type {
  margin-bottom: 12px;
}
.bag-option {
  display: flex;
  gap: 20px;
  align-items: center;
  justify-content: space-between;
  padding: 24px 0;
  border-top: 1px solid #e8edf1;
}
.bag-option:last-child {
  padding-bottom: 0;
}
.bag-option > strong {
  white-space: nowrap;
  font-size: 18px;
}
.bag-option > strong span {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: #657890;
}
.trip aside {
  align-self: start;
}
.trip dl {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 16px;
  margin: 24px 0;
}
.trip dd {
  margin: 0;
  text-align: right;
  font-weight: 600;
}
.trip-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid #bac7d5;
  padding: 20px 0;
}
.trip-total strong {
  font-size: 32px;
}
.trip aside > button {
  margin-top: 24px;
}
.trip-confirm {
  margin-top: 20px;
}
.trip footer {
  font-size: 12px;
  color: #657890;
  margin-top: 24px;
}
@media (max-width: 900px) {
  .trip-grid {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 550px) {
  .trip {
    padding: 16px;
  }
  .route,
  .options,
  .trip aside {
    padding: 20px;
  }
  .route {
    gap: 12px;
  }
  .route strong {
    font-size: 28px;
  }
  .route-line span {
    font-size: 12px;
  }
  .bag-option {
    align-items: flex-start;
    gap: 12px;
  }
}

コードリファレンス

  • main.jsx と同じ場所に保存します。ライブラリのトークンリファレンスとは異なる、カスタムの構成ルールです。
04

Kiwi Orbitデザインシステムのエージェント設定

実装の出発点

バージョンを固定したネイティブのサンプルをバンドルし、ローカルのブラウザーで動作を確認しました。このサンプルでは、アプリケーションのローカルな状態だけを使用します。

シェル
npm create vite@latest orbit-trip -- --template react
cd orbit-trip
npm install
npm install [email protected] [email protected] @kiwicom/[email protected]
# Use Node.js >=22. Replace src/main.jsx and add src/orbit.css.
npm run dev

あなたのプロジェクト向けプロンプト

AI エージェント用プロンプト
Orbitのネイティブコンポーネントとコンパイル済みスタイルを使って、旅行の追加オプション選択画面を作成します。ルート情報、旅行者ごとの料金、選択したオプション、合計金額に一貫性を持たせます。価格が架空であり、確認処理がローカルで行われることを明示し、編集時には古い確認内容をクリアしてください。予約や決済が可能であるかのような表現は避けてください。
05

Kiwi Orbitデザインシステムの情報源と適用範囲

OpenDesignのアプリケーションガイド。ルート、所要時間、料金、手荷物許容量は架空のものです。Orbitのネイティブコントロールはローカルで動作し、航空券の検索、予約、決済は行いません。