veza/docs/FRONTEND_DEEP_DIVE_AUDIT.md
senke c2d7d32f3d docs(audit): add UserProfilePage refactor entry to FRONTEND_DEEP_DIVE_AUDIT
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-06 13:11:09 +01:00

48 KiB
Raw Blame History

Audit Deep Dive — Frontend Veza (vs standards SaaS type Discord/Spotify)

Date : 2026-02-05
Périmètre : apps/web — structure des composants, styles (Tailwind / KŌDŌ), stories Storybook, décorateur global, accessibilité.
Référentiel : cohérence design system, états dinterface, complexité des composants, illusion applicative, a11y.


Synthèse exécutive

Le frontend sappuie sur un système de design KŌDŌ riche (tokens CSS, thème clair/sombre) et un Storybook stabilisé (0 erreur réseau/console, contrat documenté). Les écarts principaux par rapport à des standards type Discord/Spotify portent sur : utilisation encore forte de valeurs arbitraires malgré les tokens, états dinterface incomplets dans de nombreuses stories (Loading/Error/Disabled/Focus), plusieurs composants “monolithes” difficiles à tester et à faire évoluer, décorateur Storybook sans gestion des transitions ni du feedback tactile, et a11y partiellement couverte (addon présent, tests a11y en “todo”).

Les problèmes sont classés en Bloquant, Amélioration et Perfectionnement.


1. Cohérence du système de design

Ce qui est en place

  • Tokens centralisés dans src/index.css : palette (void, cyan, magenta, lime), sémantiques (primary, destructive, success, warning), radius (--radius), durées (--duration-fast, --duration-normal, etc.), easings, glows, glass.
  • Thème Tailwind v4 via @theme inline : couleurs (--color-primary, --color-sidebar-*), radius (--radius-sm à --radius-2xl), typo (font-sans, font-mono, font-display).
  • Composants UI de base : button.tsx utilise des tokens (bg-kodo-cyan, ring-kodo-cyan, focus-visible:ring-2), CVA pour variants/sizes, pas de valeurs arbitraires dans les variants.

Problèmes identifiés

Criticité Constat Détail
Amélioration Valeurs arbitraires nombreuses Plus de 170 fichiers contiennent des classes type h-[…], w-[…], p-[…], gap-[…], rounded-[…]. Ex. : h-[400px], w-[300px], min-h-[600px], w-[500px], h-[70px] dans stories et composants.
Amélioration Stories comme source de dérive Les stories utilisent souvent des conteneurs en h-[600px], w-[300px] pour le rendu. Ces valeurs ne sappuient pas sur les tokens (ex. --radius-lg, h-96, max-w-3xl).
Perfectionnement Échelle despacement Les tokens despacement (4px, 8px, 16px, 24px…) sont partiellement reflétés en Tailwind ; des p-4, p-8 coexistent avec des p-[12px] ou gap-[11px] ponctuels.

Recommandations

  • Remplacer progressivement les valeurs arbitraires par des tokens : par ex. h-[400px]h-[var(--height-panel)] ou min-h-96 si une scale est définie.
  • Documenter une scale de hauteurs/largeurs (cards, modals, sidebars) dans le design system et lutiliser dans les stories.
  • Linter / règle custom (stylelint ou ESLint) pour limiter les […px] / […]rem hors tokens.

Mise à jour (nettoyage systémique)

Layout primitives ont été ajoutées dans src/index.css pour App/Layouts et App/Pages :

  • Variables CSS (:root) : --layout-content-max-width (100rem), --layout-main-min-height, --layout-page-min-height (37.5rem), --layout-page-min-height-sm (25rem), --layout-story-decorator-min-height (12rem).
  • Classes utilitaires (@layer utilities) : .max-w-layout-content, .min-h-layout-main, .min-h-layout-page, .min-h-layout-page-sm, .min-h-layout-story.
  • Remplacements effectués : max-w-[1600px]max-w-layout-content (Layout, DashboardLayout, ChatPage) ; min-h-[calc(100vh-64px)]min-h-layout-main (Layout) ; min-h-[600px]min-h-layout-page (UserProfilePage, SettingsPage, PlaylistDetailPage) ; min-h-[400px]min-h-layout-page-sm (LibraryPage, SessionsPage) ; min-h-[200px] (Navbar story) → min-h-layout-story ; md:w-[400px] (AudioPlayer) → md:w-96 ; min-h-[44px]min-h-11 (PlaylistListPage) ; min-w-[140px]min-w-36 (SettingsPage) ; h-[60%] / h-[40%]h-3/5 / h-2/5 (LibraryPage). Les ombres et valeurs viewport (ex. h-[60vh]) sont laissées en létat.

2. Qualité des états dinterface (stories)

Ce qui est en place

  • Loading / Skeleton : LoadingState, Skeleton, TrackListSkeleton, PlayerLoading ont des stories dédiées.
  • Error : ErrorDisplay, PlayerError, AuthErrorMessage, ErrorBoundary, Alert (variant error) sont couverts.
  • Focus : Le Button a focus-visible:ring-2 focus-visible:ring-kodo-cyan ; plusieurs composants UI (input, checkbox, select, tabs) ont du focus: ou focus-visible:.
  • Disabled : Présent dans ~23 fichiers de stories (Button, Checkbox, VolumeControl, etc.).

Problèmes identifiés

Criticité Constat Détail
Bloquant Addon a11y non exploité Dans .storybook/preview.tsx, a11y: { test: 'todo' } — les tests a11y ne sont pas exécutés en CI ni utilisés comme garde-fou.
Amélioration Loading “factice” sur Button La story LoadingState du Button est un disabled + texte "Loading..." sans spinner ni aria-busy. Les standards SaaS montrent un état de chargement explicite (spinner + désactivation).
Amélioration États manquants par type de composant Beaucoup de composants “carte” ou “liste” nont quun état Default : pas de story Empty, Error, Loading ou Disabled (ex. plusieurs vues Playlist, Track, Chat, Commerce).
Amélioration Hover / Active peu documentés Peu de stories nommées "Hover" ou "Active" ; les variants sont surtout visuels. Pas de démo systématique des états interactifs (hover/active) pour les boutons et liens.
Perfectionnement Focus visible inégal Une soixantaine de fichiers de composants utilisent focus: ou focus-visible: ; dautres (cards cliquables, list items, custom controls) peuvent ne pas avoir de ring/outline visible.

