Skip to content

Latest commit

 

History

History
284 lines (223 loc) · 7.95 KB

File metadata and controls

284 lines (223 loc) · 7.95 KB

Twig Components Library

Une bibliothèque de composants Twig headless (sans style) inspirée de Radix UI, avec interactivité Stimulus.

Philosophie

Headless par défaut

Les composants ne contiennent aucun style CSS imposé. Vous gardez le contrôle total sur l'apparence :

  • Utilisez Tailwind, Bootstrap, ou votre propre CSS
  • Appliquez vos classes via l'attribut class
  • Personnalisez avec style inline si nécessaire

Accessibilité intégrée

  • Attributs ARIA automatiques (role, aria-live, aria-label)
  • Navigation au clavier gérée par les controllers Stimulus
  • Sémantique HTML correcte

API déclarative

<twig:Alert:Alert variant="success" dismissible>
  Contenu de l'alerte
</twig:Alert:Alert>

Composants disponibles

Alert

Affiche des messages importants à l'utilisateur.

Props

Prop Type Défaut Description
variant string 'info' Type d'alerte : info, success, warning, error
dismissible bool false Permet de fermer l'alerte
title string null Titre optionnel
icon string null Icône ou emoji à afficher

Exemples

Alerte simple

<twig:Alert:Alert variant="info">
  Votre session expire dans 5 minutes.
</twig:Alert:Alert>

Alerte dismissible

<twig:Alert:Alert variant="success" title="Succès" dismissible>
  Vos modifications ont été enregistrées.
</twig:Alert:Alert>

Avec Tailwind CSS

<twig:Alert:Alert
  variant="error"
  dismissible
  class="bg-red-50 border-l-4 border-red-500 p-4 rounded"
>
  Une erreur s'est produite.
</twig:Alert:Alert>

Data Attributes

Le composant expose ces attributs pour le ciblage CSS :

  • [data-variant="..."] : Le variant de l'alerte
  • [data-alert-title] : Le conteneur du titre
  • [data-alert-content] : Le conteneur du contenu

Events

Le controller Stimulus émet ces événements :

  • alert:dismiss : Avant la fermeture (cancelable)
  • alert:dismissed : Après la fermeture
document.addEventListener('alert:dismissed', (event) => {
  console.log('Alert dismissed:', event.detail.element);
});

Accordion

Composant collapsible pour organiser du contenu en sections pliables.

Props (Accordion)

Prop Type Défaut Description
type string 'single' Mode : single (un seul ouvert) ou multiple (plusieurs ouverts)
collapsible bool true Permet de fermer tous les items en mode single
defaultValue string null Valeur de l'item ouvert par défaut

Props (AccordionItem)

Prop Type Défaut Description
value string auto Identifiant unique de l'item
title string null Titre du bouton déclencheur
disabled bool false Désactive l'item

Exemples

Accordion simple

<twig:Accordion:Accordion type="single">
  <twig:Accordion:AccordionItem value="item1" title="Section 1">
    Contenu de la section 1
  </twig:Accordion:AccordionItem>

  <twig:Accordion:AccordionItem value="item2" title="Section 2">
    Contenu de la section 2
  </twig:Accordion:AccordionItem>
</twig:Accordion:Accordion>

Mode multiple avec item par défaut

<twig:Accordion:Accordion type="multiple" defaultValue="faq1">
  <twig:Accordion:AccordionItem value="faq1" title="Question 1">
    Réponse 1
  </twig:Accordion:AccordionItem>

  <twig:Accordion:AccordionItem value="faq2" title="Question 2">
    Réponse 2
  </twig:Accordion:AccordionItem>
</twig:Accordion:Accordion>

Avec styling personnalisé

<twig:Accordion:Accordion class="space-y-2">
  <twig:Accordion:AccordionItem
    value="styled"
    title="Item stylisé"
    class="border rounded-lg shadow-sm"
  >
    Du contenu stylisé avec vos classes CSS
  </twig:Accordion:AccordionItem>
