Tous les articles
Design systèmeTechnique

Un seul kit d’interface, six plateformes

Par Maxime Scharwath2 min de lecture

L’affiche d’un film est identique sur un Apple TV, sur une TV Samsung et dans votre navigateur. C’est un seul composant, pas trois qu’on garde synchronisés à la main.

Écrit une fois, pour React Native

Le kit @kromatv/ui est écrit pour React Native. Sur Apple TV, Android TV, iPhone et Android, il s’affiche en natif. Sur le web, sur les TV Tizen et webOS, dans l’app desktop Tauri et dans le client web, il passe par react-native-web. Un fichier, deux moteurs de rendu.

Les couleurs, la typo, les ombres et le focus sont définis une seule fois eux aussi, en TypeScript. Ce sont eux qui génèrent les variables CSS que lisent les cibles web :

import { colors, type } from '@kromatv/ui/tokens';
 
colors.accent; // #F4B642, le seul ambre du produit
colors.bg;     // #0A0A0C, le gris charbon du fond
type.hero;     // 66px / 700, Bricolage Grotesque

Ce site ne définit aucune couleur à lui. Il importe le thème Tailwind v4 du kit, donc il s’affiche dans le même charbon et le même ambre que l’application.

Le focus, la seule vraie différence

Entre une TV et un navigateur, ce qui change c’est la navigation, pas l’apparence. Une télécommande n’a pas de curseur.

En natif, c’est l’OS qui gère les déplacements directionnels : UIFocusEngine sur tvOS, la résolution nextFocus sur Android TV. Le web n’a aucun moteur de focus, donc le déplacement est calculé géométriquement. L’élément focusable le plus proche dans la direction pressée gagne, et l’écart latéral est pénalisé pour qu’un voisin aligné passe devant un voisin décalé.

Toute cette différence tient dans quelques fichiers .web.ts. Rien d’autre dans le kit ne sait qu’elle existe.

Ce que ça coûte, et ce que ça rapporte

Écrire pour React Native coûte une étape de résolution dans chaque bundler, et un deuxième moteur de rendu à tester. En échange, changer l’affiche d’un film est un seul commit, et tous les écrans de KROMA l’ont le jour même. Six apps, un composant.