Voyage et tourisme · Nouvelle ressource

Système de design Kiwi Orbit.

Un guide Orbit axé sur le voyage, avec les couleurs et espacements réels du produit, des choix de bagages natifs, un récapitulatif de prix cohérent et un parcours complet de vérification en local.

Guide OpenDesign8 chapitres38 entrées de référenceGuide de l’application d’origine
01

Aperçu de l’interface du système de design Kiwi Orbit

Modifiez le nombre de voyageurs et les options, consultez le détail et effacez un récapitulatif obsolète en changeant une option.

Choisissez les bagages et consultez un exemple de totalOuvrir l’exemple complet
Composants Native Orbit React 27.7.0 avec defaultTheme et Tailwind CSS compilé ; référence des jetons 11.0.0. · Référence de mise en œuvre
02

Référence de conception du système de design Kiwi Orbit

Composants Native Orbit React 27.7.0 avec defaultTheme et Tailwind CSS compilé ; référence des jetons 11.0.0.

Couleurs d’action du produit

Source
Nom / règleValeur / configurationUtilisation
buttonPrimaryBackground#008F7B Référence des états de l’action principale. Distinguez les rôles de survol, d’activation et de focus.
buttonPrimaryBackgroundHover#007565 Référence des états de l’action principale. Distinguez les rôles de survol, d’activation et de focus.
buttonPrimaryBackgroundActive#006153 Référence des états de l’action principale. Distinguez les rôles de survol, d’activation et de focus.
buttonPrimaryForeground#FFFFFF Référence des états de l’action principale. Distinguez les rôles de survol, d’activation et de focus.
buttonPrimaryForegroundHover#FFFFFF Référence des états de l’action principale. Distinguez les rôles de survol, d’activation et de focus.
buttonPrimaryForegroundActive#FFFFFF Référence des états de l’action principale. Distinguez les rôles de survol, d’activation et de focus.
buttonPrimaryBorderColorFocusrgba(0, 143, 123, 0.5)Référence des états de l’action principale. Distinguez les rôles de survol, d’activation et de focus.

Espacement des composants

Source
Nom / règleValeur / configurationUtilisation
space502pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space1004pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space1506pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space2008pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space30012pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space40016pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space50020pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space60024pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space80032pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space100040pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.
space120048pxValeurs d’espacement réelles en pixels, issues du package de jetons publié.

Rayons des angles

Source
Nom / règleValeur / configurationUtilisation
borderRadius502pxDifférents rayons sont prévus pour les contrôles et les grandes surfaces de l’interface de voyage.
borderRadius1004pxDifférents rayons sont prévus pour les contrôles et les grandes surfaces de l’interface de voyage.
borderRadius1506pxDifférents rayons sont prévus pour les contrôles et les grandes surfaces de l’interface de voyage.
borderRadius2008pxDifférents rayons sont prévus pour les contrôles et les grandes surfaces de l’interface de voyage.
borderRadius30012pxDifférents rayons sont prévus pour les contrôles et les grandes surfaces de l’interface de voyage.
borderRadius40016pxDifférents rayons sont prévus pour les contrôles et les grandes surfaces de l’interface de voyage.
borderRadiusNone0Différents rayons sont prévus pour les contrôles et les grandes surfaces de l’interface de voyage.
borderRadiusFull9999pxDifférents rayons sont prévus pour les contrôles et les grandes surfaces de l’interface de voyage.

Typographie du corps de texte

Source
Nom / règleValeur / configurationUtilisation
fontSizeTextSmall13pxRôles de texte courant publiés ; les titres personnalisés de la page sont composés par l’application.
fontSizeTextNormal15pxRôles de texte courant publiés ; les titres personnalisés de la page sont composés par l’application.
fontSizeTextLarge16pxRôles de texte courant publiés ; les titres personnalisés de la page sont composés par l’application.
fontSizeTextExtraLarge18pxRôles de texte courant publiés ; les titres personnalisés de la page sont composés par l’application.

Surfaces du produit et surfaces neutres

