From 25dc5f408a8845e9c8665a724d976a8791a73dbb Mon Sep 17 00:00:00 2001 From: Robin Lopez Date: Fri, 25 Sep 2026 09:41:48 +0200 Subject: [PATCH 1/2] storybook: Fix switch theming and preview layout --- storybook/docs/Overview.mdx | 6 +++--- storybook/preview.tsx | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/storybook/docs/Overview.mdx b/storybook/docs/Overview.mdx index 166e51a..a1bd5cb 100644 --- a/storybook/docs/Overview.mdx +++ b/storybook/docs/Overview.mdx @@ -136,7 +136,7 @@ export const CATEGORIES = [ { name: 'ui-avatar', description: "Personne ou entité en image, initiales ou icône. Le mode se déduit des props, avec un badge de statut posé en haut à droite.", link: '?path=/docs/components-ui-informative-ui-avatar--docs', story: AvatarStories.Default }, { name: 'ui-avatar-group', description: "Pile d'avatars qui se chevauchent. Le débordement « +N » s'écrit comme un avatar de plus.", link: '?path=/docs/components-ui-informative-ui-avatar-group--docs', story: AvatarGroupStories.Default }, { name: 'ui-chip', description: "Entité manipulable : retirable par un vrai bouton, ou sélectionnable en devenant elle-même un bouton à état.", link: '?path=/docs/components-ui-informative-ui-chip--docs', story: ChipStories.Removable }, - { name: 'ui-empty-state', description: "Absence de contenu : un visuel, un titre, une description et des actions pour offrir une suite.", link: '?path=/docs/components-ui-informative-ui-empty-state--docs', story: EmptyStateStories.Default }, + { name: 'ui-empty-state', description: "Absence de contenu : un visuel, un titre, une description et des actions pour offrir une suite.", link: '?path=/docs/components-ui-informative-ui-empty-state--docs', story: EmptyStateStories.Default, previewScale: 0.7 }, { name: 'ui-badge', description: "Compte ou statut. Trois formes selon le contenu : capsule, glyphe unique carré, ou point de notification.", link: '?path=/docs/components-ui-informative-ui-badge--docs', story: BadgeStories.Default }, { name: 'ui-helper', description: "Texte d'aide ou retour contextuel (icône déduite du niveau, région vivante optionnelle).", link: '?path=/docs/components-ui-informative-ui-helper--docs', story: HelperStories.Default }, { name: 'ui-read-only', description: "Valeur étiquetée en lecture seule. Rend une vraie liste de définition dès qu'un libellé est donné.", link: '?path=/docs/components-ui-informative-ui-read-only--docs', story: ReadOnlyStories.Default }, @@ -147,7 +147,7 @@ export const CATEGORIES = [ { name: 'ui-spinner', description: "Chargement indéterminé. Marqueur remplaçable et délai de grâce contre le clignotement.", link: '?path=/docs/components-ui-informative-ui-spinner--docs', story: SpinnerStories.Default }, { name: 'ui-tag', description: "Étiquette informative colorée par level × subLevel, pilule ou rectangle, icône de chaque côté.", link: '?path=/docs/components-ui-informative-ui-tag--docs', story: TagStories.Default }, { name: 'ui-alert', description: "Message en ligne annoncé dès son apparition. Sévérité, icône déduite, fermeture et disparition automatique.", link: '?path=/docs/components-ui-informative-ui-alert--docs', story: AlertStories.Default }, - { name: 'ui-accordion', description: "Sections repliables. L'en-tête entier est un bouton, le corps replié reste monté mais devient inerte.", link: '?path=/docs/components-ui-informative-ui-accordion--docs', story: AccordionStories.Default }, + { name: 'ui-accordion', description: "Sections repliables. L'en-tête entier est un bouton, le corps replié reste monté mais devient inerte.", link: '?path=/docs/components-ui-informative-ui-accordion--docs', story: AccordionStories.Default, previewHeight: 300, previewScale: 0.7 }, { name: 'ui-toast', description: "Notification flottante et empilée. Vit dans le calque supérieur, donc rien ne l'enterre, pas même un dialogue natif.", link: '?path=/docs/components-ui-informative-ui-toast--docs', story: ToastStories.Default }, ], }, @@ -171,7 +171,7 @@ export const CATEGORIES = [ { name: 'ui-tabs', description: "Onglets headless composés : bande à focus glissant, indicateur mesuré, défilement, panneaux paresseux.", link: '?path=/docs/components-ui-navigation-ui-tabs--docs', story: TabsStories.Default, previewHeight: 300 }, { name: 'ui-breadcrumb', description: "Fil d'Ariane. Chaque maillon rend l'élément natif de sa sémantique : ancre, bouton, ou simple texte.", link: '?path=/docs/components-ui-navigation-ui-breadcrumb--docs', story: BreadcrumbStories.Basic }, { name: 'ui-bottom-tab-bar', description: "Navigation basse des appareils tactiles. Réserve l'incrustation système et garde la cible tactile.", link: '?path=/docs/components-ui-navigation-ui-bottom-tab-bar--docs', story: BottomTabBarStories.Basic, previewHeight: 300 }, - { name: 'ui-sidebar', description: "Barre latérale applicative : rail d'icônes repliable dans le flux, ou panneau superposé sur un dialog natif. Menu déclaratif livré avec.", link: '?path=/docs/components-ui-navigation-ui-sidebar--docs', story: SidebarStories.WithMenu }, + { name: 'ui-sidebar', description: "Barre latérale applicative : rail d'icônes repliable dans le flux, ou panneau superposé sur un dialog natif. Menu déclaratif livré avec.", link: '?path=/docs/components-ui-navigation-ui-sidebar--docs', story: SidebarStories.WithMenu, previewHeight: 300, previewScale: 0.5 }, { name: 'ui-stepper', description: "Progression numérotée. La sémantique ARIA suit la disposition : onglets à plat, accordéon en colonne.", link: '?path=/docs/components-ui-navigation-ui-stepper--docs', story: StepperStories.Basic }, ], }, diff --git a/storybook/preview.tsx b/storybook/preview.tsx index 6960f90..d2873c5 100644 --- a/storybook/preview.tsx +++ b/storybook/preview.tsx @@ -1,3 +1,4 @@ +import { useDarkMode } from '@storybook-community/storybook-dark-mode'; import type { Preview } from '@storybook/react-vite'; import { addons } from 'storybook/preview-api'; @@ -62,8 +63,10 @@ const preview: Preview = { decorators: [ withBrand, withRipple, - (Story, context) => { - syncTheme(Boolean(context.globals['darkMode'])); + // L'addon ne pose aucun global : son état vit dans son propre stockage, que + // seul `useDarkMode()` lit. Chaque rendu de story réaligne donc sur lui. + (Story) => { + syncTheme(useDarkMode()); return Story(); }, ], From f97b32c49e6987714fc27b6a3b662ffb6f7f4034 Mon Sep 17 00:00:00 2001 From: Robin Lopez Date: Fri, 25 Sep 2026 14:22:42 +0200 Subject: [PATCH 2/2] storybook: Fix overview previews --- storybook/docs/Overview.mdx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/storybook/docs/Overview.mdx b/storybook/docs/Overview.mdx index a1bd5cb..7f87354 100644 --- a/storybook/docs/Overview.mdx +++ b/storybook/docs/Overview.mdx @@ -6,7 +6,6 @@ import * as ButtonStories from "../../packages/ui-kit-react/src/actions/ui-butto import * as ButtonSplitStories from "../../packages/ui-kit-react/src/actions/ui-button-split/ui-button-split.stories"; import * as SpeedDialStories from "../../packages/ui-kit-react/src/actions/ui-speed-dial/ui-speed-dial.stories"; import * as CheckboxStories from "../../packages/ui-kit-react/src/forms/ui-checkbox/ui-checkbox.stories"; -import * as FieldStories from "../../packages/ui-kit-react/src/forms/ui-field/ui-field.stories"; import * as InputStories from "../../packages/ui-kit-react/src/forms/ui-input/ui-input.stories"; import * as InputDateStories from "../../packages/ui-kit-react/src/forms/ui-input-date/ui-input-date.stories"; import * as InputMaskStories from "../../packages/ui-kit-react/src/forms/ui-input-mask/ui-input-mask.stories"; @@ -101,7 +100,6 @@ export const CATEGORIES = [ title: 'Forms', anchor: 'forms', components: [ - { name: 'ui-field', description: "Coquille partagée des champs en boîte : libellé, boîte bordée, message. Purement visuelle, le contrôle est projeté.", link: '?path=/docs/components-ui-forms-ui-field--docs', story: FieldStories.WithMessage }, { name: 'ui-input', description: 'Champ texte composé (contrôlé ou non, icônes, zone d\'action, unité, libellé flottant, validation).', link: '?path=/docs/components-ui-forms-ui-input--docs', story: InputStories.WithHelper }, { name: 'ui-label', description: 'Libellé de champ (marqueur requis, tailles, couleur pilotable par le parent).', link: '?path=/docs/components-ui-forms-ui-label--docs', story: LabelStories.Required }, { name: 'ui-input-number', description: "Champ numérique (saisie permissive, formatage riche à la sortie, min/max/step, pavé d'incrément, role spinbutton).", link: '?path=/docs/components-ui-forms-ui-input-number--docs', story: InputNumberStories.MinMax }, @@ -114,7 +112,7 @@ export const CATEGORIES = [ { name: 'ui-slider', description: "Curseur simple ou de plage. Le pointeur est capturé, donc le glissement continue hors de la piste.", link: '?path=/docs/components-ui-forms-ui-slider--docs', story: SliderStories.Default }, { name: 'ui-knob', description: "Cadran circulaire. Un arc SVG de 300° en viewBox, donc le trait suit le diamètre rendu.", link: '?path=/docs/components-ui-forms-ui-knob--docs', story: KnobStories.Basic }, { name: 'ui-swatch-picker', description: "Grille de couleurs, en ligne ou en popup. Chaque pastille pointe un jeton, donc la marque la repeint.", link: '?path=/docs/components-ui-forms-ui-swatch-picker--docs', story: SwatchStories.Small }, - { name: 'ui-editor', description: "Texte riche sur un contenteditable, sans moteur tiers. Police, taille et couleurs en classes adossées aux jetons.", link: '?path=/docs/components-ui-forms-ui-editor--docs', story: EditorStories.WithValue }, + { name: 'ui-editor', description: "Texte riche sur un contenteditable, sans moteur tiers. Police, taille et couleurs en classes adossées aux jetons.", link: '?path=/docs/components-ui-forms-ui-editor--docs', story: EditorStories.WithValue, previewHeight: 300, previewScale: 0.5 }, { name: 'ui-file-upload', description: "Téléversement en champ compact ou en zone de dépôt, sur un input natif. Validation, progression, envoi intégré ou délégué.", link: '?path=/docs/components-ui-forms-ui-file-upload--docs', story: FileUploadStories.Basic }, { name: 'ui-input-otp', description: "Code à usage unique, une case par caractère. Un seul arrêt de tabulation, et le collage se répartit.", link: '?path=/docs/components-ui-forms-ui-input-otp--docs', story: InputOtpStories.Basic }, { name: 'ui-toggle-block', description: "Bloc sélectionnable. Un label étiré rend toute la surface activante, sans gestionnaire de clic.", link: '?path=/docs/components-ui-forms-ui-toggle-block--docs', story: ToggleBlockStories.Checked }, @@ -143,7 +141,7 @@ export const CATEGORIES = [ { name: 'ui-tooltip', description: "Bulle d'aide au survol et au focus. Rejetable par Échap, survolable, persistante : WCAG 1.4.13.", link: '?path=/docs/components-ui-informative-ui-tooltip--docs', story: TooltipStories.Default }, { name: 'ui-separator', description: "Filet role=separator entre deux contenus, titrable, horizontal ou vertical.", link: '?path=/docs/components-ui-informative-ui-separator--docs', story: SeparatorStories.Labelled }, { name: 'ui-progress-bar', description: "Avancement d'un traitement : valeur suivie, boucle indéterminée, ou étapes discrètes.", link: '?path=/docs/components-ui-informative-ui-progress-bar--docs', story: ProgressBarStories.Default }, - { name: 'ui-skeleton', description: "Bloc affiché à la place d'un contenu en cours de chargement (3 formes, reflet ou clignotement).", link: '?path=/docs/components-ui-informative-ui-skeleton--docs', story: SkeletonStories.Default }, + { name: 'ui-skeleton', description: "Bloc affiché à la place d'un contenu en cours de chargement (3 formes, reflet ou clignotement).", link: '?path=/docs/components-ui-informative-ui-skeleton--docs', story: SkeletonStories.CardPlaceholder }, { name: 'ui-spinner', description: "Chargement indéterminé. Marqueur remplaçable et délai de grâce contre le clignotement.", link: '?path=/docs/components-ui-informative-ui-spinner--docs', story: SpinnerStories.Default }, { name: 'ui-tag', description: "Étiquette informative colorée par level × subLevel, pilule ou rectangle, icône de chaque côté.", link: '?path=/docs/components-ui-informative-ui-tag--docs', story: TagStories.Default }, { name: 'ui-alert', description: "Message en ligne annoncé dès son apparition. Sévérité, icône déduite, fermeture et disparition automatique.", link: '?path=/docs/components-ui-informative-ui-alert--docs', story: AlertStories.Default },