Skip to content

Latest commit

 

History

History
937 lines (710 loc) · 15.6 KB

File metadata and controls

937 lines (710 loc) · 15.6 KB

Bibliothèque de composants

Vue d'ensemble

Cette bibliothèque décrit tous les composants UI réutilisables de l'application, leurs props, leurs variantes et leurs cas d'usage.

Composants de base

Button (Bouton)

Bouton principal de l'application avec plusieurs variantes.

Props

interface ButtonProps {
  children: React.ReactNode;
  variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger';
  size?: 'sm' | 'md' | 'lg';
  icon?: string; // Nom de l'icône Font Awesome
  iconPosition?: 'left' | 'right';
  disabled?: boolean;
  loading?: boolean;
  fullWidth?: boolean;
  onClick?: () => void;
  type?: 'button' | 'submit' | 'reset';
  className?: string;
}

Variantes

  • primary : Bouton principal (fond vert, texte blanc)
  • secondary : Bouton secondaire (fond gris, texte foncé)
  • outline : Bouton avec bordure (fond transparent, bordure verte)
  • ghost : Bouton sans bordure (fond transparent au hover)
  • danger : Bouton de danger (fond rouge, texte blanc)

Tailles

  • sm : Petit (h: 32px, padding: 8px 16px)
  • md : Moyen (h: 40px, padding: 10px 20px) - Par défaut
  • lg : Grand (h: 48px, padding: 12px 24px)

Exemple

<Button variant="primary" size="md" icon="fa-save" iconPosition="left">
  Enregistrer
</Button>

Input (Champ de saisie)

Champ de saisie de texte avec validation.

Props

interface InputProps {
  label?: string;
  name: string;
  type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'date';
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  required?: boolean;
  disabled?: boolean;
  error?: string;
  helperText?: string;
  icon?: string;
  iconPosition?: 'left' | 'right';
  className?: string;
}

Exemple

<Input
  label="Email"
  name="email"
  type="email"
  value={email}
  onChange={setEmail}
  required
  error={errors.email}
  helperText="Votre adresse email"
/>

Select (Sélection)

Liste déroulante de sélection.

Props

interface SelectProps {
  label?: string;
  name: string;
  value: string;
  onChange: (value: string) => void;
  options: { value: string; label: string }[];
  placeholder?: string;
  required?: boolean;
  disabled?: boolean;
  error?: string;
  helperText?: string;
  className?: string;
}

Exemple

<Select
  label="Rôle"
  name="role"
  value={role}
  onChange={setRole}
  options={[
    { value: 'teacher', label: 'Professeur' },
    { value: 'student', label: 'Élève' }
  ]}
  required
/>

Textarea (Zone de texte)

Zone de texte multi-lignes.

Props

interface TextareaProps {
  label?: string;
  name: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  rows?: number;
  required?: boolean;
  disabled?: boolean;
  error?: string;
  helperText?: string;
  className?: string;
}

Checkbox (Case à cocher)

Case à cocher pour sélections multiples.

Props

interface CheckboxProps {
  label: string;
  name: string;
  checked: boolean;
  onChange: (checked: boolean) => void;
  disabled?: boolean;
  error?: string;
  className?: string;
}

Radio (Bouton radio)

Bouton radio pour sélection unique.

Props

interface RadioProps {
  label: string;
  name: string;
  value: string;
  checked: boolean;
  onChange: (value: string) => void;
  disabled?: boolean;
  className?: string;
}

Modal (Fenêtre modale)

Fenêtre modale pour afficher du contenu par-dessus la page.

Props

interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  title?: string;
  children: React.ReactNode;
  size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
  showCloseButton?: boolean;
  footer?: React.ReactNode;
  className?: string;
}

Caractéristiques

  • Overlay sombre avec opacité
  • Classe CSS modal-content sur le contenu (selon mémoire)
  • Fermeture par clic sur overlay ou bouton X
  • Animation d'ouverture/fermeture

Exemple