Source
Nom / règleValeur / configurationUtilisation
paletteCloudLight#F5F7F9 Privilégiez des surfaces sobres et un texte lisible autour de la couleur d’action du produit.
paletteCloudNormal#E8EDF1 Privilégiez des surfaces sobres et un texte lisible autour de la couleur d’action du produit.
paletteInkDark#252A31 Privilégiez des surfaces sobres et un texte lisible autour de la couleur d’action du produit.
paletteInkLight#657890 Privilégiez des surfaces sobres et un texte lisible autour de la couleur d’action du produit.
paletteInkNormal#4F5E71 Privilégiez des surfaces sobres et un texte lisible autour de la couleur d’action du produit.
paletteProductLight#E1F4F3 Privilégiez des surfaces sobres et un texte lisible autour de la couleur d’action du produit.
paletteProductNormal#008F7B Privilégiez des surfaces sobres et un texte lisible autour de la couleur d’action du produit.
paletteProductDark#007061 Privilégiez des surfaces sobres et un texte lisible autour de la couleur d’action du produit.
03

Guide complet du système de design Kiwi Orbit

Un guide pratique pour choisir, appliquer et évaluer ce système dans une interface réelle.

DESIGN-kiwi-orbit.md

Des conseils complets, un point de départ pour la mise en œuvre et des liens vers les sources.

Télécharger le guide

Mise en page de sélection de voyage du système de design Kiwi Orbit

Présentez l’itinéraire avant les options

Le résumé de l’itinéraire affiche les codes des deux aéroports, le nom des villes et une durée fictive avant les options de bagages. Le contexte d’achat reste ainsi visible pendant que l’utilisateur compare les options. Le connecteur en pointillés est une illustration originale de CSS, et non un tracé d’itinéraire d’un transporteur ni la promesse d’un service réel.

Extrait de ce guide OpenDesign

Séparez les options du total

Les voyageurs et les bagages sont regroupés d’un côté, tandis que le détail du prix figure à côté. Un même état détermine les contrôles sélectionnés et les montants. Sur téléphone, le récapitulatif suit les options dans l’ordre du document, ce qui permet de voir clairement quelles saisies déterminent le total.

Couleurs du produit et retours d’information du système de design Kiwi Orbit

Utilisez la gamme du produit pour l’action principale

Le package de jetons fournit une couleur d’action verte pour le produit, avec des nuances distinctes au survol et à l’activation. La référence indique les valeurs exactes du rôle de bouton au lieu de s’appuyer sur un vert de marque approximatif. Des surfaces neutres couleur nuage encadrent les options sélectionnables sans rivaliser avec l’action de récapitulatif.

Adaptez le retour d’information au résultat

L’alerte de réussite native indique « Sélection récapitulée localement » et précise le nombre de voyageurs et le total. Elle est effacée dès qu’une option change. Une confirmation verte précédente ne peut donc pas rester affichée comme si elle validait un nouvel ensemble d’options.

Typographie et hiérarchie des prix du système de design Kiwi Orbit

Utilisez les styles de texte natifs pour les explications

Orbit propose des styles natifs de texte courant en 13 px (petit) et 15 px (normal), ainsi que des tailles supérieures. L’exemple utilise les composants Text et Heading natifs, tandis que les codes d’itinéraire et le total sont mis en valeur sur mesure. Le navigateur utilise ici une pile de polices de remplacement documentée ; aucune police de marque Kiwi.com n’est récupérée en arrière-plan.

Indiquez les unités à côté des montants

Le prix de chaque bagage est indiqué par voyageur. Le détail multiplie le prix de chaque option sélectionnée par le nombre de voyageurs, et le total est mis davantage en évidence que les lignes qui le composent. L’unité ne doit pas disparaître sur mobile : un montant élevé et attrayant, sans indication de sa portée, peut facilement être mal interprété.

Échelles de rayons et d’espacement du système de design Kiwi Orbit

Distinguez les contrôles des grandes surfaces

L’échelle de rayons actuelle comprend des valeurs de 2, 4, 6, 8, 12 et 16 px, ainsi que les options aucun et complet. Les panneaux personnalisés de l’itinéraire et du récapitulatif ont des coins de 12 px, tandis que les contrôles natifs conservent les règles de leur thème. Appliquer le rayon maximal à chaque élément imbriqué ferait perdre sa hiérarchie au formulaire.

Préservez l’intégrité de la ligne d’option lorsqu’elle passe à la ligne

Case à cocher et liste de sélection contrôlées du système de design Kiwi Orbit

Utilisez les libellés des composants et les champs d’information

La case à cocher reçoit son libellé visible et ses informations complémentaires par le biais de props publiques. Le composant Select reçoit un libellé et des options explicites pour choisir de un à quatre voyageurs. Ces compositions natives préservent leur comportement d’interaction et d’étiquetage, sans remplacer un contrôle de bagage par un div cliquable.

Gérez chaque option séparément

