{# # ============================================================================ # MOLECULE: TABS # ============================================================================ # # Système d'onglets pour organiser le contenu en sections. # Fonctionne en JS vanilla pour le changement d'onglet. # # ============================================================================ # COMPOSITION (Atomes utilisés) # ============================================================================ # # - _atoms/icon/icon.html.twig # - _atoms/badge/badge.html.twig # # ============================================================================ # PARAMÈTRES # ============================================================================ # # | Paramètre | Type | Défaut | Description | # |---------------|---------|------------|-----------------------------------| # | tabs | array | (requis) | Liste des onglets | # | └ id | string | (requis) | Identifiant unique de l'onglet | # | └ label | string | (requis) | Texte de l'onglet | # | └ icon | string | null | Icône de l'onglet | # | └ badge | string | null | Badge (ex: compteur) | # | └ disabled | bool | false | Désactive l'onglet | # | └ right | bool | false | Aligne l'onglet à droite | # | active | string | premier | ID de l'onglet actif | # | variant | string | 'default' | default, pills, underline, settings| # | size | string | 'md' | sm, md, lg | # | fullWidth | bool | false | Onglets en pleine largeur | # | class | string | '' | Classes additionnelles | # | id | string | auto | ID du conteneur | # # ============================================================================ # EXEMPLES D'UTILISATION # ============================================================================ # # Tabs simple: # {% include '_molecules/tabs/tabs.html.twig' with { # tabs: [ # { id: 'tab1', label: 'Général' }, # { id: 'tab2', label: 'Paramètres' }, # { id: 'tab3', label: 'Avancé' } # ] # } %} # # Avec icônes et badges: # {% include '_molecules/tabs/tabs.html.twig' with { # tabs: [ # { id: 'inbox', label: 'Inbox', icon: 'inbox', badge: '5' }, # { id: 'sent', label: 'Envoyés', icon: 'send' }, # { id: 'trash', label: 'Corbeille', icon: 'trash', disabled: true } # ], # active: 'inbox', # variant: 'pills' # } %} # # ============================================================================ #} {# ============================================================================ CONFIGURATION DES VALEURS PAR DÉFAUT ============================================================================ #} {% set tabs = tabs ?? [] %} {% set active = active ?? (tabs|first).id ?? null %} {% set variant = variant ?? 'default' %} {% set size = size ?? 'md' %} {% set fullWidth = fullWidth ?? false %} {% set borderless = borderless ?? false %} {% set class = class ?? '' %} {% set id = id ?? 'tabs-' ~ random() %} {# ============================================================================ CLASSES TAILWIND ============================================================================ #} {% set sizeConfig = { 'sm': { 'padding': 'px-3 py-1.5', 'text': 'text-xs', 'gap': 'gap-1.5', 'iconSize': 'sm' }, 'md': { 'padding': 'px-4 py-2', 'text': 'text-sm', 'gap': 'gap-2', 'iconSize': 'md' }, 'lg': { 'padding': 'px-5 py-2.5', 'text': 'text-base', 'gap': 'gap-2.5', 'iconSize': 'md' } } %} {% set variantConfig = { 'default': { 'container': 'border-b border-gray-200', 'list': 'flex gap-0 -mb-px', 'tab': 'border-b-2 border-transparent hover:border-gray-300 hover:text-gray-700', 'active': 'border-b-2 border-primary text-primary', 'disabled': 'opacity-50 cursor-not-allowed', 'iconFilter': false }, 'pills': { 'container': '', 'list': 'flex gap-1 p-1 bg-gray-100 rounded-lg', 'tab': 'rounded-md hover:bg-gray-200 text-gray-600', 'active': 'bg-white text-gray-900 shadow-sm', 'disabled': 'opacity-50 cursor-not-allowed', 'iconFilter': false }, 'underline': { 'container': '', 'list': 'flex gap-4', 'tab': 'border-b-2 border-transparent hover:text-primary', 'active': 'border-b-2 border-primary text-primary font-medium', 'disabled': 'opacity-50 cursor-not-allowed', 'iconFilter': false }, 'settings': { 'container': 'border-b-2 border-primary/10', 'list': 'flex gap-8 -mb-0.5 overflow-x-auto scrollbar-hide', 'tab': 'border-b-[3px] border-transparent text-gray-500 hover:text-primary pb-4', 'active': 'border-b-[3px] border-primary text-primary font-semibold pb-4', 'disabled': 'opacity-50 cursor-not-allowed pointer-events-none', 'iconFilter': true } } %} {% set sConfig = sizeConfig[size] ?? sizeConfig['md'] %} {% set vConfig = variantConfig[variant] ?? variantConfig['default'] %} {# ============================================================================ RENDU HTML ============================================================================ #}