<Modal
  isOpen={isOpen}
  onClose={handleClose}
  title="Confirmer la suppression"
  size="md"
>
  <p>Êtes-vous sûr de vouloir supprimer cet élément ?</p>
  <div className="flex gap-4 mt-4">
    <Button variant="primary" onClick={handleConfirm}>Confirmer</Button>
    <Button variant="secondary" onClick={handleClose}>Annuler</Button>
  </div>
</Modal>

Table (Tableau)

Tableau avec tri, pagination et filtres.

Props

interface TableProps<T> {
  data: T[];
  columns: Column<T>[];
  onRowClick?: (row: T) => void;
  sortable?: boolean;
  pagination?: {
    page: number;
    pageSize: number;
    total: number;
    onPageChange: (page: number) => void;
  };
  loading?: boolean;
  emptyMessage?: string;
  className?: string;
}

interface Column<T> {
  key: keyof T | string;
  header: string;
  render?: (value: any, row: T) => React.ReactNode;
  sortable?: boolean;
  width?: string;
}

Exemple

<Table
  data={students}
  columns={[
    { key: 'firstName', header: 'Prénom', sortable: true },
    { key: 'lastName', header: 'Nom', sortable: true },
    { key: 'email', header: 'Email' },
    {
      key: 'status',
      header: 'Statut',
      render: (value) => <Badge status={value} />
    }
  ]}
  pagination={{
    page: 1,
    pageSize: 20,
    total: 100,
    onPageChange: setPage
  }}
/>

Card (Carte)

Carte pour afficher du contenu groupé.

Props

interface CardProps {
  children: React.ReactNode;
  title?: string;
  subtitle?: string;
  header?: React.ReactNode;
  footer?: React.ReactNode;
  hover?: boolean;
  onClick?: () => void;
  className?: string;
}

Exemple

<Card
  title="Violon Débutant"
  subtitle="Cours collectif - 10 élèves"
  hover
  onClick={handleClick}
>
  <p>Description du cours...</p>
</Card>

Badge (Badge)

Badge pour afficher des statuts ou labels.

Props

interface BadgeProps {
  children: React.ReactNode;
  variant?: 'primary' | 'success' | 'warning' | 'error' | 'info' | 'gray';
  size?: 'sm' | 'md';
  className?: string;
}

Exemple

<Badge variant="success">Actif</Badge>
<Badge variant="warning">En attente</Badge>
<Badge variant="error">Annulé</Badge>

Alert (Alerte)

Message d'alerte pour informer l'utilisateur.

Props

interface AlertProps {
  children: React.ReactNode;
  variant?: 'success' | 'error' | 'warning' | 'info';
  title?: string;
  icon?: string;
  onClose?: () => void;
  className?: string;
}

Exemple

<Alert variant="success" title="Succès" onClose={handleClose}>
  L'élève a été créé avec succès.
</Alert>

Toast (Notification)

Notification toast pour les actions rapides.

Props

interface ToastProps {
  message: string;
  variant?: 'success' | 'error' | 'warning' | 'info';
  icon?: string;
  duration?: number;
  onClose?: () => void;
}

Note : Selon la mémoire, les toasts doivent avoir le background comme la variante 50 de la couleur et l'icône doit correspondre à la couleur de la bordure (ex: green-50 background, green-600 icon).


Dropdown (Menu déroulant)

Menu déroulant pour actions contextuelles.

Props

interface DropdownProps {
  trigger: React.ReactNode;
  items: DropdownItem[];
  align?: 'left' | 'right';
  className?: string;
}

interface DropdownItem {
  label: string;
  icon?: string;
  onClick: () => void;
  disabled?: boolean;
  divider?: boolean;
}

Tabs (Onglets)

Onglets pour organiser le contenu.

Props

interface TabsProps {
  tabs: Tab[];
  activeTab: string;
  onChange: (tabId: string) => void;
  className?: string;
}

interface Tab {
  id: string;
  label: string;
  icon?: string;
  content: React.ReactNode;
}