Les bagages en cabine et les bagages en soute sont deux valeurs booléennes distinctes. L’application ne laisse pas entendre que la sélection de l’un désélectionne automatiquement l’autre. Cette règle est volontairement simple pour l’exemple ; une vraie compagnie aérienne peut proposer des forfaits mutuellement exclusifs ou des franchises propres à chaque passager, qui nécessiteraient un autre modèle.

Calcul et récapitulatif de la sélection du système de design Kiwi Orbit

Calculez le total à partir d’une seule formule

L’exemple calcule le nombre de voyageurs multiplié par le tarif de base augmenté des options sélectionnées par personne. Il ne stocke pas un total modifiable séparément, qui pourrait ne plus correspondre aux options visibles. Tous les prix et franchises sont explicitement fictifs et ne sont pas des offres Kiwi.com en vigueur.

Enregistrez un instantané du récapitulatif

Le récapitulatif enregistre ensemble le nombre de voyageurs, les options de bagages et le total. Toute modification d’un contrôle efface cet instantané. L’exemple montre ainsi la cohérence de l’état, sans présenter un clic local comme une réservation, un paiement, une vérification de disponibilité en temps réel ou un devis définitif.

Retours d’information accessibles sur le choix — système de design Kiwi Orbit

Vérifiez ensemble les libellés et le recalcul

Au clavier ou au pointeur, l’utilisateur peut choisir le nombre de voyageurs et activer l’une ou l’autre des options de bagages à l’aide des contrôles natifs. Le résultat du récapitulatif apparaît dans une région de statut. Aucune validation artificielle n’est ajoutée pour les bagages facultatifs : ne sélectionner aucune option est un état valide pour ce tarif fictif.

  1. Choisissez deux voyageurs et ajoutez un bagage en cabine.
  2. Ajoutez un bagage en soute et vérifiez les trois montants du détail.
  3. Faites le récapitulatif localement, modifiez une option et vérifiez que le message de réussite précédent disparaît.

Évitez les conséquences cachées

La page explique la nature fictive de l’offre au-dessus du formulaire et à côté du total. L’action proposée est d’examiner la sélection locale, et non d’acheter ou de réserver. Toutes les modifications restent sur la page, et aucune information personnelle sur les passagers n’est demandée puisque la démonstration n’en a pas besoin.

Fournisseur du système de design Kiwi Orbit et styles compilés

Utilisez la version stable correspondante

Cet exemple fixe les composants React à la version 27.7.0 et les références de jetons à la version 11.0.0. Il importe OrbitProvider, le paquet defaultTheme et la feuille de style compilée lib/tailwind.css. Sans cette feuille de style, le rendu de l’arborescence React resterait incomplet, même si le style des composants repose sur des classes utilitaires.

  • OrbitProvider et le paquet defaultTheme.
  • Fichier compilé lib/tailwind.css des composants en version 27.7.0.
  • Node.js 22 ou une version ultérieure pour l’environnement de compilation du package.

Précisez les exigences de déploiement

Exemples de composants du système de design Kiwi Orbit

main.jsx — exemple complet fonctionnel

Choisissez des bagages et consultez un exemple de total. Le code source ci-dessous correspond à l’entrée React complète, avec tous les états et la validation.

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

Référence du code

  • Créez un projet Vite React, conservez <div id="root"></div> et chargez ce fichier comme src/main.jsx.

orbit.css — composition adaptative d’origine

Mise en page de l’application construite autour des composants natifs.

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

Référence du code

  • Enregistrez ce fichier à côté de main.jsx. Ces règles de composition personnalisées se distinguent de la référence des jetons de la bibliothèque.
04

Configuration de l’agent du système de design Kiwi Orbit

Point de départ de l’implémentation

L’exemple natif épinglé a été assemblé et vérifié localement dans un navigateur. Cet exemple utilise uniquement l’état local de l’application.

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

Un prompt pour votre projet

Prompt pour l’agent IA
Créez un sélecteur d’options de voyage avec les composants natifs Orbit et les styles compilés. Assurez la cohérence du contexte de l’itinéraire, des prix par voyageur, des options choisies et du total. Indiquez clairement que les prix sont fictifs et que la vérification se fait localement ; effacez toute vérification devenue obsolète lors d’une modification et ne laissez pas entendre qu’une réservation ou un paiement est possible.
05

Sources et périmètre du système de design Kiwi Orbit

Guide de l’application OpenDesign. L’itinéraire, la durée, les prix et les franchises de bagages sont fictifs. Les contrôles natifs Orbit fonctionnent localement ; aucune recherche de vol, réservation ou opération de paiement n’est effectuée.