Recommandations

  • Passer a11y.test de 'todo' à une config réelle (ex. runOnly avec règles WCAG 2.1 AA) et faire échouer le build/audit si des violations sont détectées.
  • Ajouter une story Loading réaliste au Button (spinner + disabled + aria-busy) et un état Disabled explicite partout où laction peut être désactivée.
  • Pour les listes/cartes (Playlist, Track, Chat, Commerce), ajouter au moins Empty et Error (et Loading si async).
  • Documenter Hover / Active dans les stories des composants interactifs (boutons, nav, sidebar) pour valider la cohérence visuelle.

3. Complexité des composants (“composants dieux”)

Composants les plus volumineux (≥ ~400 lignes)

Fichier Lignes Responsabilités identifiées
ProfileForm.tsx 678 Refactorisé 2026-02-05 : module profile-form/ avec useProfileForm, ProfileCompletionCard, ProfileFormSkeleton, schéma dédié. Stories : Default, Loading, Error, ProfileFormSkeleton. Re-export depuis ProfileForm.tsx.
ProfileView.tsx 602 Refactorisé 2026-02-05 : module profile-view/ avec useProfileViewData, sous-composants (TrackCard, PlaylistCard, Sidebar, Overview, TracksTab, PlaylistsTab, AboutTab), ProfileViewSkeleton. Stories : Default, Loading, Error, ProfileViewSkeleton. Re-export depuis ProfileView.tsx.
GearView.tsx 559 Refactorisé 2026-02-05 : module gear-view/ avec useGearView, GearViewToolbar, GearViewSkeleton ; props pour stories. Stories : Default, Loading, Empty, Error, GearViewSkeleton. Re-export depuis GearView.tsx.
CommentThread.tsx 547 Refactorisé 2026-02-05 : module comment-thread/ avec hooks et sous-composants (voir ci-dessous).
LazyComponent.tsx 505 Refactorisé 2026-02-05 : module lazy-component/ avec LazyErrorFallback, LazyErrorBoundary, createLazyComponent, lazyExports. Stories : LazyErrorFallback (Default, WithRetry, NoError), LazyComponent (Default, Loading). Re-export depuis LazyComponent.tsx.
CloudFileBrowser.tsx 503 Module existant : features/studio/components/cloud-file-browser/ — orchestrateur CloudFileBrowser.tsx (~188 lignes), FileToolbar, FileTable, FileGrid, FileGridCard, FileTableRow, CloudFileBrowserSkeleton, types. Ancien fichier monolithe components/studio/CloudFileBrowser.tsx supprimé.
Search.tsx 494 Refactorisé 2026-02-05 : module features/search/components/search/ avec hooks et sous-composants (voir ci-dessous).
UploadModal.tsx 486 Refactorisé 2026-02-05 : module upload-modal/ avec useUploadModal, UploadModalDropzone, UploadModalFileDisplay, UploadModalProgress, UploadModalErrorAlert, UploadModalMetadataForm. Stories : Default, Open. Re-export depuis UploadModal.tsx.
file-upload.tsx 478 Refactorisé 2026-02-05 : module components/ui/file-upload/ avec useFileUpload, FileUploadDropzone, FileUploadErrorList, FileUploadFileList. Stories : Default, Empty, ImagesOnly, MaxSize, Disabled, Error, StateSimulation. Point dentrée file-upload/index.ts.
ChatSidebar.tsx 469 Refactorisé 2026-02-05 : module chat-sidebar/ avec hooks (useChatConversations, useConversationActions) et sous-composants (Header, Empty, Skeleton, ConversationItem). Stories : Default, Empty, Error, ChatSidebarSkeleton.
select.tsx 466 Refactorisé 2026-02-05 : module components/ui/select/ avec useSelect, SelectTrigger, SelectDropdownContent, SelectOptionItem. Stories : Default, Empty, Disabled, Grouped, MultiSelect. Point dentrée select/index.ts.
NotificationsPage.tsx 421 Refactorisé 2026-02-05 : module features/notifications/components/notifications-page/ avec useNotificationsPage, Header, Filters, Item, Empty, Error, Skeleton. Stories : Default, Loading, Error, Empty. Re-export depuis pages/NotificationsPage.tsx.
SearchPage.tsx 235 Refactorisé 2026-02-05 : module features/search/components/search-page/ avec useSearchPage, Header, Discovery, Empty, Error, Results, Skeleton. Stories : Default, Loading, Empty, Error. MSW : GET search → SearchResults.
FileManagerView.tsx 449 Refactorisé 2026-02-05 : module components/views/file-manager-view/ avec useFileManagerView, Header, Toolbar, Table, Grid, Empty, Skeleton. Stories : Default, Loading, Empty. Re-export depuis FileManagerView.tsx.
RegisterPage.tsx 380 Refactorisé 2026-02-05 : module features/auth/components/register-page/ avec useRegisterPage, RegisterPageForm, RegisterPageVerificationNotice, RegisterPageSkeleton. Stories : Default, Loading, WithError. Re-export depuis pages/RegisterPage.tsx.
MonitoringDashboard.tsx 423 Refactorisé 2026-02-05 : module components/monitoring/monitoring-dashboard/ avec useMonitoringDashboard, MonitoringDashboardContent (découpé en Header, Stats, ValidationCard, ErrorsCard, PerformanceCard), MonitoringDashboardSkeleton, types. Stories : Default, Loading, Error. Layout primitive min-h-layout-page-sm pour skeleton et erreur. Re-export depuis MonitoringDashboard.tsx.
PlaybackDashboard.tsx 434 Refactorisé 2026-02-05 : module features/streaming/components/playback-dashboard/ avec usePlaybackDashboard, StatsCard, TrendsCard, Charts, DetailedCard, Content, Skeleton. Stories : Default, Loading, Error, Empty. MSW : GET /api/v1/tracks/:id/playback/dashboard. Re-export depuis PlaybackDashboard.tsx.
ShareLinkManager.tsx 413 Refactorisé 2026-02-05 : module components/share/share-link-manager/ avec useShareLinkManager, CreateForm, Item, Empty, Content, Skeleton. Props optionnelles initialLinks, isLoading. Stories : Default, Empty, Loading, Error. Re-export depuis ShareLinkManager.tsx.
date-picker.tsx 445 Refactorisé 2026-02-05 : module components/ui/date-picker/ avec useDatePicker, DatePickerTrigger, DatePickerCalendar, types. Stories : SingleDate, DateRange, Disabled. Point dentrée date-picker/index.ts.
avatar-upload.tsx 436 Refactorisé 2026-02-05 : module components/ui/avatar-upload/ avec useAvatarUpload, AvatarUploadDropzone, AvatarUploadActions, AvatarUploadSkeleton. Stories : Default, WithExistingAvatar, Disabled, Large, Loading. MSW : POST avatar retourne avatar_url. Point dentrée avatar-upload/index.ts.
optimized-image.tsx 407 Refactorisé 2026-02-05 : module components/ui/optimized-image/ avec types, generateImageSources, BlurPlaceholder, useImageFormatSupport, OptimizedImage, OptimizedImageSkeleton, useImagePreloader, ResponsiveImage. Stories : Default, WithPlaceholder, ErrorState, Loading (skeleton). Re-export depuis optimized-image.tsx.
DataList.tsx 398 Refactorisé 2026-02-05 : module components/ui/data-list/ avec types, DataListSkeleton, DataListEmpty, DataListError, DataList. Modal/Dropdown retirés (doublons de modal.tsx/dropdown.tsx). Stories : Default, Loading, Empty, Error, Skeleton. Re-export depuis DataList.tsx.
components/player/AudioPlayer.tsx 405 Refactorisé 2026-02-05 : module components/player/audio-player/ avec types, useAudioPlayerEffects, AudioPlayerTrackInfo, AudioPlayerControls, AudioPlayerProgress, AudioPlayerVolume, AudioPlayerSkeleton, AudioPlayer. Stories : Default (avec mock store), Skeleton. Re-export depuis AudioPlayer.tsx.
TrackFilters.tsx 401 Refactorisé 2026-02-05 : module features/tracks/components/track-filters/ avec useTrackFilters, TrackFiltersHeader, TrackFiltersSearch, TrackFiltersGrid, TrackFiltersClear, TrackFiltersSkeleton. Stories : Default, Collapsible, Loading. Re-export depuis TrackFilters.tsx.
PlaylistList.tsx 380 Refactorisé 2026-02-05 : module features/playlists/components/playlist-list/ avec usePlaylistList, PlaylistListToolbar, PlaylistListEmpty, PlaylistListError. Skeleton existant PlaylistListSkeleton. Stories : Default, Grid, Empty (MSW), Loading (skeleton). Re-export depuis PlaylistList.tsx.
dialog.tsx 365 Refactorisé 2026-02-05 : module components/ui/dialog/ avec types, Dialog, DialogHeader, DialogBody, DialogFooter, DialogContent, DialogDescription, DialogTitle, DialogTrigger, DialogSkeleton. Stories : Default, Alert, Composition, Loading. Re-export depuis dialog.tsx.
dropdown-menu.tsx 345 Refactorisé 2026-02-05 : module components/ui/dropdown-menu/ avec types, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuPlaceholders (Group, Portal, Sub, SubContent, SubTrigger, RadioGroup). Dropdown base (dropdown.tsx) : open / defaultOpen pour mode contrôlé. Conformité UI : min-w-32 (pas de valeur arbitraire). Re-export depuis dropdown-menu.tsx.
accordion.tsx 335 Refactorisé 2026-02-05 : module components/ui/accordion/ avec types, Accordion, AccordionItem, AccordionTrigger, AccordionContent. Conformité UI : max-h-[5000px]max-h-none, stories w-[500px]max-w-xl. Re-export depuis accordion.tsx.
tabs.tsx 330 Refactorisé 2026-02-05 : module components/ui/tabs/ avec types, Tabs, TabsList, TabsTrigger, TabsContent. Stories w-[400px]max-w-md. Re-export depuis tabs.tsx.
tooltip.tsx 327 Refactorisé 2026-02-05 : module components/ui/tooltip/ avec types, useTooltip, TooltipContent, Tooltip. Handlers hover sur wrapper, click/focus sur enfant (cloneElement). Conformité : max-w-xs par défaut, stories h-[200px]min-h-layout-story. Re-export depuis tooltip.tsx.
Table.tsx (data) 323 Refactorisé 2026-02-05 : module components/data/table/ avec types, useTable, TableHeadRow, TableBodyRows, Table. Conformité : largeur colonnes via style (pas de classe arbitraire). Stories : Default, Empty, Paginated, Selectable (Data/Table). Re-export depuis Table.tsx.
FormBuilder.tsx 316 Refactorisé 2026-02-05 : module components/forms/form-builder/ avec types, useFormBuilder, FormBuilderFieldWidget, FormBuilder. Conformité : textarea min-h-[80px]min-h-20. Stories : Default, Empty, Disabled (Components/Forms/FormBuilder). Re-export depuis FormBuilder.tsx.
EditProfile.tsx 310 Refactorisé 2026-02-05 : module components/settings/profile/edit-profile/ avec types, cropUtils, useEditProfile, EditProfileImagesCard, EditProfileIdentityCard, EditProfileSidebar, EditProfileSkeleton. Conformité : textarea min-h-[100px]min-h-24. Stories : Default, Loading (Skeleton). Re-export depuis EditProfile.tsx.
GroupDetailView.tsx 307 Refactorisé 2026-02-05 : module components/social/groups/group-detail-view/ avec types (ExtendedGroup, GroupMember, GroupEvent), useGroupDetailView, GroupDetailViewHeader, GroupDetailViewMembers, GroupDetailViewEvents, GroupDetailViewSidebar, GroupDetailViewSkeleton. Conformité : text-[10px]text-xs, min-w-[80px]min-w-20. Stories : Default, Loading. Re-export depuis GroupDetailView.tsx.
UserProfilePage.tsx 318 Refactorisé 2026-02-05 : module features/profile/pages/user-profile-page/ avec useUserProfilePage, UserProfilePageHero, UserProfilePageHeader, UserProfilePageTabs, UserProfilePageSkeleton, UserProfilePageError. Conformité : stats text-[10px]text-xs. Stories : Default (route /u/demo), Loading (Skeleton), NotFound (route /u/notfound). MSW : GET /api/v1/users/by-username/:username (404 pour notfound). Re-export depuis UserProfilePage.tsx.
AccountSettings.tsx 362 Refactorisé 2026-02-05 : module features/settings/components/account-settings/ avec useAccountSettings, AccountSettingsErrorBanner, AccountSettingsPasswordCard, AccountSettingsExportCard, AccountSettingsDeleteCard, AccountSettingsSkeleton. Stories : Default, Loading. Re-export depuis AccountSettings.tsx.
TrackSearchFilters.tsx 348 Refactorisé 2026-02-05 : module features/tracks/components/track-search-filters/ avec useTrackSearchFilters, TrackSearchFiltersBasic, TrackSearchFiltersAdvanced, TrackSearchFiltersSkeleton. Stories : Default, Applied, Loading. Re-export depuis TrackSearchFilters.tsx.
SessionsPage.tsx 351 Refactorisé 2026-02-05 : module features/auth/components/sessions-page/ avec useSessionsPage, SessionsPageHeader, SessionsPageErrorBanner, SessionsPageRevokeAllButton, SessionsPageSessionItem, SessionsPageContent, SessionsPageEmpty, SessionsPageSkeleton. Stories : Default, Loading, Empty, Error. MSW : GET/DELETE auth/sessions. Re-export depuis pages/SessionsPage.tsx.
ProjectDetailView.tsx 367 Refactorisé 2026-02-05 : module components/studio/projects/project-detail-view/ avec useProjectDetailView, ProjectDetailViewHeader, ProjectDetailViewTabs, ProjectDetailViewOverview, ProjectDetailViewFiles, ProjectDetailViewSettings, ProjectDetailViewSidebar, ProjectDetailViewSkeleton. Stories : Default, Loading, Empty. Re-export depuis projects/ProjectDetailView.tsx.
PlaybackHeatmap.tsx 353 Refactorisé 2026-02-05 : module features/streaming/components/playback-heatmap/ avec usePlaybackHeatmap, PlaybackHeatmapHeader, PlaybackHeatmapStats, PlaybackHeatmapGrid, PlaybackHeatmapSkeleton, PlaybackHeatmapError, PlaybackHeatmapEmpty. Stories : Default, CustomSegmentSize, Loading, Empty, Error. MSW : GET /api/v1/tracks/:id/playback/heatmap. Re-export depuis PlaybackHeatmap.tsx.
ProductDetailView.tsx 352 Refactorisé 2026-02-05 : module components/marketplace/product-detail-view/ avec useProductDetailView, ProductDetailViewHeader, ProductDetailViewGallery, ProductDetailViewInfo, ProductDetailViewLicenses, ProductDetailViewDescription, ProductDetailViewReviews, ProductDetailViewSimilar, ProductDetailViewSkeleton. Stories : Default, Loading, Empty, WithReviews. Re-export depuis ProductDetailView.tsx.
CourseLearningView.tsx 353 Refactorisé 2026-02-05 : module components/education/course-learning-view/ avec useCourseLearningView, CourseLearningViewHeader, CourseLearningViewPlayer, CourseLearningViewTabs, CourseLearningViewSidebar, CourseLearningViewSkeleton. Layout min-h-layout-main. Stories : Default, Loading, Empty, Complete. Re-export depuis CourseLearningView.tsx.
CourseDetailView.tsx 348 Refactorisé 2026-02-05 : module components/education/course-detail-view/ avec useCourseDetailView, CourseDetailViewHeader, CourseDetailViewTabs, CourseDetailViewSidebar, CourseDetailViewSkeleton. Stories : Default, Loading, Empty, Enrolled. Re-export depuis CourseDetailView.tsx.
LibraryManager.tsx 337 Refactorisé 2026-02-05 : module features/library/components/library-manager/ avec useLibraryManager, Header, Toolbar, Error, Empty, Content, Stats, LibraryManagerSkeleton. Layout min-h-layout-page. Stories : Default, Loading, Empty, Error. MSW : GET /api/v1/tracks. Re-export depuis LibraryManager.tsx.
NotificationMenu.tsx 339 Refactorisé 2026-02-05 : module components/notifications/notification-menu/ avec useNotificationMenu, Trigger, Dropdown, List, Item, NotificationMenuSkeleton. Dropdown max-h-96. Stories : Default, Loading, Empty, Error, Skeleton. Re-export depuis NotificationMenu.tsx.
PlaylistTrackList.tsx 309 Refactorisé 2026-02-05 : module features/playlists/components/playlist-track-list/ avec usePlaylistTrackList, Empty, SortableItem, Skeleton, utils. Stories : Default, Loading, Empty, Reordering. Re-export depuis PlaylistTrackList.tsx et PlaylistTrackListSkeleton.tsx.
AddTrackToPlaylistModal.tsx 324 Refactorisé 2026-02-05 : module features/playlists/components/add-track-to-playlist-modal/ avec useAddTrackToPlaylistModal, AddTrackToPlaylistModalSearch, AddTrackToPlaylistModalList, AddTrackToPlaylistModalTrackRow, AddTrackToPlaylistModalFooter, AddTrackToPlaylistModalSkeleton. Liste max-h-96. Stories : Default, Loading (Skeleton). Re-export depuis AddTrackToPlaylistModal.tsx.
PlaylistBatchActions.tsx 323 Refactorisé 2026-02-05 : module features/playlists/components/playlist-batch-actions/ avec usePlaylistBatchActions, exportUtils, PlaylistBatchActionsBar, PlaylistBatchActionsButtons, PlaylistBatchActionsDeleteDialog, PlaylistBatchActionsSkeleton. Boutons min-h-11. Stories : Default, SingleSelection, Loading. Re-export depuis PlaylistBatchActions.tsx.
PlaylistSearch.tsx 331 Refactorisé 2026-02-05 : module features/playlists/components/playlist-search/ avec usePlaylistSearch, PlaylistSearchBar, PlaylistSearchFilters, PlaylistSearchResults, PlaylistSearchSkeleton. Chargement avec Spinner. PLAYLIST_SEARCH activé en Storybook (VITE_STORYBOOK). MSW : GET /api/v1/playlists/search. Stories : Default, Loading, Empty, Error. Re-export depuis PlaylistSearch.tsx.
CreatePlaylistDialog.tsx 186 Refactorisé 2026-02-05 : module features/playlists/components/create-playlist-dialog/ avec schema, useCreatePlaylistDialog, CreatePlaylistDialogForm, CreatePlaylistDialogSkeleton. Bouton Créer avec Spinner. Stories : Default, Loading. Re-export depuis CreatePlaylistDialog.tsx.
SharePlaylistModal.tsx 145 Refactorisé 2026-02-05 : module features/playlists/components/share-playlist-modal/ avec useSharePlaylistModal, SharePlaylistModalContent, SharePlaylistModalSkeleton. ErrorDisplay + retry. Stories : Default, Loading, Error. Re-export depuis SharePlaylistModal.tsx.
AddCollaboratorModal.tsx 200 Refactorisé 2026-02-05 : module features/playlists/components/add-collaborator-modal/ avec useAddCollaboratorModal, AddCollaboratorModalForm, AddCollaboratorModalSkeleton. ErrorDisplay (validation + mutation, retry). Stories : Default, Loading, Error (MSW). Re-export depuis AddCollaboratorModal.tsx.
UploadView.tsx 301 Refactorisé 2026-02-05 : module components/views/upload-view/ avec useUploadView, UploadViewStepper, UploadViewStep1, UploadViewStep2, UploadViewStep3, UploadViewSkeleton. Layout min-h-layout-page, max-h-96. Stories : Default, Loading, Empty, Error. Re-export depuis UploadView.tsx.
TwoFactorSetup.tsx 322 Refactorisé 2026-02-05 : module components/settings/security/two-factor-setup/ avec useTwoFactorSetup, TwoFactorSetupHeader, TwoFactorSetupStep1, TwoFactorSetupStep2, TwoFactorSetupStep3, TwoFactorSetupSkeleton. Stories : Default, Step1, Step2, Loading, Error (MSW). Re-export depuis TwoFactorSetup.tsx.
TrackHistory.tsx 324 Refactorisé 2026-02-05 : module features/tracks/components/track-history/ avec useTrackHistory, TrackHistoryHeader, TrackHistoryEmpty, TrackHistoryItemRow, TrackHistoryPagination, TrackHistorySkeleton, trackHistoryUtils. Stories : Default, Loading, Empty, Error (MSW). Re-export depuis TrackHistory.tsx.
ProjectsManager.tsx 322 Refactorisé 2026-02-05 : module components/studio/projects-manager/ avec useProjectsManager, ProjectsManagerHeader, ProjectsManagerFilterBar, ProjectsManagerCard, ProjectsManagerAddCard, ProjectsManagerEmpty, ProjectsManagerSkeleton. Stories : Default, Loading, Empty. Re-export depuis ProjectsManager.tsx.
CreateProjectModal.tsx 127 Refactorisé 2026-02-05 : module components/studio/projects/create-project-modal/ avec useCreateProjectModal, CreateProjectModalHeader, CreateProjectModalForm, CreateProjectModalFooter, CreateProjectModalSkeleton. Stories : Default, Loading. Re-export depuis projects/CreateProjectModal.tsx.
GoLiveView.tsx 255 Refactorisé 2026-02-05 : module components/studio/go-live-view/ avec useGoLiveView, GoLiveViewHeader, GoLiveViewPreview, GoLiveViewStreamInfo, GoLiveViewEncoderSetup, GoLiveViewQuickInstructions, GoLiveViewMicLevel, GoLiveViewSkeleton. Stories : Default, Loading. Re-export depuis GoLiveView.tsx.
ConnectivityView.tsx 192 Refactorisé 2026-02-05 : module components/studio/connectivity-view/ avec useConnectivityView, ConnectivityViewWebDAV, ConnectivityViewWebhooks, ConnectivityViewSkeleton. Stories : Default, Loading. Re-export depuis ConnectivityView.tsx.
AIToolsView.tsx 188 Refactorisé 2026-02-05 : module components/studio/ai-tools-view/ avec useAIToolsView, AIToolsViewToolGrid, AIToolsViewWorkspace, AIToolsViewSkeleton, constantes AI_TOOLS. Stories : Default, Loading. Re-export depuis AIToolsView.tsx.
CloudSettingsView.tsx 113 Refactorisé 2026-02-05 : module components/studio/cloud-settings-view/ avec useCloudSettingsView, CloudSettingsViewQuota, CloudSettingsViewPreferences, CloudSettingsViewSkeleton. Stories : Default, Loading. Re-export depuis CloudSettingsView.tsx.
StudioView.tsx 169 Refactorisé 2026-02-05 : module components/views/studio-view/ avec useStudioView, StudioViewHeader, StudioViewSidebar, StudioViewNavButton, StudioViewContent, StudioViewProjectsSwitch, StudioViewSkeleton. Layout min-h-layout-main ; w-[65%]w-2/3. Stories : Default, Projects, Loading. Re-export depuis StudioView.tsx.

