여행 · 새 리소스

Kiwi Orbit 디자인 시스템.

실제 제품 색상과 간격, 네이티브 수하물 선택 항목, 일관된 가격 내역, 완전한 로컬 검토 흐름을 갖춘 여행 중심 Orbit 가이드입니다.

OpenDesign 가이드8개 챕터참조 항목 38개독자적 적용 가이드
01

Kiwi Orbit 디자인 시스템 인터페이스 미리보기

여행객 수와 추가 옵션을 변경하고, 금액 내역을 확인하세요. 선택을 수정하면 오래된 검토 결과가 지워집니다.

수하물을 선택하고 예시 총액을 확인하세요전체 예시 열기
기본 테마 defaultTheme 및 컴파일된 Tailwind CSS을 사용하는 네이티브 Orbit React 구성 요소 27.7.0, 토큰 참조 11.0.0. · 구현 레퍼런스
02

Kiwi Orbit 디자인 시스템 디자인 참조

기본 테마 defaultTheme 및 컴파일된 Tailwind CSS을 사용하는 네이티브 Orbit React 구성 요소 27.7.0, 토큰 참조 11.0.0.

제품 주요 동작 색상

출처
이름 / 규칙값 / 구성용도
buttonPrimaryBackground#008F7B 주요 동작 상태 참조입니다. hover, active, focus 역할을 구분해 유지하세요.
buttonPrimaryBackgroundHover#007565 주요 동작 상태 참조입니다. hover, active, focus 역할을 구분해 유지하세요.
buttonPrimaryBackgroundActive#006153 주요 동작 상태 참조입니다. hover, active, focus 역할을 구분해 유지하세요.
buttonPrimaryForeground#FFFFFF 주요 동작 상태 참조입니다. hover, active, focus 역할을 구분해 유지하세요.
buttonPrimaryForegroundHover#FFFFFF 주요 동작 상태 참조입니다. hover, active, focus 역할을 구분해 유지하세요.
buttonPrimaryForegroundActive#FFFFFF 주요 동작 상태 참조입니다. hover, active, focus 역할을 구분해 유지하세요.
buttonPrimaryBorderColorFocusrgba(0, 143, 123, 0.5)주요 동작 상태 참조입니다. hover, active, focus 역할을 구분해 유지하세요.

구성 요소 간격

출처
이름 / 규칙값 / 구성용도
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 디자인 시스템 여행 선택 레이아웃

추가 옵션보다 먼저 경로를 보여주세요

경로 요약에는 수하물 옵션 앞에 두 공항 코드와 도시 이름, 가상의 소요 시간이 표시됩니다. 이를 통해 사용자가 추가 옵션을 비교하는 동안에도 구매 맥락을 확인할 수 있습니다. 점선 연결선은 CSS의 독창적인 일러스트이며, 항공사의 경로 그래픽이나 실제 서비스에 대한 약속이 아닙니다.

이 OpenDesign 가이드에서

선택 항목과 총액을 구분하세요

한쪽에는 여행객과 수하물 선택 항목을, 옆에는 금액 내역을 배치합니다. 선택 상태에 따라 선택 컨트롤과 금액이 함께 결정됩니다. 휴대전화에서는 문서 순서에 따라 선택 항목 다음에 요약이 표시되므로, 어떤 입력값이 총액에 반영됐는지 명확하게 알 수 있습니다.

Kiwi Orbit 디자인 시스템 제품 색상 및 피드백

주요 동작에는 제품 색상군을 사용하세요

토큰 패키지는 hover와 active 상태에 서로 다른 색조를 적용한 녹색 제품 동작 색상을 제공합니다. 임의로 브랜드 녹색을 추측하지 말고 참조에 정확한 버튼 역할별 값을 명시하세요. 중립적인 구름색 표면으로 선택 가능한 추가 옵션을 감싸 검토 동작과 패널이 서로 경쟁하지 않도록 합니다.

결과에 맞는 구체적인 피드백을 제공하세요

네이티브 성공 알림에는 ‘선택 항목을 로컬에서 검토했습니다’라고 표시하고 여행객 수와 총액을 안내합니다. 선택을 변경할 때마다 알림이 지워집니다. 따라서 이전의 녹색 확인 메시지가 새로 수정한 추가 옵션까지 검증한 것처럼 계속 표시되지 않습니다.

Kiwi Orbit 디자인 시스템 타이포그래피 및 가격 위계

설명 문구에는 네이티브 텍스트 역할을 사용하세요

Orbit는 13px 작은 본문과 15px 일반 본문 역할 외에도 더 큰 크기 옵션을 제공합니다. 이 예제에서는 네이티브 Text 및 Heading 구성 요소를 사용하며, 경로 코드와 총액은 독창적으로 강조했습니다. 브라우저는 여기에 문서화된 대체 글꼴 스택을 사용하며, Kiwi.com 브랜드 글꼴을 몰래 불러오지 않습니다.

금액 옆에 단위를 표시하세요

각 수하물 가격에는 여행객 1인 기준임을 표시합니다. 금액 내역에서는 선택한 추가 옵션별 가격에 여행객 수를 곱하며, 총액은 각 항목보다 시각적으로 강조됩니다. 범위가 표시되지 않은 큰 숫자는 오해하기 쉬우므로 모바일에서도 단위를 생략하지 마세요.

