Skip to content

Preview et Storybook ​

Objectif ​

Deux surfaces complémentaires permettent de tester SIA UI au fur et à mesure, sans maintenir plusieurs copies des composants.

Les deux applications importent @sia-ui/react-web, aliasé vers sa source. Une modification d'un composant est donc visible dans les deux outils sans build préalable et sans recopier son implémentation.

Sur Windows avec pnpm, la configuration Vite et Storybook force aussi la résolution de react, react/jsx-runtime et react/jsx-dev-runtime pour éviter les erreurs de pré-bundling liées aux chemins internes de .pnpm. En développement, @sia-ui/react pointe aussi vers packages/react/src plutôt que vers dist, afin que la preview et Storybook travaillent sur la source réelle sans dépendre d'un build préalable du package React.

Preview Vite ​

bash
pnpm preview

La preview s'ouvre sur http://127.0.0.1:6006 et permet de naviguer dans le catalogue, changer le thème, personnaliser la couleur principale et simuler les largeurs desktop, tablette et mobile.

La preview utilise elle-même les composants qu'elle présente. Sa structure est un AppShell; son menu est le Sidebar de ce shell; les sélecteurs de largeur, de mode de couleur, de couleur principale et de rayon utilisent ToggleGroup et Field. Une régression du rail, des sous-menus, du tiroir mobile ou du theming devient donc visible dès l'ouverture de la démonstration.

La marque et le pied de navigation utilisent AppShellBrand et AppShellRailItem. Leur texte disparaît automatiquement dans le rail : la preview ne contient aucun CSS particulier pour reproduire ce comportement.

Le fond du ToggleGroup conserve un contraste léger avec la page en thème clair comme en thème sombre. L'option active reste posée sur la surface surélevée, ce qui permet de distinguer le groupe sans dépendre uniquement de son ombre.

Sous le seuil où la colonne de personnalisation disparaît, un IconButton dans le header ouvre le même ThemePanel dans un Drawer venant de la droite. Les réglages de couleur et de rayon restent ainsi accessibles sur tablette et mobile sans maintenir une seconde implémentation.

La liste sections de apps/docs/src/App.tsx reste la source de vérité du contenu et du menu. Toutes les entrées de composant apparaissent sous Composants. Une entrée dont le type vaut Nouveau reçoit un badge New; elle ne doit pas être déplacée dans un menu séparé. Ce badge utilise le teal de l'identité SIA UI, indépendamment de la couleur principale personnalisée, afin de rester un repère stable en modes clair, sombre et rail réduit.

Storybook ​

bash
pnpm storybook

Storybook s'ouvre sur http://127.0.0.1:6007 et fournit les contrôles de props, la documentation automatique, le changement global de thème et l'audit d'accessibilité avec @storybook/addon-a11y.

La barre d'outils porte deux réglages globaux, appliqués à chaque story par le SiaProvider du décorateur : le mode (clair, sombre) et la langue (français, anglais). Une story se lit ainsi dans les quatre combinaisons, et l'URL les garde : &globals=colorMode:dark;langue:en.

Builds statiques ​

bash
pnpm --filter @sia-ui/docs build
pnpm build:storybook

Le premier produit apps/docs/dist. Le second produit apps/docs/storybook-static.

Mise en ligne ​

Ce dépôt est privé, et GitHub Pages ne sert pas un dépôt privé sur les offres gratuites. Le site est donc construit ici et poussé dans un dépôt public séparé, BeatJo/sia-ui-site, qui ne contient que le résultat : du HTML, du CSS et du JavaScript. Aucune source, aucun historique, aucun document brut — le code reste entièrement privé.

Trois surfaces, trois rôles, et aucune ne redit ce que dit une autre :

AdresseQuoiRépond à
/la documentationpourquoi c'est fait ainsi
/storybook/le catalogueà quoi ressemble ce composant, quelles props
/preview/la démonstrationà quoi ça ressemble en situation
/r/v1/le registrece que sia-ui add --registry installe

La base n'est pas dans le code ​