Problèmes identifiés

Criticité Constat Détail
Amélioration Trop de responsabilités dans un seul fichier Réduit : CloudFileBrowser est désormais un module (FileToolbar, FileTable, FileGrid, etc.) dans features/studio/components/cloud-file-browser/.
Amélioration Logique métier + UI mélangées CommentThread, ProfileForm, Search : logique (appels API, état) et rendu (JSX) dans le même composant ; pas de découpage net en hooks + sous-composants.
Perfectionnement Réutilisabilité limitée GearView, ProfileView : vues “pages” très spécifiques ; extraire des blocs (Header, Stats, List, Filters) permettrait des stories et des tests plus ciblés.

Recommandations

  • CloudFileBrowser : déjà découpé dans features/studio/components/cloud-file-browser/ (FileToolbar, FileTable, FileGrid, CloudFileBrowserSkeleton, etc.) ; ancien monolithe components/studio/ supprimé.
  • CommentThread (fait 2026-02-05) : logique extraite dans useCommentReplies, useCommentActions ; rendu délégué à CommentThreadHeader, CommentThreadContent, CommentThreadActions, CommentReplyForm, CommentRepliesList ; CommentThreadSkeleton pour létat Loading. Stories : Default, WithReplies, DeeplyNested, Edited, EmptyReplies, LoadingReplies, ReplyError. MSW : PUT /api/v1/comments/:id ajouté.
  • ProfileForm (fait 2026-02-05) : module features/user/components/profile-form/ avec useProfileForm, ProfileCompletionCard, ProfileFormSkeleton, schéma zod dédié. Stories : Default, Loading, Error, ProfileFormSkeleton. Re-export depuis ProfileForm.tsx.
  • ProfileView (fait 2026-02-05) : module components/views/profile-view/ avec useProfileViewData ; sous-composants ProfileViewTrackCard, ProfileViewPlaylistCard, ProfileViewSidebar, ProfileViewOverview, ProfileViewTracksTab, ProfileViewPlaylistsTab, ProfileViewAboutTab, ProfileViewSkeleton. Stories : Default, Loading, Error, ProfileViewSkeleton. Re-export depuis ProfileView.tsx.
  • Search (fait 2026-02-05) : logique extraite dans useSearchSuggestions ; présentiel SearchInput, SearchDropdown, SearchSkeleton ; orchestrateur dans Search.tsx. Stories : Default, NoHistory, Loading, Empty, Error. Re-export depuis components/search/Search.
  • ChatSidebar (fait 2026-02-05) : module features/chat/components/chat-sidebar/ avec useChatConversations, useConversationActions ; sous-composants ChatSidebarHeader, ChatSidebarEmpty, ChatSidebarSkeleton, ConversationItem. Stories : Default, Empty, Error, ChatSidebarSkeleton. Re-export depuis ChatSidebar.tsx.
  • GearView (fait 2026-02-05) : module components/views/gear-view/ avec useGearView (filter, search, viewMode, itemsOverride, isLoading, error), GearViewToolbar, GearViewSkeleton. Stories : Default, Loading, Empty, Error, GearViewSkeleton. Re-export depuis GearView.tsx.
  • LazyComponent (fait 2026-02-05) : module components/ui/lazy-component/ avec LazyErrorFallback, LazyErrorBoundary, createLazyComponent, lazyExports. Stories : LazyErrorFallback (Default, WithRetry, NoError), LazyComponent (Default, Loading). Layout primitive min-h-layout-page-sm pour lerreur. Re-export depuis LazyComponent.tsx.
  • UploadModal (fait 2026-02-05) : module features/upload/components/upload-modal/ avec useUploadModal, sous-composants (Dropzone, FileDisplay, Progress, ErrorAlert, MetadataForm). Stories : Default, Open. Re-export depuis UploadModal.tsx.
  • file-upload (fait 2026-02-05) : module components/ui/file-upload/ avec useFileUpload, FileUploadDropzone, FileUploadErrorList, FileUploadFileList. Stories : Default, Empty, Error, Disabled, etc. Point dentrée file-upload/index.ts.
  • select (fait 2026-02-05) : module components/ui/select/ avec useSelect, SelectTrigger, SelectDropdownContent, SelectOptionItem. Stories : Default, Empty, Disabled, Grouped, MultiSelect. Point dentrée select/index.ts.
  • NotificationsPage (fait 2026-02-05) : module features/notifications/components/notifications-page/ avec useNotificationsPage, Header, Filters, Item, Empty, Error, Skeleton. Stories : Default, Loading, Error, Empty. MSW : GET notifications aligné avec notificationService.
  • SearchPage (fait 2026-02-05) : module features/search/components/search-page/ avec useSearchPage, Header, Discovery, Empty, Error, Results, Skeleton. Stories : Default, Loading, Empty, Error. MSW : GET /api/v1/search → SearchResults.
  • FileManagerView (fait 2026-02-05) : module components/views/file-manager-view/ avec useFileManagerView, Header, Toolbar, Table, Grid, Empty, Skeleton. Stories : Default, Loading, Empty.
  • RegisterPage (fait 2026-02-05) : module features/auth/components/register-page/ avec useRegisterPage, Form, VerificationNotice, Skeleton. Stories : Default, Loading, WithError.
  • MonitoringDashboard (fait 2026-02-05) : module components/monitoring/monitoring-dashboard/ avec useMonitoringDashboard, Content, Skeleton, état Error avec réessai. Stories : Default, Loading, Error.
  • PlaybackDashboard (fait 2026-02-05) : module features/streaming/components/playback-dashboard/ avec usePlaybackDashboard, StatsCard, TrendsCard, Charts, DetailedCard, Skeleton. Stories : Default, Loading, Error, Empty. MSW playback dashboard.
  • ShareLinkManager (fait 2026-02-05) : module components/share/share-link-manager/ avec useShareLinkManager, CreateForm, Item, Empty, Content, Skeleton. Stories : Default, Empty, Loading, Error.
  • date-picker (fait 2026-02-05) : module components/ui/date-picker/ avec useDatePicker, Trigger, Calendar. Stories : SingleDate, DateRange, Disabled.
  • avatar-upload (fait 2026-02-05) : module components/ui/avatar-upload/ avec useAvatarUpload, Dropzone, Actions, Skeleton. Stories : Default, WithExistingAvatar, Disabled, Large, Loading.
  • optimized-image (fait 2026-02-05) : module components/ui/optimized-image/ avec types, generateImageSources, BlurPlaceholder, useImageFormatSupport, OptimizedImage, OptimizedImageSkeleton, useImagePreloader, ResponsiveImage. Stories : Default, WithPlaceholder, ErrorState, Loading.
  • DataList (fait 2026-02-05) : module components/ui/data-list/ avec types, DataListSkeleton, DataListEmpty, DataListError, DataList. Stories : Default, Loading, Empty, Error, Skeleton.
  • AudioPlayer components/player (fait 2026-02-05) : module components/player/audio-player/ avec useAudioPlayerEffects, AudioPlayerTrackInfo, AudioPlayerControls, AudioPlayerProgress, AudioPlayerVolume, AudioPlayerSkeleton. Stories : Default, Skeleton.
  • TrackFilters (fait 2026-02-05) : module features/tracks/components/track-filters/ avec useTrackFilters, TrackFiltersHeader, TrackFiltersSearch, TrackFiltersGrid, TrackFiltersClear, TrackFiltersSkeleton. Stories : Default, Collapsible, Loading.
  • TrackSearchFilters (fait 2026-02-05) : module features/tracks/components/track-search-filters/ avec useTrackSearchFilters, TrackSearchFiltersBasic, TrackSearchFiltersAdvanced, TrackSearchFiltersSkeleton. Stories : Default, Applied, Loading.
  • SessionsPage (fait 2026-02-05) : module features/auth/components/sessions-page/ avec useSessionsPage, Header, ErrorBanner, RevokeAllButton, SessionItem, Content, Empty, Skeleton. Stories : Default, Loading, Empty, Error. MSW : GET/DELETE auth/sessions.
  • ProjectDetailView (fait 2026-02-05) : module components/studio/projects/project-detail-view/ avec useProjectDetailView, Header, Tabs, Overview, Files, Settings, Sidebar, Skeleton. Stories : Default, Loading, Empty.
  • PlaybackHeatmap (fait 2026-02-05) : module features/streaming/components/playback-heatmap/ avec usePlaybackHeatmap, Header, Stats, Grid, Skeleton, Error, Empty. Stories : Default, CustomSegmentSize, Loading, Empty, Error. MSW : GET heatmap.
  • ProductDetailView (fait 2026-02-05) : module components/marketplace/product-detail-view/ avec useProductDetailView, Header, Gallery, Info, Licenses, Description, Reviews, Similar, Skeleton. Stories : Default, Loading, Empty, WithReviews.
  • CourseLearningView (fait 2026-02-05) : module components/education/course-learning-view/ avec useCourseLearningView, Header, Player, Tabs, Sidebar, Skeleton. Layout min-h-layout-main. Stories : Default, Loading, Empty, Complete.
  • CourseDetailView (fait 2026-02-05) : module components/education/course-detail-view/ avec useCourseDetailView, Header, Tabs, Sidebar, Skeleton. Stories : Default, Loading, Empty, Enrolled.
  • LibraryManager (fait 2026-02-05) : module features/library/components/library-manager/ avec useLibraryManager, Header, Toolbar, Error, Empty, Content, Stats, Skeleton. Stories : Default, Loading, Empty, Error. MSW GET /tracks.
  • NotificationMenu (fait 2026-02-05) : module components/notifications/notification-menu/ avec useNotificationMenu, Trigger, Dropdown, List, Item, Skeleton. Stories : Default, Loading, Empty, Error, Skeleton.
  • PlaylistTrackList (fait 2026-02-05) : module features/playlists/components/playlist-track-list/ avec usePlaylistTrackList, Empty, SortableItem, Skeleton. Stories : Default, Loading, Empty, Reordering.
  • AddTrackToPlaylistModal (fait 2026-02-05) : module features/playlists/components/add-track-to-playlist-modal/ avec useAddTrackToPlaylistModal, Search, List, TrackRow, Footer, Skeleton. Stories : Default, Loading.
  • PlaylistBatchActions (fait 2026-02-05) : module features/playlists/components/playlist-batch-actions/ avec usePlaylistBatchActions, exportUtils, Bar, Buttons, DeleteDialog, Skeleton. Stories : Default, SingleSelection, Loading.
  • PlaylistSearch (fait 2026-02-05) : module features/playlists/components/playlist-search/ avec usePlaylistSearch, Bar, Filters, Results, Skeleton. Stories : Default, Loading, Empty, Error. MSW playlists/search.
  • CreatePlaylistDialog (fait 2026-02-05) : module features/playlists/components/create-playlist-dialog/ avec schema zod, useCreatePlaylistDialog, Form, Skeleton. Stories : Default, Loading.
  • SharePlaylistModal (fait 2026-02-05) : module features/playlists/components/share-playlist-modal/ avec useSharePlaylistModal, Content, Skeleton. Stories : Default, Loading, Error.
  • AddCollaboratorModal (fait 2026-02-05) : module features/playlists/components/add-collaborator-modal/ avec useAddCollaboratorModal, Form, Skeleton. Stories : Default, Loading, Error (MSW). ErrorDisplay pour validation et mutation avec retry.
  • UploadView (fait 2026-02-05) : module components/views/upload-view/ avec useUploadView, Stepper, Step1/2/3, Skeleton. Stories : Default, Loading, Empty, Error.
  • TwoFactorSetup (fait 2026-02-05) : module components/settings/security/two-factor-setup/ avec useTwoFactorSetup, Header, Step1/2/3, Skeleton. Stories : Default, Step1, Step2, Loading, Error (MSW).
  • TrackHistory (fait 2026-02-05) : module features/tracks/components/track-history/ avec useTrackHistory, Header, Empty, ItemRow, Pagination, Skeleton, trackHistoryUtils. Stories : Default, Loading, Empty, Error (MSW).
  • ProjectsManager (fait 2026-02-05) : module components/studio/projects-manager/ avec useProjectsManager, Header, FilterBar, Card, AddCard, Empty, Skeleton. Stories : Default, Loading, Empty.
  • CreateProjectModal (fait 2026-02-05) : module components/studio/projects/create-project-modal/ avec useCreateProjectModal, Header, Form, Footer, Skeleton. Stories : Default, Loading.
  • GoLiveView (fait 2026-02-05) : module components/studio/go-live-view/ avec useGoLiveView, Header, Preview, StreamInfo, EncoderSetup, QuickInstructions, MicLevel, Skeleton. Stories : Default, Loading.
  • ConnectivityView (fait 2026-02-05) : module components/studio/connectivity-view/ avec useConnectivityView, WebDAV, Webhooks, Skeleton. Stories : Default, Loading.
  • AIToolsView (fait 2026-02-05) : module components/studio/ai-tools-view/ avec useAIToolsView, ToolGrid, Workspace, Skeleton, AI_TOOLS. Stories : Default, Loading. Conformité : text-xs, min-h-layout-page-sm ; pas de ToastProvider en story.
  • CloudSettingsView (fait 2026-02-05) : module components/studio/cloud-settings-view/ avec useCloudSettingsView, Quota, Preferences, Skeleton. Stories : Default, Loading.
  • StudioView (fait 2026-02-05) : module components/views/studio-view/ avec useStudioView, Header, Sidebar, NavButton, Content, ProjectsSwitch, Skeleton. Stories : Default, Projects, Loading. Conformité : h-[calc(...)] → min-h-layout-main, w-[65%] → w-2/3.
  • PlaylistList (fait 2026-02-05) : module features/playlists/components/playlist-list/ avec usePlaylistList, PlaylistListToolbar, PlaylistListEmpty, PlaylistListError. Stories : Default, Grid, Empty (MSW), Loading (skeleton).
  • dialog (fait 2026-02-05) : module components/ui/dialog/ avec Dialog, Header, Body, Footer, Content, Description, Title, Trigger, DialogSkeleton. Stories : Default, Alert, Composition, Loading.
  • dropdown-menu (fait 2026-02-05) : module components/ui/dropdown-menu/ avec types, Trigger, Content, Item, CheckboxItem, RadioItem, Label, Separator, Shortcut, Placeholders. Dropdown base : open/defaultOpen. Re-export depuis dropdown-menu.tsx.
  • accordion (fait 2026-02-05) : module components/ui/accordion/ avec types, Accordion, AccordionItem, AccordionTrigger, AccordionContent. Stories : Default, Multiple. Re-export depuis accordion.tsx.
  • tabs (fait 2026-02-05) : module components/ui/tabs/ avec types, Tabs, TabsList, TabsTrigger, TabsContent. Stories : Default. Re-export depuis tabs.tsx.
  • tooltip (fait 2026-02-05) : module components/ui/tooltip/ avec useTooltip, TooltipContent, Tooltip. Stories : Default, Positions, ManualTrigger. Re-export depuis tooltip.tsx.
  • AccountSettings (fait 2026-02-05) : module features/settings/components/account-settings/ avec useAccountSettings, ErrorBanner, PasswordCard, ExportCard, DeleteCard, AccountSettingsSkeleton. Stories : Default, Loading.
  • Les autres composants volumineux restants : appliquer le même principe pour améliorer la testabilité et la maintenabilité.