Kiwi Orbit 디자인 시스템 모서리 반경 및 간격 척도

컨트롤과 넓은 표면을 구분하세요

현재 반경 척도에는 2, 4, 6, 8, 12, 16px 단계와 none 및 full이 포함됩니다. 직접 작성한 경로 및 요약 패널에는 12px 모서리를 사용하고, 네이티브 컨트롤은 자체 테마 규칙을 따릅니다. 중첩된 모든 요소에 가장 큰 반경을 적용하면 양식의 위계가 흐려집니다.

줄바꿈이 발생해도 옵션 행의 구조를 유지하세요

Kiwi Orbit 디자인 시스템 제어형 체크박스 및 선택 메뉴

컴포넌트 라벨과 정보 필드 사용

Checkbox에는 공개 props를 통해 표시 라벨과 보조 정보를 전달합니다. Select에는 라벨과 여행객 1~4명을 위한 명시적 옵션을 전달합니다. 이러한 네이티브 구성은 상호작용과 라벨 지정 동작을 그대로 유지하며, 수하물 제어 요소인 것처럼 꾸민 클릭 가능한 div를 사용하지 않습니다.

추가 항목을 각각 독립적으로 모델링

기내 수하물과 위탁 수하물은 별개의 불리언 값입니다. 하나를 선택해도 다른 하나가 자동으로 선택 해제된다고 가정하지 않습니다. 이는 의도적으로 단순화한 예시 정책입니다. 실제 항공사에서는 서로 배타적인 번들이나 승객별 허용량을 적용할 수 있으며, 이 경우 다른 모델이 필요합니다.

Kiwi Orbit 디자인 시스템 선택 요금 계산 및 확인

하나의 공식으로 총액 계산

이 예시에서는 기본 요금에 선택한 1인당 추가 요금을 더한 뒤 여행객 수를 곱합니다. 화면에 표시된 옵션과 달라질 수 있는 별도의 편집 가능한 총액은 저장하지 않습니다. 모든 가격과 허용량은 명시적으로 허구이며, 현재 Kiwi.com에서 제공하는 상품이 아닙니다.

확인용 스냅샷 저장

확인 단계에서는 인원수, 수하물 선택 항목, 총액을 함께 저장합니다. 컨트롤을 변경하면 스냅샷이 삭제됩니다. 이 예시는 상태 일관성을 보여 주며, 로컬에서 클릭한 동작을 예약, 결제, 실시간 잔여석 확인 또는 최종 견적으로 표현하지 않습니다.

Kiwi Orbit 디자인 시스템 접근성 있는 선택 피드백

라벨과 재계산을 함께 확인

키보드나 포인터를 사용하는 사람은 네이티브 컨트롤로 여행객 수를 선택하고 수하물 항목을 켜고 끌 수 있습니다. 확인 결과는 상태 안내 영역에 표시됩니다. 선택 사항인 수하물에 대해 허위 검증을 하지 않습니다. 두 추가 항목을 모두 선택하지 않는 것도 이 가상의 요금에서 유효한 상태입니다.

  1. 여행객 2명을 선택하고 기내 수하물을 추가하세요.
  2. 위탁 수하물을 추가하고 세 가지 요금 내역을 모두 확인하세요.
  3. 로컬에서 선택 내용을 확인하고 항목을 변경한 뒤, 이전 성공 메시지가 사라지는지 확인하세요.

숨겨진 결과 방지

양식 위와 총액 옆에 허구의 예시임을 설명합니다. 동작 이름은 구매나 예약이 아닌 ‘로컬 선택 내용 확인’입니다. 모든 변경 사항은 페이지 안에서만 처리되며, 필요하지 않은 승객 개인 정보는 데모용으로 요청하지 않습니다.

Kiwi Orbit 디자인 시스템 Provider 및 컴파일된 스타일

호환되는 안정 버전 사용

이 예시에서는 React components 27.7.0과 token references 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 디자인 시스템 에이전트 설정

구현 시작점

고정된 기본 예제를 번들링한 뒤 로컬 브라우저에서 확인했습니다. 이 예제는 로컬 애플리케이션 상태만 사용합니다.

sh
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

프로젝트를 위한 프롬프트

에이전트 프롬프트
Orbit 네이티브 컴포넌트와 컴파일된 스타일을 사용해 여행 추가 항목 선택기를 만드세요. 경로 정보, 1인당 가격, 선택한 추가 항목, 총액의 일관성을 유지하세요. 허구의 가격과 로컬 확인임을 명확히 표시하고, 편집 시 이전 확인 내용을 삭제하며, 예약이나 결제 기능이 있는 것처럼 표현하지 마세요.
05

Kiwi Orbit 디자인 시스템 출처 및 범위

OpenDesign 애플리케이션 가이드. 경로, 소요 시간, 가격, 수하물 허용량은 허구입니다. 네이티브 Orbit 컨트롤은 로컬에서 동작하며 항공편 검색, 예약 또는 결제는 진행되지 않습니다.