Calendar (Calendrier)

Composant calendrier réutilisable.

Voir la section "Composants métier" ci-dessous.


Composants métier

Calendar (Calendrier)

Calendrier avec vues jour/semaine/mois.

Props

interface CalendarProps {
  view: 'day' | 'week' | 'month';
  date: Date;
  onDateChange: (date: Date) => void;
  events: CalendarEvent[];
  onEventClick?: (event: CalendarEvent) => void;
  onEventCreate?: (date: Date, time: string) => void;
  filters?: {
    teacherId?: string;
    studentId?: string;
    roomId?: string;
  };
  className?: string;
}

interface CalendarEvent {
  id: string;
  title: string;
  start: Date;
  end: Date;
  type: 'lesson' | 'course' | 'workshop' | 'rehearsal';
  color?: string;
  data?: any; // Données supplémentaires
}

Fonctionnalités

  • Vue jour, semaine, mois
  • Drag & drop pour déplacer les événements
  • Création d'événement par clic
  • Filtres par professeur, élève, salle
  • Indicateurs visuels pour les conflits

StudentCard (Carte élève)

Carte affichant les informations d'un élève.

Props

interface StudentCardProps {
  student: Student;
  onClick?: () => void;
  showActions?: boolean;
  className?: string;
}

TeacherCard (Carte professeur)

Carte affichant les informations d'un professeur.

Props

interface TeacherCardProps {
  teacher: Teacher;
  onClick?: () => void;
  showActions?: boolean;
  className?: string;
}

InstrumentCard (Carte instrument)

Carte affichant un instrument avec son icône.

Props

interface InstrumentCardProps {
  instrument: Instrument;
  onClick?: () => void;
  showAvailability?: boolean;
  className?: string;
}