</twig:Accordion:Accordion>

Navigation clavier

  • / : Naviguer entre les items
  • Home / End : Aller au premier/dernier item
  • Enter / Space : Toggle l'item courant

Data Attributes

  • [data-accordion-item] : Conteneur de l'item
  • [data-accordion-trigger] : Bouton déclencheur
  • [data-accordion-content] : Contenu collapsible
  • [data-accordion-icon] : Icône de l'état (rotatable)

Events

  • accordion:open : Quand un item s'ouvre
  • accordion:close : Quand un item se ferme
document.addEventListener('accordion:open', (event) => {
  console.log('Item opened:', event.detail.value);
});

FormCollection

Gère l'ajout et la suppression dynamique d'éléments dans les collections Symfony.

Props

Prop Type Défaut Description
prototype string null Le prototype HTML du formulaire (généré par Symfony)
addLabel string 'Ajouter' Texte du bouton d'ajout
removeLabel string 'Supprimer' Texte du bouton de suppression
allowAdd bool true Permet d'ajouter des éléments
allowRemove bool true Permet de supprimer des éléments
addButtonClass string '' Classes CSS pour le bouton d'ajout
removeButtonClass string '' Classes CSS pour le bouton de suppression

Utilisation avec Symfony Form

{# Rendre le prototype une seule fois dans une variable #}
{% set emailPrototype %}
    <div style="display: flex; gap: 0.5rem;">
        {{ form_widget(form.emails.vars.prototype) }}
    </div>
{% endset %}

<twig:FormCollection
    prototype="{{ emailPrototype|e('html_attr') }}"
    addLabel="➕ Ajouter un email"
    addButtonClass="btn btn-primary"
>
    {% for emailForm in form.emails %}
        <div data-form-collection-item style="display: flex; gap: 0.5rem;">
            {{ form_widget(emailForm) }}
            {{ form_errors(emailForm) }}
        </div>
    {% endfor %}
</twig:FormCollection>

Important : Le prototype doit être rendu dans une variable avec {% set %} pour éviter l'erreur "Field has already been rendered". Utilisez |e('html_attr') pour l'échapper correctement.

Utilisation sans Symfony Form

Utilisation directe avec les helpers Stimulus :

<div
    {{ stimulus_controller('form-collection') }}
    data-form-collection-prototype-value="{{ '<div><input name=&quot;items[__name__]&quot; /></div>' }}"
    data-form-collection-index-value="1"
>
    <div {{ stimulus_target('form-collection', 'container') }}>
        <div data-form-collection-item>
            <input name="items[0]" />
            <button {{ stimulus_action('form-collection', 'remove') }}>Supprimer</button>
        </div>
    </div>
    <button {{ stimulus_action('form-collection', 'add') }}>Ajouter</button>
</div>

Events

  • form-collection:item-added : Quand un élément est ajouté
  • form-collection:item-removed : Quand un élément est supprimé
  • form-collection:before-remove : Avant la suppression (cancelable)
document.addEventListener('form-collection:item-added', (event) => {
    console.log('Nouvel élément:', event.detail.element);
});

Features

  • ✅ Gestion automatique des indices (__name__)
  • ✅ Animation de suppression
  • ✅ Scroll automatique vers le nouvel élément
  • ✅ Support des formulaires imbriqués
  • ✅ Events personnalisables

Prochains composants

  • Accordion
  • FormCollection
  • Dialog / Modal
  • Dropdown
  • Tabs
  • Tooltip
  • Badge
  • Card

Architecture

src/Twig/Components/       # Classes PHP des composants
templates/components/      # Templates Twig
assets/controllers/        # Controllers Stimulus

Conventions

Nommage

  • Composants : PascalCase (Alert, Accordion)
  • Props : camelCase (dismissible, variant)
  • Events : kebab-case (alert:dismiss)

Props communes

Tous les composants acceptent :

  • class : Classes CSS personnalisées
  • style : Styles inline
  • id : ID HTML
  • Tout autre attribut HTML via {{ attributes }}