Viagens · Novo recurso

sistema de design Kiwi Orbit.

Um guia do Orbit voltado a viagens, com cores e espaçamentos reais do produto, opções nativas de bagagem, detalhamento de preços consistente e um fluxo completo de revisão local.

Guia OpenDesign8 capítulos38 entradas de referênciaGuia de aplicação original
01

Pré-visualização da interface do sistema de design Kiwi Orbit

Altere o número de viajantes e os extras; confira o detalhamento e remova uma revisão desatualizada editando uma opção.

Escolha a bagagem e confira um total de exemploAbrir exemplo completo
Componentes nativos Orbit React 27.7.0 com defaultTheme e CSS Tailwind compilado; referência dos tokens 11.0.0. · Referência de implementação
02

Referência de design do sistema de design Kiwi Orbit

Componentes nativos Orbit React 27.7.0 com defaultTheme e CSS Tailwind compilado; referência dos tokens 11.0.0.

Cores de ação do produto

Fonte
Nome / RegraValor / ConfiguraçãoUso
buttonPrimaryBackground#008F7B Referência dos estados da ação principal. Mantenha distintos os papéis de hover, active e focus.
buttonPrimaryBackgroundHover#007565 Referência dos estados da ação principal. Mantenha distintos os papéis de hover, active e focus.
buttonPrimaryBackgroundActive#006153 Referência dos estados da ação principal. Mantenha distintos os papéis de hover, active e focus.
buttonPrimaryForeground#FFFFFF Referência dos estados da ação principal. Mantenha distintos os papéis de hover, active e focus.
buttonPrimaryForegroundHover#FFFFFF Referência dos estados da ação principal. Mantenha distintos os papéis de hover, active e focus.
buttonPrimaryForegroundActive#FFFFFF Referência dos estados da ação principal. Mantenha distintos os papéis de hover, active e focus.
buttonPrimaryBorderColorFocusrgba(0, 143, 123, 0.5)Referência dos estados da ação principal. Mantenha distintos os papéis de hover, active e focus.

Espaçamento dos componentes

Fonte
Nome / RegraValor / ConfiguraçãoUso
space502pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space1004pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space1506pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space2008pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space30012pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space40016pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space50020pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space60024pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space80032pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space100040pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.
space120048pxMedidas de espaçamento reais em pixels, conforme o pacote de tokens publicado.

Raios dos cantos

Fonte
Nome / RegraValor / ConfiguraçãoUso
borderRadius502pxDiferentes papéis de raio atendem a controles e superfícies maiores da experiência de viagem.
borderRadius1004pxDiferentes papéis de raio atendem a controles e superfícies maiores da experiência de viagem.
borderRadius1506pxDiferentes papéis de raio atendem a controles e superfícies maiores da experiência de viagem.
borderRadius2008pxDiferentes papéis de raio atendem a controles e superfícies maiores da experiência de viagem.
borderRadius30012pxDiferentes papéis de raio atendem a controles e superfícies maiores da experiência de viagem.
borderRadius40016pxDiferentes papéis de raio atendem a controles e superfícies maiores da experiência de viagem.
borderRadiusNone0Diferentes papéis de raio atendem a controles e superfícies maiores da experiência de viagem.
borderRadiusFull9999pxDiferentes papéis de raio atendem a controles e superfícies maiores da experiência de viagem.

Tipografia do corpo

Fonte
Nome / RegraValor / ConfiguraçãoUso
fontSizeTextSmall13pxPapéis tipográficos publicados para o corpo; os títulos personalizados da página fazem parte da composição da aplicação.
fontSizeTextNormal15pxPapéis tipográficos publicados para o corpo; os títulos personalizados da página fazem parte da composição da aplicação.
fontSizeTextLarge16pxPapéis tipográficos publicados para o corpo; os títulos personalizados da página fazem parte da composição da aplicação.
fontSizeTextExtraLarge18pxPapéis tipográficos publicados para o corpo; os títulos personalizados da página fazem parte da composição da aplicação.

Superfícies do produto e neutras