4. Fidélité de lillusion applicative (StorybookDecorator)

Ce qui est en place

  • Providers centralisés : I18nextProvider, ThemeProvider, QueryClientProvider, ToastProvider, AudioProvider, AuthProvider, MemoryRouter.
  • Router : parameters.router.initialEntries pour les stories dépendant dune route.
  • Thème : bascule light/dark via globals Storybook (backgrounds).
  • Toasts : en mode Storybook, toasts loggés en console (pas daffichage intrusif).

Problèmes identifiés

Criticité Constat Détail
Amélioration Pas de gestion des transitions Aucun wrapper prefers-reduced-motion ni fourniture de context pour désactiver les animations en Storybook. Les transitions CSS (--duration-*) sont appliquées telles quelles ; pas de mode “réduit” pour les tests ou laccessibilité.
Amélioration Feedback tactile non simulé Pas de décorateur ou paramètre pour simuler états tactiles (active, press) ou pointer (hover) de façon déterministe. Utile pour valider les états “pressed” / “hover” de boutons et cartes.
Perfectionnement Couleurs de fond en dur Le décorateur utilise #0a0a0a et #ffffff en inline style au lieu des tokens (var(--background)). En cas dévolution du thème, le conteneur Storybook peut diverger de lapp.
Perfectionnement Pas de “viewport” par défaut Des viewports custom (mobile, tablet, desktop) existent ; le décorateur ne force pas de viewport par story. Pour un rendu type “app”, un conteneur largeur max (ex. 1440px) pourrait être optionnel.