GitHub Pages sert un dépôt de projet dans un sous-dossier (https://beatjo.github.io/sia-ui-site/); Netlify, Cloudflare et Vercel servent à la racine. Une seule variable décide, et les trois surfaces la suivent :

bash
pnpm build:pages                          # base /, pour servir en local
SIA_SITE_BASE=sia-ui-site pnpm build:pages # base /sia-ui-site/
npx serve .pages

Sans ce partage, chaque surface chercherait ses fichiers un cran trop haut ou trop bas — et rien ne le signalerait avant la mise en ligne. Le nom s'écrit sans barre oblique initiale : Git Bash sous Windows transformerait /sia-ui-site/ en /C:/Program Files/Git/sia-ui-site/. Le script refuse une valeur de cette forme plutôt que de construire un site cassé.

Les paquets sont construits avant les surfaces ​

build:pages lance chaque surface par pnpm --filter, qui ne construit que le paquet nommé — pas ce dont il dépend. Sur une machine de développement, les dist traînent d'une exécution précédente et rien ne se voit. Sur un checkout vierge, le tsc --noEmit de la démonstration ne trouve pas les déclarations de @sia-ui/registry :

src/App.tsx(3,26): error TS2307: Cannot find module '@sia-ui/registry'

Le script commence donc par pnpm turbo run build --filter=./packages/* : Turbo connaît l'ordre des dépendances, et c'est le seul endroit où il est appelé. Les surfaces gardent leur pnpm --filter, parce que leur sortie dépend de SIA_SITE_BASE — une variable que le cache de Turbo ne prend pas en compte, et qui servirait donc un site construit pour la mauvaise base.

C'est une panne qui ne se voit qu'en CI, et seulement à la publication : la validation ne construit pas la démonstration. Le symptôme est un workflow Pages rouge alors que tout passe en local.

Mettre en place la publication ​

Trois gestes, une seule fois :

  1. Créer le dépôt public BeatJo/sia-ui-site, vide.
  2. Créer un jeton d'accès personnel à portée fine, avec la seule permission Contents : Read and write sur ce dépôt, et l'enregistrer ici en secret d'Actions sous le nom SITE_REPO_TOKEN.
  3. Dans sia-ui-site → Settings → Pages, choisir Deploy from a branch, branche main, dossier / (root).

Le workflow pousse en force : l'historique du site n'a aucune valeur, il se reconstruit à chaque fois. Il dépose aussi un .nojekyll, sans quoi Pages ignorerait les dossiers de Storybook commençant par un souligné.

Fichiers GitHub du dépôt public ​

Le dépôt public ne se modifie pas à la main. Les fichiers qui ne sont pas des artefacts de build — README.md, CONTRIBUTING.md et les gabarits d'issues — vivent dans public-repo/ ici, puis sont copiés dans .pages/ par scripts/synchroniser-depot-public.mjs.

Ajouter un gabarit public se fait donc dans public-repo/.github/ISSUE_TEMPLATE/. La publication suivante le pousse automatiquement vers BeatJo/sia-ui-site.

Changer de dépôt public se fait en deux lignes, côte à côte en tête de pages.yml : DEPOT_PUBLIC et SIA_SITE_BASE. Les changer séparément casserait tous les liens d'un coup.

La CI de validation construit Storybook sur chaque pull request : c'est le seul moyen de voir qu'une story casse avant la fusion. Le workflow de publication, lui, ne tourne que sur main.

Le site de documentation ​

docs/ est le site : VitePress vit dans docs/.vitepress/, à côté des fichiers qu'il publie. Aucun d'eux n'a été retouché — pas de front-matter, pas de syntaxe propre à un générateur. Ils restent lisibles tels quels sur GitHub, et changer un jour de générateur ne demandera pas de réécrire la documentation.

Trois points méritent d'être connus avant de toucher à la configuration.

Le sommaire ne se déclare pas deux fois. La barre latérale est construite en lisant la liste numérotée de README.md — voir .vitepress/sidebar.ts. Un document ajouté à l'index apparaît sur le site sans autre geste, et il ne peut pas exister deux ordres de lecture qui divergent.

VitePress compile chaque page comme un composant Vue, donc {{ … }} y devient une interpolation. Les blocs de code sont protégés d'office, pas les code spans — et nos pages sont pleines de props React comme controlProps={{ range: true }}. Le code inline est donc passé en v-pre, et lui seul : déplacer les délimiteurs de Vue aurait aussi cassé le thème, dont la barre latérale affichait alors {{ site.title }}.

Les diagrammes gardent leur taille. Mermaid les comprime par défaut dans la largeur de la colonne : un enchaînement de neuf étapes, large de 2301 pixels, arrivait à vingt-cinq pixels de haut. Avec useMaxWidth: false et un conteneur défilant (theme/custom.css), les quarante-cinq diagrammes restent lisibles.

Où vivent les stories ​

Dans apps/docs/src/stories/, et nulle part ailleurs.

Neuf stories vivaient dans packages/react-web/src/components/, sous un préfixe « Package · react-web » — un reliquat de l'époque où ce paquet était une implémentation parallèle qu'on validait contre les gabarits du registre. Storybook affichait donc chaque composant deux fois.

Pire : le tsconfig de @sia-ui/react-web excluait **/*.stories.tsx, et Storybook ne typecheck pas. Ces fichiers n'étaient vérifiés par rien, et ils ont dérivé sans bruit — un Badge documenté avec closable et variant="dot", un Divider avec thickness et labelPosition, un Label avec des tons secondary et tertiary. Aucune de ces props n'a jamais existé. Storybook les affichait comme des contrôles qui ne faisaient rien.

Les neuf ont été retirées, ce qui manquait a été rapatrié, et l'exclusion du tsconfig est levée : une story écrite dans le paquet serait désormais typecheckée. La CLI garde son filtre — une story n'a rien à faire chez qui installe un composant.

Règle anti-duplication ​

Le code d'un composant ne doit jamais être recopié dans la preview ou dans une story. Les exemples importent toujours @sia-ui/react-web. Seuls les scénarios d'utilisation et les données de démonstration vivent dans apps/docs.

Publié sous licence MIT.