Fonte
Nome / RegraValor / ConfiguraçãoUso
paletteCloudLight#F5F7F9 Use superfícies discretas e texto legível ao redor da cor de ação do produto.
paletteCloudNormal#E8EDF1 Use superfícies discretas e texto legível ao redor da cor de ação do produto.
paletteInkDark#252A31 Use superfícies discretas e texto legível ao redor da cor de ação do produto.
paletteInkLight#657890 Use superfícies discretas e texto legível ao redor da cor de ação do produto.
paletteInkNormal#4F5E71 Use superfícies discretas e texto legível ao redor da cor de ação do produto.
paletteProductLight#E1F4F3 Use superfícies discretas e texto legível ao redor da cor de ação do produto.
paletteProductNormal#008F7B Use superfícies discretas e texto legível ao redor da cor de ação do produto.
paletteProductDark#007061 Use superfícies discretas e texto legível ao redor da cor de ação do produto.
03

Guia completo do sistema de design Kiwi Orbit

Um guia prático para escolher, aplicar e avaliar este sistema em uma interface real.

DESIGN-kiwi-orbit.md

Orientações completas, um ponto de partida para a implementação e links para o código-fonte.

Baixar o guia

Layout de seleção de viagem do sistema de design Kiwi Orbit

Apresente o trajeto antes dos extras

O resumo do trajeto mostra os códigos dos dois aeroportos, os nomes das cidades e uma duração fictícia antes das opções de bagagem. Assim, o contexto da compra permanece visível enquanto a pessoa compara os extras. O conector tracejado é uma ilustração original de CSS, não um gráfico de rota de uma companhia aérea nem uma promessa sobre um serviço real.

Com base neste guia de OpenDesign

Separe as opções do total

Os viajantes e a bagagem ficam de um lado, enquanto o detalhamento do preço aparece ao lado. O mesmo estado determina os controles selecionados e os valores. Em celulares, o resumo vem depois das opções na ordem do documento, deixando claro quais entradas compõem o total.

Sistema de design Kiwi Orbit: cores do produto e feedback

Use a família de cores do produto para a ação principal

O pacote de tokens fornece uma cor verde para ações do produto, com tons distintos para os estados de foco e ativo. A referência lista os valores exatos para a função do botão, em vez de depender de um verde de marca presumido. Superfícies neutras em tom de nuvem enquadram os extras selecionáveis sem fazer com que todos os painéis disputem a atenção com a ação de revisão.

Mantenha o feedback específico para o resultado

O alerta de sucesso nativo informa que a seleção foi revisada localmente e especifica a quantidade de viajantes e o total. Ele é removido sempre que uma opção é alterada. Assim, uma confirmação verde anterior não continua visível como se validasse um conjunto de extras recém-editado.

Sistema de design Kiwi Orbit: tipografia e hierarquia de preços

Use estilos de texto nativos para as explicações

O Orbit oferece estilos nativos de corpo de texto pequeno, com 13px, e normal, com 15px, além de opções maiores. O exemplo usa os componentes nativos Text e Heading, enquanto os códigos de rota e o total recebem destaque próprio. O navegador usa aqui uma pilha de fontes alternativas documentada; nenhuma fonte da marca Kiwi.com é carregada sem aviso.

Mantenha as unidades junto aos valores

O preço de cada bagagem informa que é por viajante. O detalhamento multiplica cada extra selecionado pela quantidade de viajantes, e o total tem mais destaque visual do que seus componentes. A unidade não deve desaparecer em dispositivos móveis, pois um valor grande e chamativo sem indicar seu escopo pode ser facilmente interpretado de forma errada.

Sistema de design Kiwi Orbit: escalas de raio e espaçamento

Diferencie os controles das superfícies maiores

A escala de raio atual inclui os valores 2, 4, 6, 8, 12 e 16px, além de nenhum e máximo. Os painéis de rota e resumo definidos no exemplo usam cantos de 12px, enquanto os controles nativos mantêm as regras do próprio tema. Aplicar o maior raio a todos os elementos aninhados prejudicaria a hierarquia do formulário.

Mantenha a linha da opção íntegra quando houver quebra de linha

Sistema de design Kiwi Orbit: caixas de seleção e seletores controlados

Use rótulos de componentes e campos de informação

Checkbox recebe seu rótulo visível e as informações complementares por meio de propriedades públicas. Select recebe um rótulo e opções explícitas para selecionar de um a quatro viajantes. Essas composições nativas preservam o comportamento de interação e rotulagem, sem recorrer a uma div clicável que se passe por controle de bagagem.

