52 KiB
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 d’interface, complexité des composants, illusion applicative, a11y.
Synthèse exécutive
Le frontend s’appuie 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 d’interface 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.tsxutilise 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 s’appuient pas sur les tokens (ex. --radius-lg, h-96, max-w-3xl). |
| Perfectionnement | Échelle d’espacement | Les tokens d’espacement (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)]oumin-h-96si une scale est définie. - Documenter une scale de hauteurs/largeurs (cards, modals, sidebars) dans le design system et l’utiliser dans les stories.
- Linter / règle custom (stylelint ou ESLint) pour limiter les
[…px]/[…]remhors 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 d’interface (stories)
Ce qui est en place
- Loading / Skeleton :
LoadingState,Skeleton,TrackListSkeleton,PlayerLoadingont des stories dédiées. - Error :
ErrorDisplay,PlayerError,AuthErrorMessage,ErrorBoundary,Alert(variant error) sont couverts. - Focus : Le
Buttonafocus-visible:ring-2 focus-visible:ring-kodo-cyan; plusieurs composants UI (input, checkbox, select, tabs) ont dufocus:oufocus-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” n’ont qu’un é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: ; d’autres (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.runOnlyavec 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ù l’action 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 |
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 |
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 |
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 |
Refactorisé 2026-02-05 : module comment-thread/ avec hooks et sous-composants (voir ci-dessous). |
|
LazyComponent.tsx |
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 |
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 |
Refactorisé 2026-02-05 : module features/search/components/search/ avec hooks et sous-composants (voir ci-dessous). |
|
UploadModal.tsx |
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 |
Refactorisé 2026-02-05 : module components/ui/file-upload/ avec useFileUpload, FileUploadDropzone, FileUploadErrorList, FileUploadFileList. Stories : Default, Empty, ImagesOnly, MaxSize, Disabled, Error, StateSimulation. Point d’entrée file-upload/index.ts. |
|
ChatSidebar.tsx |
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 |
Refactorisé 2026-02-05 : module components/ui/select/ avec useSelect, SelectTrigger, SelectDropdownContent, SelectOptionItem. Stories : Default, Empty, Disabled, Grouped, MultiSelect. Point d’entrée select/index.ts. |
|
NotificationsPage.tsx |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
Refactorisé 2026-02-05 : module components/ui/date-picker/ avec useDatePicker, DatePickerTrigger, DatePickerCalendar, types. Stories : SingleDate, DateRange, Disabled. Point d’entrée date-picker/index.ts. |
|
avatar-upload.tsx |
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 d’entrée avatar-upload/index.ts. |
|
optimized-image.tsx |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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) |
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 |
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 |
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 |
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 |
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. |
|
DiscoverView.tsx |
Refactorisé 2026-02-05 : module components/views/discover-view/ avec useDiscoverView, DiscoverViewHero, DiscoverViewTrending, DiscoverViewNewReleases, DiscoverViewGenres, DiscoverViewSkeleton, DiscoverViewError. Conformité : loading h-[50vh] → Skeleton ; badge UPDATED text-[10px] → text-xs ; erreur min-h-layout-page-sm. Stories : Default, Loading (Skeleton), Error. Re-export depuis DiscoverView.tsx. |
|
features/library/UploadModal.tsx |
Refactorisé 2026-02-05 : module features/library/components/upload-modal/ avec useLibraryUploadModal, UploadModalForm, UploadModalFooter, types (UploadModalProps, UploadFormData, ALLOWED_AUDIO_TYPES, MAX_FILE_SIZE_BYTES). Stories inchangées : Default, Controlled. Re-export depuis UploadModal.tsx. |
|
features/player/components/AudioPlayer.tsx |
Refactorisé 2026-02-05 : module features/player/components/audio-player/ avec useAudioPlayerLifecycle, AudioPlayerCompact, AudioPlayerFull, AudioPlayerSkeleton. Stories : Playing, Paused, Loading (Skeleton), Error. Re-export et default export depuis AudioPlayer.tsx. 20 tests passent. |
|
AccountSettings.tsx |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
Refactorisé 2026-02-05 : module components/studio/connectivity-view/ avec useConnectivityView, ConnectivityViewWebDAV, ConnectivityViewWebhooks, ConnectivityViewSkeleton. Stories : Default, Loading. Re-export depuis ConnectivityView.tsx. |
|
AIToolsView.tsx |
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 |
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 |
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. |
|
context/AudioContext.tsx |
Refactorisé 2026-02-05 : module context/audio-context/ avec types (VisualizerSettings, AudioContextType), mockTracks, useAudioContextValue, AudioContext (createContext, useAudio, AudioProvider). Re-export depuis AudioContext.tsx. 12 tests passent. Correction : toggleMute bascule isMuted (au lieu de play). |
|
components/ui/virtualized-list.tsx |
Refactorisé 2026-02-05 : module components/ui/virtualized-list/ avec types (VirtualizedListProps), VirtualizedList, useInfiniteScroll, useScrollPosition. Re-export depuis virtualized-list.tsx (import explicite depuis ./virtualized-list/index). Stories : Default, SmallItems. 4 tests passent (mock useVirtualizer complété). |
|
components/views/FileDetailsView.tsx |
Refactorisé 2026-02-05 : module components/views/file-details-view/ avec types (FileDetailsViewProps, ActivityItem, VersionItem), mockData (MOCK_ACTIVITY, MOCK_VERSIONS, getMockFile), useFileDetailsView, Header, Preview, Metadata, Activity, Versions, Storage, FileDetailsViewSkeleton. Layout : min-h-[400px] → min-h-layout-page-sm, badge LATEST text-[10px] → text-xs. Stories : Default, Loading (Skeleton). Re-export depuis FileDetailsView.tsx. |
|
components/seller/CreateProductView.tsx |
Refactorisé 2026-02-05 : module components/seller/create-product-view/ avec types (LicenseConfig), useCreateProductView, Header, CoverCard, FilesCard, DetailsCard, PricingCard, CreateProductViewSkeleton. Textarea min-h-[120px] → min-h-24. MSW : POST /api/v1/marketplace/products. Stories : Default, Loading (Skeleton). Re-export depuis CreateProductView.tsx. |
|
features/chat/components/ChatInterface.tsx |
Refactorisé 2026-02-05 : module features/chat/components/chat-interface/ avec types (ChatInterfaceProps), useChatInterface (wsService, loadMessages, loadChatStats, formatTimestamp), Header, Messages, Input, ChatInterfaceSkeleton. Stories : Default, ProductionRoom, Loading (Skeleton). Decorator h-[600px] → min-h-layout-page. Re-export depuis ChatInterface.tsx. |
|
components/settings/account/AccountSettings.tsx |
Refactorisé 2026-02-05 : module components/settings/account/account-settings/ avec types (AccountSettingsUserMock, AccountSettingsToggles), useAccountSettingsPage (view, modals, user, toggles, theme), IdentityCard, PreferencesCard, NotificationsCard, PrivacyCard, DangerCard, AccountSettingsSkeleton. Privacy labels text-[10px] → text-xs. Stories : Default, Loading (Skeleton). Decorator min-h-screen → min-h-layout-page. Re-export depuis AccountSettings.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 monolithecomponents/studio/supprimé. - CommentThread (fait 2026-02-05) : logique extraite dans
useCommentReplies,useCommentActions; rendu délégué àCommentThreadHeader,CommentThreadContent,CommentThreadActions,CommentReplyForm,CommentRepliesList;CommentThreadSkeletonpour l’état Loading. Stories : Default, WithReplies, DeeplyNested, Edited, EmptyReplies, LoadingReplies, ReplyError. MSW : PUT/api/v1/comments/:idajouté. - ProfileForm (fait 2026-02-05) : module
features/user/components/profile-form/avecuseProfileForm,ProfileCompletionCard,ProfileFormSkeleton, schéma zod dédié. Stories : Default, Loading, Error, ProfileFormSkeleton. Re-export depuisProfileForm.tsx. - ProfileView (fait 2026-02-05) : module
components/views/profile-view/avecuseProfileViewData; sous-composantsProfileViewTrackCard,ProfileViewPlaylistCard,ProfileViewSidebar,ProfileViewOverview,ProfileViewTracksTab,ProfileViewPlaylistsTab,ProfileViewAboutTab,ProfileViewSkeleton. Stories : Default, Loading, Error, ProfileViewSkeleton. Re-export depuisProfileView.tsx. - Search (fait 2026-02-05) : logique extraite dans
useSearchSuggestions; présentielSearchInput,SearchDropdown,SearchSkeleton; orchestrateur dansSearch.tsx. Stories : Default, NoHistory, Loading, Empty, Error. Re-export depuiscomponents/search/Search. - ChatSidebar (fait 2026-02-05) : module
features/chat/components/chat-sidebar/avecuseChatConversations,useConversationActions; sous-composantsChatSidebarHeader,ChatSidebarEmpty,ChatSidebarSkeleton,ConversationItem. Stories : Default, Empty, Error, ChatSidebarSkeleton. Re-export depuisChatSidebar.tsx. - GearView (fait 2026-02-05) : module
components/views/gear-view/avecuseGearView(filter, search, viewMode, itemsOverride, isLoading, error),GearViewToolbar,GearViewSkeleton. Stories : Default, Loading, Empty, Error, GearViewSkeleton. Re-export depuisGearView.tsx. - LazyComponent (fait 2026-02-05) : module
components/ui/lazy-component/avecLazyErrorFallback,LazyErrorBoundary,createLazyComponent,lazyExports. Stories : LazyErrorFallback (Default, WithRetry, NoError), LazyComponent (Default, Loading). Layout primitivemin-h-layout-page-smpour l’erreur. Re-export depuisLazyComponent.tsx. - UploadModal (fait 2026-02-05) : module
features/upload/components/upload-modal/avecuseUploadModal, sous-composants (Dropzone, FileDisplay, Progress, ErrorAlert, MetadataForm). Stories : Default, Open. Re-export depuisUploadModal.tsx. - file-upload (fait 2026-02-05) : module
components/ui/file-upload/avecuseFileUpload,FileUploadDropzone,FileUploadErrorList,FileUploadFileList. Stories : Default, Empty, Error, Disabled, etc. Point d’entréefile-upload/index.ts. - select (fait 2026-02-05) : module
components/ui/select/avecuseSelect,SelectTrigger,SelectDropdownContent,SelectOptionItem. Stories : Default, Empty, Disabled, Grouped, MultiSelect. Point d’entréeselect/index.ts. - NotificationsPage (fait 2026-02-05) : module
features/notifications/components/notifications-page/avecuseNotificationsPage, 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/avecuseSearchPage, 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/avecuseFileManagerView, Header, Toolbar, Table, Grid, Empty, Skeleton. Stories : Default, Loading, Empty. - RegisterPage (fait 2026-02-05) : module
features/auth/components/register-page/avecuseRegisterPage, Form, VerificationNotice, Skeleton. Stories : Default, Loading, WithError. - MonitoringDashboard (fait 2026-02-05) : module
components/monitoring/monitoring-dashboard/avecuseMonitoringDashboard, Content, Skeleton, état Error avec réessai. Stories : Default, Loading, Error. - PlaybackDashboard (fait 2026-02-05) : module
features/streaming/components/playback-dashboard/avecusePlaybackDashboard, StatsCard, TrendsCard, Charts, DetailedCard, Skeleton. Stories : Default, Loading, Error, Empty. MSW playback dashboard. - ShareLinkManager (fait 2026-02-05) : module
components/share/share-link-manager/avecuseShareLinkManager, CreateForm, Item, Empty, Content, Skeleton. Stories : Default, Empty, Loading, Error. - date-picker (fait 2026-02-05) : module
components/ui/date-picker/avecuseDatePicker, Trigger, Calendar. Stories : SingleDate, DateRange, Disabled. - avatar-upload (fait 2026-02-05) : module
components/ui/avatar-upload/avecuseAvatarUpload, 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/avecuseAudioPlayerEffects,AudioPlayerTrackInfo,AudioPlayerControls,AudioPlayerProgress,AudioPlayerVolume,AudioPlayerSkeleton. Stories : Default, Skeleton. - TrackFilters (fait 2026-02-05) : module
features/tracks/components/track-filters/avecuseTrackFilters,TrackFiltersHeader,TrackFiltersSearch,TrackFiltersGrid,TrackFiltersClear,TrackFiltersSkeleton. Stories : Default, Collapsible, Loading. - TrackSearchFilters (fait 2026-02-05) : module
features/tracks/components/track-search-filters/avecuseTrackSearchFilters,TrackSearchFiltersBasic,TrackSearchFiltersAdvanced,TrackSearchFiltersSkeleton. Stories : Default, Applied, Loading. - SessionsPage (fait 2026-02-05) : module
features/auth/components/sessions-page/avecuseSessionsPage, 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/avecuseProjectDetailView, Header, Tabs, Overview, Files, Settings, Sidebar, Skeleton. Stories : Default, Loading, Empty. - PlaybackHeatmap (fait 2026-02-05) : module
features/streaming/components/playback-heatmap/avecusePlaybackHeatmap, 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/avecuseProductDetailView, Header, Gallery, Info, Licenses, Description, Reviews, Similar, Skeleton. Stories : Default, Loading, Empty, WithReviews. - CourseLearningView (fait 2026-02-05) : module
components/education/course-learning-view/avecuseCourseLearningView, Header, Player, Tabs, Sidebar, Skeleton. Layoutmin-h-layout-main. Stories : Default, Loading, Empty, Complete. - CourseDetailView (fait 2026-02-05) : module
components/education/course-detail-view/avecuseCourseDetailView, Header, Tabs, Sidebar, Skeleton. Stories : Default, Loading, Empty, Enrolled. - LibraryManager (fait 2026-02-05) : module
features/library/components/library-manager/avecuseLibraryManager, 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/avecuseNotificationMenu, Trigger, Dropdown, List, Item, Skeleton. Stories : Default, Loading, Empty, Error, Skeleton. - PlaylistTrackList (fait 2026-02-05) : module
features/playlists/components/playlist-track-list/avecusePlaylistTrackList, Empty, SortableItem, Skeleton. Stories : Default, Loading, Empty, Reordering. - AddTrackToPlaylistModal (fait 2026-02-05) : module
features/playlists/components/add-track-to-playlist-modal/avecuseAddTrackToPlaylistModal, Search, List, TrackRow, Footer, Skeleton. Stories : Default, Loading. - PlaylistBatchActions (fait 2026-02-05) : module
features/playlists/components/playlist-batch-actions/avecusePlaylistBatchActions, exportUtils, Bar, Buttons, DeleteDialog, Skeleton. Stories : Default, SingleSelection, Loading. - PlaylistSearch (fait 2026-02-05) : module
features/playlists/components/playlist-search/avecusePlaylistSearch, 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/avecuseSharePlaylistModal, Content, Skeleton. Stories : Default, Loading, Error. - AddCollaboratorModal (fait 2026-02-05) : module
features/playlists/components/add-collaborator-modal/avecuseAddCollaboratorModal, Form, Skeleton. Stories : Default, Loading, Error (MSW). ErrorDisplay pour validation et mutation avec retry. - UploadView (fait 2026-02-05) : module
components/views/upload-view/avecuseUploadView, Stepper, Step1/2/3, Skeleton. Stories : Default, Loading, Empty, Error. - TwoFactorSetup (fait 2026-02-05) : module
components/settings/security/two-factor-setup/avecuseTwoFactorSetup, Header, Step1/2/3, Skeleton. Stories : Default, Step1, Step2, Loading, Error (MSW). - TrackHistory (fait 2026-02-05) : module
features/tracks/components/track-history/avecuseTrackHistory, Header, Empty, ItemRow, Pagination, Skeleton, trackHistoryUtils. Stories : Default, Loading, Empty, Error (MSW). - ProjectsManager (fait 2026-02-05) : module
components/studio/projects-manager/avecuseProjectsManager, Header, FilterBar, Card, AddCard, Empty, Skeleton. Stories : Default, Loading, Empty. - CreateProjectModal (fait 2026-02-05) : module
components/studio/projects/create-project-modal/avecuseCreateProjectModal, Header, Form, Footer, Skeleton. Stories : Default, Loading. - GoLiveView (fait 2026-02-05) : module
components/studio/go-live-view/avecuseGoLiveView, Header, Preview, StreamInfo, EncoderSetup, QuickInstructions, MicLevel, Skeleton. Stories : Default, Loading. - ConnectivityView (fait 2026-02-05) : module
components/studio/connectivity-view/avecuseConnectivityView, WebDAV, Webhooks, Skeleton. Stories : Default, Loading. - AIToolsView (fait 2026-02-05) : module
components/studio/ai-tools-view/avecuseAIToolsView, 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/avecuseCloudSettingsView, Quota, Preferences, Skeleton. Stories : Default, Loading. - StudioView (fait 2026-02-05) : module
components/views/studio-view/avecuseStudioView, 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/avecusePlaylistList,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 depuisdropdown-menu.tsx. - accordion (fait 2026-02-05) : module
components/ui/accordion/avec types, Accordion, AccordionItem, AccordionTrigger, AccordionContent. Stories : Default, Multiple. Re-export depuisaccordion.tsx. - tabs (fait 2026-02-05) : module
components/ui/tabs/avec types, Tabs, TabsList, TabsTrigger, TabsContent. Stories : Default. Re-export depuistabs.tsx. - tooltip (fait 2026-02-05) : module
components/ui/tooltip/avec useTooltip, TooltipContent, Tooltip. Stories : Default, Positions, ManualTrigger. Re-export depuistooltip.tsx. - AccountSettings (fait 2026-02-05) : module
features/settings/components/account-settings/avecuseAccountSettings, 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 l’illusion applicative (StorybookDecorator)
Ce qui est en place
- Providers centralisés :
I18nextProvider,ThemeProvider,QueryClientProvider,ToastProvider,AudioProvider,AuthProvider,MemoryRouter. - Router :
parameters.router.initialEntriespour les stories dépendant d’une route. - Thème : bascule light/dark via globals Storybook (backgrounds).
- Toasts : en mode Storybook, toasts loggés en console (pas d’affichage 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 l’accessibilité. |
| 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 l’app. |
| 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 appliqueprefers-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 s’assurer que les variables sont bien appliquées dans l’iframe). - 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,tabsont des stylesfocus-visible:ringou équivalent.
Problèmes identifiés
| Criticité | Constat | Détail |
|---|---|---|
| Bloquant | Tests a11y non actifs | Tant que test: 'todo', aucune violation a11y ne fait échouer l’audit 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, n’ont 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 à l’audit (ou au moins au build Storybook) pour faire échouer en cas de violations. - Vérifier les cartes et listes cliquables : soit
<button>oudivavecrole="button",tabIndex={0}, et gestiononKeyDown(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 d’interface | 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 d’espacement/hauteurs documentée ; linter pour limiter les valeurs arbitraires. |
| Perfectionnement | États d’interface | 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
- 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.
- Moyen terme : Découper 2–3 composants “dieux” (ex. CloudFileBrowser, CommentThread) et aligner les nouvelles stories sur les tokens (réduction des valeurs arbitraires).
- Long terme : Documenter une grille de hauteurs/largeurs et une checklist “états d’interface” pour toute nouvelle story ; intégrer reduced-motion et feedback tactile dans le décorateur.
Rapport généré dans le cadre de l’audit frontend Veza — Storybook stabilisé, contrat dans docs/STORYBOOK_CONTRACT.md.