EnrollmentForm (Formulaire d'inscription)

Formulaire multi-étapes pour l'inscription.

Props

interface EnrollmentFormProps {
  studentId?: string;
  onSubmit: (enrollment: Enrollment) => void;
  onCancel?: () => void;
}

Étapes

  1. Informations élève
  2. Sélection des cours
  3. Plan de paiement
  4. Documents
  5. Confirmation

DocumentUploader (Upload de documents)

Composant pour uploader des documents.

Props

interface DocumentUploaderProps {
  onUpload: (file: File) => Promise<void>;
  accept?: string;
  maxSize?: number; // En MB
  multiple?: boolean;
  className?: string;
}

PaymentSchedule (Échéancier de paiement)

Affichage de l'échéancier de paiement.

Props

interface PaymentScheduleProps {
  installments: PaymentInstallment[];
  onPaymentClick?: (installment: PaymentInstallment) => void;
  className?: string;
}

Layouts

PageLayout (Layout de page)

Layout standard pour les pages.

Props

interface PageLayoutProps {
  title: string;
  subtitle?: string;
  actions?: React.ReactNode;
  children: React.ReactNode;
  breadcrumbs?: Breadcrumb[];
}

DashboardLayout (Layout dashboard)

Layout pour les tableaux de bord.

Props

interface DashboardLayoutProps {
  children: React.ReactNode;
  sidebar?: React.ReactNode;
  header?: React.ReactNode;
}

Navigation

Sidebar (Barre latérale)

Navigation latérale principale.

Props

interface SidebarProps {
  items: SidebarItem[];
  activeItem?: string;
  onItemClick?: (item: SidebarItem) => void;
  collapsed?: boolean;
  onToggleCollapse?: () => void;
}

interface SidebarItem {
  id: string;
  label: string;
  icon: string;
  path: string;
  badge?: number;
  children?: SidebarItem[];
}

Header (En-tête)

En-tête de l'application.

Props

interface HeaderProps {
  user: User;
  onLogout?: () => void;
  onProfileClick?: () => void;
  notifications?: Notification[];
}

Utilitaires

LoadingSpinner (Indicateur de chargement)

Spinner de chargement.

Props

interface LoadingSpinnerProps {
  size?: 'sm' | 'md' | 'lg';
  className?: string;
}

LoadingState (État de chargement)

Composant pour afficher un état de chargement avec spinner et texte.

Props

interface LoadingStateProps {
  text?: string;
  size?: 'sm' | 'md' | 'lg' | 'xl';
  fullScreen?: boolean;
  className?: string;
}

Exemple

<LoadingState text="Chargement des données..." size="md" />
<LoadingState text="Chargement..." fullScreen />

EmptyState (État vide)

Affichage quand il n'y a pas de données. Supporte deux variantes : default et card.

Props

interface EmptyStateProps {
  icon?: string; // Nom de l'icône Font Awesome (ex: 'fa-user-graduate')
  title: string;
  description?: string;
  action?: {
    label: string;
    onClick: () => void;
    icon?: string;
  };
  variant?: 'default' | 'card';
  children?: ReactNode;
  className?: string;
}

Variantes

  • default : Affichage centré avec grande icône
  • card : Affichage dans une carte avec icône dans conteneur arrondi

Exemple

<EmptyState
  icon="fa-user-graduate"
  title="Aucun élève trouvé"
  description="Commencez par ajouter un élève"
  variant="card"
/>

<EmptyState
  icon="fa-inbox"
  title="Aucune donnée"
  description="Il n'y a pas encore de données"
  action={{
    label: "Ajouter",
    onClick: handleAdd,
    icon: "fa-plus"
  }}
/>

SectionHeader (En-tête de section)

Composant pour standardiser les en-têtes de section avec titre, sous-titre et actions.

Props

interface SectionHeaderProps {
  title: string;
  subtitle?: string;
  actions?: ReactNode;
  className?: string;
}

Exemple

<SectionHeader
  title="Gestion des élèves"
  subtitle="Gérez tous les élèves du conservatoire"
  actions={<Button>Ajouter</Button>}
/>

CardContainer (Conteneur de carte)

Composant pour créer des conteneurs de cartes avec style uniforme.

Props

interface CardContainerProps extends HTMLAttributes<HTMLDivElement> {
  children: ReactNode;
  padding?: 'none' | 'sm' | 'md' | 'lg';
  shadow?: 'none' | 'sm' | 'md' | 'lg';
  className?: string;
}

Exemple

<CardContainer padding="md" shadow="md">
  <h3>Titre</h3>
  <p>Contenu</p>
</CardContainer>

Scrollbar (Barre de défilement)

Composant wrapper pour appliquer un style uniforme aux barres de défilement.

Props

interface ScrollbarProps extends HTMLAttributes<HTMLDivElement> {
  children: ReactNode;
  direction?: 'vertical' | 'horizontal' | 'both';
  className?: string;
}

Exemple

<Scrollbar direction="vertical" className="max-h-64">
  <div>Contenu scrollable</div>
</Scrollbar>

<Scrollbar direction="horizontal">
  <table>Table large</table>
</Scrollbar>

SearchBar (Barre de recherche)

Barre de recherche avec filtres.

Props

interface SearchBarProps {
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  filters?: Filter[];
  onFilterChange?: (filters: Record<string, any>) => void;
  className?: string;
}

Patterns d'utilisation

Formulaires

Utiliser React Hook Form pour la gestion des formulaires :

const { register, handleSubmit, formState: { errors } } = useForm();

<form onSubmit={handleSubmit(onSubmit)}>
  <Input
    label="Email"
    {...register('email', { required: true })}
    error={errors.email?.message}
  />
  <Button type="submit">Envoyer</Button>
</form>

Listes avec pagination

<Table
  data={items}
  columns={columns}
  pagination={{
    page: currentPage,
    pageSize: 20,
    total: totalItems,
    onPageChange: setCurrentPage
  }}
/>

Modals avec formulaires

<Modal isOpen={isOpen} onClose={onClose} title="Créer un élève">
  <form onSubmit={handleSubmit}>
    {/* Champs du formulaire */}
  </form>
</Modal>