Skip to content

Contribution ​

Ce document porte les règles de fond : ce qu'un composant doit garantir, où va chaque chose, et pourquoi. La marche à suivre pratique — installer, lancer les vérifications, ouvrir une pull request — vit dans le CONTRIBUTING.md à la racine du dépôt, là où GitHub la propose au moment de contribuer.

Les deux ne se recopient pas : celui-ci dit quoi respecter, l'autre comment s'y prendre.

Signalements ​

.github/ISSUE_TEMPLATE/ porte deux gabarits, et ils demandent chacun ce qui manque le plus souvent :

  • Anomalie — par quel canal le code est arrivé, et la sortie de sia-ui doctor. Un composant copié vit dans le dépôt de qui l'a installé : sans savoir s'il a été retouché, on cherche un défaut qui n'est pas le nôtre. sia-ui diff répond à cette question en une commande.
  • Composant ou variante — où le besoin s'est déjà présenté, et ce qui différait d'une fois à l'autre. SIA UI n'ajoute pas une entrée parce qu'elle existe ailleurs, mais parce qu'un besoin se répète; et ce qui diffère devient une prop, ou ne doit surtout pas être uniformisé.

Le gabarit de pull request reprend les sept vérifications de la CI, et ajoute celles qui ne sont pas mécanisables : la documentation dans le même changement, et le CHANGELOG du registre quand une entrée monte de version.

Documentation obligatoire ​

Toute évolution structurante doit mettre à jour la documentation dans le même changement. Si aucun document existant ne couvre correctement le sujet, un nouveau fichier Markdown doit être créé dans docs/ puis ajouté à l'index.

Sont notamment concernées : les nouveaux packages, composants majeurs, patterns, commandes CLI, dépendances structurantes, API publiques et conventions internes.

Un diagramme Mermaid est obligatoire lorsqu'une évolution modifie un flux, les dépendances entre packages ou l'organisation du système.

Ajouter un composant ​

Critères obligatoires ​

  • API publique typée et concise.
  • Comportement clavier documenté.
  • Labels et relations ARIA corrects.
  • États loading, disabled, error ou empty lorsque pertinents.
  • Design basé sur les tokens sémantiques.
  • Aucun nom d'entreprise, endpoint ou modèle métier.
  • Dépendances du registre déclarées explicitement.
  • Aucun écrasement silencieux d'un fichier utilisateur.
  • Documentation Markdown créée ou mise à jour dans le même changement.
  • Un contrôle natif masqué derrière un visuel personnalisé porte sia-visually-hidden, jamais un opacity:0 maison : un contrôle seulement transparent reste peint par le navigateur, et son propre dessin clignote sous le nôtre au clic.

Un composant composé laisse passer les props de ce qu'il assemble ​

CrudPage rend un PageHeader, un DataTable, une Pagination ; Form rend un Field par champ ; PhoneInput rend un Select. Un projet qui voulait régler l'un d'eux — une icône à l'état vide, un Select cherchable, un niveau de titre — devait recopier le composant, et perdait la mise à jour suivante. La règle :

Pour chaque sous-composant rendu, l'interface <Nom>Props expose une prop typée par les props de ce sous-composant, transmise telle quelle.

ÉlémentConvention
NomxxxProps, du nom du sous-composant (paginationProps, emptyStateProps) ; un nom de rôle quand il sert deux fois (keyInputProps, valueInputProps)
TypePartial<Omit<XxxProps, <clés pilotées>>> : le parent garde la valeur, les gestionnaires et l'ouverture qu'il calcule lui-même
Ordre au rendudéfauts du parent, puis {...xxxProps}, puis les props pilotées
classNamefusionnée : cn("classe-du-parent", xxxProps?.className)
Cas Fieldun seul controlProps, typé par l'union des props de ses contrôles
tsx
<CrudPage
  resource={factures}
  paginationProps={{ jumpTo: true }}
  table={{ emptyStateProps: { icon: <FolderIcon /> } }}
/>
<Field type="select" options={pays} controlProps={{ searchable: true }} />

pnpm check:slot-props, lancé par la CI, le vérifie : tout composant voisin rendu en JSX doit être cité, par ses props, dans l'interface du composant. Une exception s'écrit dans scripts/check-slot-props.mjs, avec sa raison.

Choisir le bon emplacement ​

SituationEmplacement
Valeur visuelle, vocabulaire de ton ou de taillepackages/tokens
Fonction sans dépendancepackages/utils
Appel réseau, greffon, service CRUDpackages/api
Calcul ou machine à états partagée avec le natifpackages/headless
Mécanisme React lié au DOMpackages/react
Composant webpackages/react-web/src/components
Storyapps/docs/src/stories
Explication structurelledocs

Vérification avant validation ​

bash
pnpm typecheck
pnpm test
pnpm build

Une nouvelle entrée doit également être installée dans un dossier temporaire avec la CLI afin de vérifier les chemins et les dépendances transitives.

Où écrire un composant web ​

Dans packages/react-web/src/components/<Nom>/, et nulle part ailleurs. Il n'y a plus de gabarits : le registre sert le fichier source lui-même, copié octet pour octet par la CLI.

Deux contraintes viennent de là :

  • N'importez rien hors de votre dossier, à part @sia-ui/* et un autre composant par ../<Nom>. La CLI ne copie que components/<Nom>/; un import vers ../../hooks arrive cassé chez l'utilisateur. C'est ce qui a rendu l'entrée drawer ininstallable pendant des semaines.
  • Déclarez l'entrée dans packages/registry/registry.json, avec ses dependencies et ses registryDependencies — la CLI s'en sert pour tirer ce qui manque et annoncer ce qu'il faut installer.

Voir Source unique des composants.

Où écrire quoi ​

Le dépôt a un ordre de dépendance : tokens → core → react → react-web. Une chose s'écrit au niveau le plus bas où elle a du sens, et une seule fois.

Ce que tu écrisOù
Une valeur de thème, une échelle@sia-ui/tokens
Le vocabulaire partagé web/mobile — ton, taille, variante@sia-ui/tokens
Un helper pur, sans React@sia-ui/utils
Un hook de runtime, un provider, un portail@sia-ui/react
Un composant DOM@sia-ui/react-web

Avant d'ajouter un helper ou un hook, vérifier qu'il n'existe pas déjà plus bas. Un composant ne réimplémente jamais ce qu'une couche inférieure expose.

Publié sous licence MIT.