Modele cada extra de forma independente

Bagagem de mão e bagagem despachada são valores booleanos separados. A aplicação não indica que selecionar uma opção desmarque automaticamente a outra. Esta é uma regra intencionalmente simples para o exemplo; uma companhia aérea real pode oferecer pacotes mutuamente exclusivos ou franquias específicas por passageiro, o que exigiria outro modelo.

Sistema de design Kiwi Orbit: cálculo e revisão da seleção

Calcule o total usando uma única fórmula

O exemplo calcula a quantidade de viajantes multiplicada pela tarifa base mais os extras selecionados por pessoa. Ele não armazena um total editável de forma independente, que poderia divergir das opções exibidas. Todos os preços e franquias são explicitamente fictícios e não correspondem a ofertas atuais da Kiwi.com.

Registre uma captura da revisão

A revisão armazena juntos a quantidade de viajantes, as opções de bagagem e o total. Alterar qualquer controle remove essa captura. Assim, o exemplo demonstra a consistência do estado sem apresentar um clique local como reserva, pagamento, verificação de disponibilidade em tempo real ou cotação final.

Sistema de design Kiwi Orbit: feedback acessível para escolhas

Verifique os rótulos e o recálculo em conjunto

Pessoas que usam teclado ou ponteiro podem selecionar a quantidade de viajantes e ativar ou desativar cada opção de bagagem usando os controles nativos. O resultado da revisão aparece em uma região de status. Não se inventa uma validação para bagagem opcional: deixar os dois extras desmarcados é um estado válido para esta tarifa fictícia.

  1. Selecione dois viajantes e adicione bagagem de mão.
  2. Adicione bagagem despachada e confira os três valores do detalhamento.
  3. Faça a revisão local, altere uma opção e confirme que a mensagem de sucesso anterior desaparece.

Evite consequências ocultas

A página explica o escopo fictício acima do formulário e ao lado do total. A ação é Revisar seleção local, não Comprar ou Reservar. Todas as alterações permanecem na página, e não são solicitados dados pessoais dos passageiros para uma demonstração que não precisa deles.

Sistema de design Kiwi Orbit: provider e estilos compilados

Use a versão estável correspondente

Este exemplo fixa a versão 27.7.0 de components e a versão 11.0.0 das referências de tokens. Ele importa OrbitProvider, o defaultTheme do pacote e o arquivo compilado lib/tailwind.css. Sem essa folha de estilos, os estilos dos componentes baseados em utilitários ficam incompletos, mesmo que a árvore de React seja renderizada.

  • OrbitProvider e defaultTheme do pacote.
  • Arquivo lib/tailwind.css compilado de components 27.7.0.
  • Node.js 22 ou versão posterior para o ambiente de build do pacote.

Deixe explícitos os requisitos de implantação

Sistema de design Kiwi Orbit: exemplos de componentes

main.jsx — exemplo funcional completo

Escolha as opções de bagagem e revise um total de exemplo. O código-fonte abaixo é a entrada completa de React, incluindo todo o estado e a validação.

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 />);

Referência de código

  • Crie um projeto Vite React, mantenha <div id="root"></div> e carregue este arquivo como src/main.jsx.

orbit.css — composição responsiva original

Layout da aplicação organizado em torno dos componentes nativos.

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;
  }
}

Referência de código

  • Salve junto de main.jsx. Estas regras de composição personalizadas são distintas da referência de tokens da biblioteca.
04

Sistema de design Kiwi Orbit: configuração do agente

Ponto de partida para implementação

O exemplo nativo com versões fixadas foi empacotado e verificado localmente no navegador. O exemplo usa apenas o estado local da aplicação.

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

Um prompt para seu projeto

Prompt para agente de IA
Crie um seletor de extras de viagem com componentes nativos do Orbit e estilos compilados. Mantenha consistentes o contexto da rota, os preços por viajante, os extras escolhidos e o total. Identifique claramente os preços fictícios e a revisão local, remova revisões desatualizadas após alterações e não sugira que há recursos de reserva ou pagamento.
05

Sistema de design Kiwi Orbit: fontes e escopo

Guia de aplicação de OpenDesign. A rota, a duração, os preços e as franquias de bagagem são fictícios. Os controles nativos do Orbit funcionam localmente; nenhuma busca de voos, reserva ou pagamento é realizada.