{# # ============================================================================ # MOLECULE: CARD # ============================================================================ # # Conteneur flexible avec header, body et footer optionnels. # Molécule fondamentale pour afficher du contenu structuré. # # ============================================================================ # COMPOSITION (Atomes utilisés) # ============================================================================ # # - _atoms/typography/typography.html.twig (titres) # - _atoms/icon/icon.html.twig (icône header) # - _atoms/button/button.html.twig (actions) # # ============================================================================ # PARAMÈTRES # ============================================================================ # # | Paramètre | Type | Défaut | Description | # |----------------|---------|-----------|------------------------------------------| # | title | string | null | Titre du header | # | subtitle | string | null | Sous-titre du header | # | description | string | null | Description (pour mode action) | # | icon | string | null | Icône du header (nom) | # | iconColor | string | 'primary' | Couleur de l'icône | # | status | string | null | Statut: available, locked, coming | # | badge | string | null | Badge texte (Nouveau, À venir...) | # | headerAction | block | null | Slot pour action dans le header | # | footer | block | null | Slot pour le footer | # | variant | string | 'default' | Style: default, elevated, bordered, flat | # | padding | string | 'md' | Padding du body: none, sm, md, lg | # | href | string | null | Rend la card cliquable | # | hover | bool | false | Effet hover (auto si href) | # | fullHeight | bool | false | Étirer la card verticalement (h-full) | # | collapsible | bool | false | Rend le body pliable (clic sur header) | # | collapsed | bool | false | État initial fermé (si collapsible) | # | class | string | '' | Classes additionnelles | # # ============================================================================ # EXEMPLES D'UTILISATION # ============================================================================ # # Card simple: # {% embed '_molecules/card/card.html.twig' with { title: 'Mon titre' } %} # {% block body %} #
Contenu de la card
# {% endblock %} # {% endembed %} # # Card avec footer: # {% embed '_molecules/card/card.html.twig' with { title: 'Utilisateur', icon: 'user' } %} # {% block body %} #Informations utilisateur
# {% endblock %} # {% block footer %} # # {% endblock %} # {% endembed %} # # Card Mode Action (quick-action style): # {% embed '_molecules/card/card.html.twig' with { # title: 'Créer un cours', # description: 'Générez un cours depuis un PDF', # icon: 'bubul-moodia', # iconColor: 'moodia', # status: 'available', # href: '/moodia' # } %}{% endembed %} # # ============================================================================ #} {# ============================================================================ CONFIGURATION DES VALEURS PAR DÉFAUT ============================================================================ #} {% set title = title ?? null %} {% set subtitle = subtitle ?? null %} {% set description = description ?? null %} {% set icon = icon ?? null %} {% set iconColor = iconColor ?? 'primary' %} {% set status = status ?? null %} {% set badge = badge ?? null %} {% set variant = variant ?? 'default' %} {% set padding = padding ?? 'md' %} {% set href = href ?? null %} {% set hover = hover ?? (href is not null) %} {% set fullHeight = fullHeight ?? false %} {% set collapsible = collapsible ?? false %} {% set collapsed = collapsed ?? false %} {% set collapsibleGroup = collapsibleGroup ?? '' %} {% set overflowHidden = overflowHidden ?? false %} {% set class = class ?? '' %} {# Mode Action = quand status est défini (style quick-action) #} {% set isActionMode = status is not null %} {# Status configuration #} {% set statusConfig = { 'available': { 'badge': null, 'icon': 'chevron-right', 'opacity': '', 'interactive': true }, 'locked': { 'badge': null, 'icon': 'lock', 'opacity': 'opacity-75', 'interactive': false }, 'coming': { 'badge': badge ?? 'À venir', 'icon': null, 'opacity': 'opacity-75', 'interactive': false } } %} {% set sStatus = status ? (statusConfig[status] ?? statusConfig['available']) : null %} {# Est-ce que la card est interactive ? #} {% set isInteractive = href is not null and (not sStatus or sStatus.interactive) %} {# ============================================================================ CLASSES TAILWIND ============================================================================ #} {% set variantClasses = { 'default': 'bg-white border border-gray-200 shadow-sm', 'elevated': 'bg-white border border-gray-100 shadow-md', 'bordered': 'bg-white border-2 border-gray-200', 'flat': 'bg-gray-50 border border-gray-100' } %} {% set paddingClasses = { 'none': '', 'sm': 'p-4', 'md': 'p-6', 'lg': 'p-8' } %} {# Hover classes selon le mode #} {% if isActionMode and isInteractive %} {% set hoverClasses = 'group hover:-translate-y-1 hover:shadow-[0_12px_32px_rgba(12,129,228,0.15)] hover:border-primary transition-all duration-300 cursor-pointer' %} {% elseif hover %} {% set hoverClasses = 'hover:shadow-md hover:border-gray-300 transition-all cursor-pointer' %} {% else %} {% set hoverClasses = '' %} {% endif %} {# Classes du conteneur #} {% set cardClasses = [ 'rounded-2xl relative' ~ (overflowHidden ? ' overflow-hidden' : ''), isActionMode ? 'border border-primary/10 bg-white shadow-sm' : variantClasses[variant] ?? variantClasses['default'], hoverClasses, sStatus ? sStatus.opacity : '', fullHeight ? 'h-full flex flex-col' : '', class ]|join(' ')|trim %} {# ============================================================================ RENDU HTML ============================================================================ #} {% set cardTag = href ? 'a' : 'div' %} <{{ cardTag }} {% if href and isInteractive %} href="{{ href }}"{% endif %} class="{{ cardClasses }}" {% if collapsible %} data-controller="shared--collapsible" data-shared--collapsible-open-value="{{ collapsed ? 'false' : 'true' }}" {% if collapsibleGroup %}data-shared--collapsible-group-value="{{ collapsibleGroup }}"{% endif %} {% endif %} > {# Overlay gradient au hover (Mode Action uniquement) #} {% if isActionMode and isInteractive %} {% endif %} {# ----- Mode Action (quick-action style) ----- #} {% if isActionMode %}{{ description }}
{% endif %}{{ subtitle }}
{% endif %} {% if description %}{{ description }}
{% endif %}