Recommandations

  • Ajouter un paramètre (ex. parameters.motion: 'reduce') et un wrapper qui applique prefers-reduced-motion: reduce (media query ou class) pour tester le comportement sans animations.
  • Utiliser les tokens pour le fond du conteneur : background: 'var(--background)' (et sassurer que les variables sont bien appliquées dans liframe).
  • Optionnel : décorateur ou paramètre pour forcer un état “interaction” (hover/active) sur le premier élément focusable, pour valider le focus visible et les états actifs dans les stories.

5. Accessibilité (a11y)

Ce qui est en place

  • ARIA / rôles : utilisés dans une soixantaine de composants (table, select, modal, tabs, pagination, breadcrumbs, tooltip, checkbox, progress, alert, etc.).
  • Contrastes : palette KŌDŌ en oklch avec séparation sémantique (primary, destructive, muted, etc.) ; fonds et textes prévus pour être lisibles.
  • Addon a11y : présent dans Storybook ; config actuelle a11y: { test: 'todo' }.
  • Focus visible : button, input, checkbox, select, tabs ont des styles focus-visible:ring ou équivalent.

Problèmes identifiés

Criticité Constat Détail
Bloquant Tests a11y non actifs Tant que test: 'todo', aucune violation a11y ne fait échouer laudit ni le build. Risque de régressions (contraste, labels, rôles).
Amélioration Contraste à vérifier sur cas réels Les combinaisons muted-foreground sur muted, ou textes sur “glass” / dégradés, nont pas été vérifiées automatiquement. Un audit manuel ou des tests a11y ciblés (contrast, label) sont recommandés.
Amélioration Zones cliquables non boutons Cartes ou lignes entières cliquables sans role="button" ni tabIndex={0} ni gestion clavier (Enter/Space) — à vérifier dans les composants “card” et “list”.
Perfectionnement Annonces live (toasts, chargement) Pas de revue systématique des aria-live, aria-busy, aria-atomic pour les toasts et états de chargement.

Recommandations

  • Activer les tests a11y dans Storybook : définir a11y: { runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa'] } } (ou équivalent) et intégrer le résultat à laudit (ou au moins au build Storybook) pour faire échouer en cas de violations.
  • Vérifier les cartes et listes cliquables : soit <button> ou div avec role="button", tabIndex={0}, et gestion onKeyDown (Enter/Space).
  • Planifier un audit contraste (manuel ou outil) sur les écrans clés (login, player, sidebar, modales) et documenter les ratios pour les combinaisons utilisées.

6. Tableau de synthèse par criticité

Criticité Thème Action prioritaire
Bloquant a11y Activer les tests a11y dans Storybook (retirer test: 'todo', définir des règles WCAG et les faire échouer le job si besoin).
Amélioration Design system Réduire les valeurs arbitraires (h-[…], w-[…]) en les remplaçant par des tokens ou des utilitaires Tailwind cohérents.
Amélioration États dinterface Compléter les stories : Loading réaliste (Button), Empty/Error/Loading pour listes et cartes, états Disabled et si possible Hover/Active.
Amélioration Composants dieux Découper CloudFileBrowser, CommentThread, ProfileForm/ProfileView en sous-composants et hooks testables.
Amélioration Illusion applicative Utiliser les tokens pour le fond du décorateur ; ajouter support reduced-motion et optionnellement états hover/active.
Amélioration a11y Vérifier cartes/listes cliquables (rôle, clavier) ; audit contraste sur écrans clés.
Perfectionnement Design system Scale despacement/hauteurs documentée ; linter pour limiter les valeurs arbitraires.
Perfectionnement États dinterface Stories Hover/Active explicites ; revue focus visible sur tous les contrôles.
Perfectionnement Composants Extraire blocs réutilisables des vues “page” (GearView, ProfileView, Search).
Perfectionnement a11y Revue aria-live / aria-busy pour toasts et chargement.

7. Prochaines étapes suggérées

  1. Court terme : Activer a11y dans Storybook et corriger les violations bloquantes ; ajouter les stories Empty/Error (et Loading si pertinent) aux composants listes/cartes les plus utilisés.
  2. Moyen terme : Découper 23 composants “dieux” (ex. CloudFileBrowser, CommentThread) et aligner les nouvelles stories sur les tokens (réduction des valeurs arbitraires).
  3. Long terme : Documenter une grille de hauteurs/largeurs et une checklist “états dinterface” pour toute nouvelle story ; intégrer reduced-motion et feedback tactile dans le décorateur.

Rapport généré dans le cadre de laudit frontend Veza — Storybook stabilisé, contrat dans docs/STORYBOOK_CONTRACT.md.