From 846d19b064fca06c1f98ceadd6cc9afe79d8d8ee Mon Sep 17 00:00:00 2001 From: Benoit VIGNAL Date: Tue, 31 Mar 2026 10:19:18 +0200 Subject: [PATCH 1/7] Add sf components docs --- source/devapi/index.rst | 1 + source/devapi/symfonycomponents/index.rst | 4 ++++ source/sourcecode.rst | 4 ++++ 3 files changed, 9 insertions(+) create mode 100644 source/devapi/symfonycomponents/index.rst diff --git a/source/devapi/index.rst b/source/devapi/index.rst index 8def254..a5b3fc1 100644 --- a/source/devapi/index.rst +++ b/source/devapi/index.rst @@ -10,6 +10,7 @@ Apart from the current documentation, you can also generate the full PHP documen database/index search controllers + symfonycomponents/index hlapi/index massiveactions rules diff --git a/source/devapi/symfonycomponents/index.rst b/source/devapi/symfonycomponents/index.rst new file mode 100644 index 0000000..ca8dd97 --- /dev/null +++ b/source/devapi/symfonycomponents/index.rst @@ -0,0 +1,4 @@ +Symfony Twig Components +------------ + +Salut diff --git a/source/sourcecode.rst b/source/sourcecode.rst index b2b45b4..54aa455 100644 --- a/source/sourcecode.rst +++ b/source/sourcecode.rst @@ -131,7 +131,11 @@ This is a brief description of GLPI main folders and files: * |phpfile| `*.php`: Classes * |folder| `stubs` + * |folder| `templates`: Twig templates files + + * |folder| `twig_components`: Symfony Twig Components (`see documentation `_) + * |folder| `tests`: unit and integration tests * |folder| `tools`: a bunch of tools * |folder| `version`: Current version for internal use From 1e63be19790037bc2331cbbbe1b6a612d5758732 Mon Sep 17 00:00:00 2001 From: Benoit VIGNAL Date: Tue, 31 Mar 2026 11:11:02 +0200 Subject: [PATCH 2/7] Start adding alert doc --- .editorconfig | 26 ++++++++++++++++++ source/devapi/symfonycomponents/alert.rst | 9 +++++++ source/devapi/symfonycomponents/index.rst | 33 +++++++++++++++++++++-- 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 .editorconfig create mode 100644 source/devapi/symfonycomponents/alert.rst diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..bbdf004 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,26 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 4 + +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false +insert_final_newline = false + +[*.{yaml,yml}] +indent_size = 2 +trim_trailing_whitespace = false + +# Makefile must be tab indented +[Makefile] +indent_style = tab diff --git a/source/devapi/symfonycomponents/alert.rst b/source/devapi/symfonycomponents/alert.rst new file mode 100644 index 0000000..da3bed7 --- /dev/null +++ b/source/devapi/symfonycomponents/alert.rst @@ -0,0 +1,9 @@ +Alert +===== + +This is the first component + +Subtitle +^^^^^^^^^^^^^ + +asd diff --git a/source/devapi/symfonycomponents/index.rst b/source/devapi/symfonycomponents/index.rst index ca8dd97..940cafd 100644 --- a/source/devapi/symfonycomponents/index.rst +++ b/source/devapi/symfonycomponents/index.rst @@ -1,4 +1,33 @@ Symfony Twig Components ------------- +======================= -Salut +.. versionadded:: 12.0 + +Twig Components is a `Symfony UX bundle `_ giving us the possibility to configure component in PHP. + +It also enable a cleaner integration and `vuejs` like integration making it easier to maintain and review (compared to the old macro integration). + +Following components are available: + +.. toctree:: + :maxdepth: 1 + + alert + +Recommended usage +^^^^^^^^^^^^^^^^^ + +Twig component support various integration mode, we recommend the following one: + +.. code-block:: twig + + + +It exist a `component` twig method, this usage is not advise and should be use for rare case as it's less readable and less flexible (no block overload, visually blending with other twig method). + +.. code-block:: twig + + {{ component('Alert', { + type: 'warning', + title: __('The Legacy API is enabled. It is recommended to only use the new API when possible.') + }) }} From fcc0e6066f1817ee0f6d790b80afbee9fb55faef Mon Sep 17 00:00:00 2001 From: Benoit VIGNAL Date: Tue, 31 Mar 2026 12:29:41 +0200 Subject: [PATCH 3/7] Adding Alert documentation --- .../images/symfonycomponents/alert-1.png | Bin 0 -> 4186 bytes .../symfonycomponents/alert-custom-block.png | Bin 0 -> 16275 bytes source/devapi/symfonycomponents/alert.rst | 54 ++++++++++++++-- source/devapi/symfonycomponents/index.rst | 59 ++++++++++++++++-- 4 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 source/_static/images/symfonycomponents/alert-1.png create mode 100644 source/_static/images/symfonycomponents/alert-custom-block.png diff --git a/source/_static/images/symfonycomponents/alert-1.png b/source/_static/images/symfonycomponents/alert-1.png new file mode 100644 index 0000000000000000000000000000000000000000..af804fddf1d9bbccdffd4cd44d90d818c6c020c6 GIT binary patch literal 4186 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

?0q-)gHOyo3|CbJK2AcWDzlhscOVVlv zzX)wZK6q7kk=j`{oG)2C-0)|d3Gj1Y{Mz&Cy~{3of~^C@pl6G)*Ml{$5@Y@_bSBjpz-H058nvPb{`N!YPb? zrUVM4vbFSV{Df10O4~J>IiCcTlfWq`7h@151$h!wyPLQ=02NPqmgb8rw3_nt<>^dE zjXnIFnLBLvI}__ZZ}fP4Bm{8WpxQh2n&Z{w?r(G#?auXTkX0#;Z0xh8qT`E+{!1vcTZ z^=pY^*H?Gx+Kx)tjOn;D)Cb0QETa7;Cuf<F#^Ax}iC5V1yym;Z5*`FgP@$_**. Message content, a list can be passed. + +* :code:`icon` **string**. CSS icon class, for example :code:`ti ti-info-circle`. + + * If not defined, it will be calculated based on the alert type. + +* :code:`important` **bool**. False by default, highlight the alert. + +Blocks +------ + +title +^^^^^ +Completely override the title field. Even the `

` field + +content +^^^^^^^ +Completely override the message field. + + +.. code-block:: twig + + +

+ We can also be more like a vue/nuxt component +

+
+ +
+ My content custom alert content +
+
+ +Variants +-------- diff --git a/source/devapi/symfonycomponents/index.rst b/source/devapi/symfonycomponents/index.rst index 940cafd..cab7d6f 100644 --- a/source/devapi/symfonycomponents/index.rst +++ b/source/devapi/symfonycomponents/index.rst @@ -5,7 +5,7 @@ Symfony Twig Components Twig Components is a `Symfony UX bundle `_ giving us the possibility to configure component in PHP. -It also enable a cleaner integration and `vuejs` like integration making it easier to maintain and review (compared to the old macro integration). +It also enable a cleaner integration and :code:`vuejs` like integration making it easier to maintain and review (compared to the old macro integration). Following components are available: @@ -14,20 +14,69 @@ Following components are available: alert -Recommended usage -^^^^^^^^^^^^^^^^^ +Usage +----- +Twig component support various integration mode, we recommend using the **Component HTML Syntax** + + +Component HTML Syntax +^^^^^^^^^^^^^^^^^^^^^ + +`Symfony Documentation `_ -Twig component support various integration mode, we recommend the following one: .. code-block:: twig +Using this syntax ressemble a lot like modern frontend framework. + +For example, if you want to pass variables, boolean or array you can do a twig block like the following + +.. code-block:: twig + + + +

+ Custom title block +

+ {{ parent() }} -- Injecting parent datas (here will be `Overridden tittle`) +
+
+ +Most of the component also have support the default block that should be named :code:`{% block content %}` inside the twig template. + +To inject data into it, you just avec to set data inside the block. + +.. code-block:: twig + + + +

+ Custom title block +

+
+ +
+ My alert content +
+
+ +.. image:: /_static/images/symfonycomponents/alert-custom-block.png + :alt: Example with custom twig block + + + +Component Twig Syntax +^^^^^^^^^^^^^^^^^^^^^ + It exist a `component` twig method, this usage is not advise and should be use for rare case as it's less readable and less flexible (no block overload, visually blending with other twig method). .. code-block:: twig {{ component('Alert', { type: 'warning', - title: __('The Legacy API is enabled. It is recommended to only use the new API when possible.') + title: __('My alert title.') }) }} + +In the components documentation we will not display this integration mode. From e07faa55ce0e999a1cb0e4ada46d2cd8bc30e637 Mon Sep 17 00:00:00 2001 From: Benoit VIGNAL Date: Tue, 31 Mar 2026 14:01:16 +0200 Subject: [PATCH 4/7] Adding Alert documentation --- .../symfonycomponents/alert-variants.png | Bin 0 -> 23292 bytes source/devapi/symfonycomponents/alert.rst | 31 ++++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 source/_static/images/symfonycomponents/alert-variants.png diff --git a/source/_static/images/symfonycomponents/alert-variants.png b/source/_static/images/symfonycomponents/alert-variants.png new file mode 100644 index 0000000000000000000000000000000000000000..e13f64cc72e246fa29412dc3696ff1179f9f8353 GIT binary patch literal 23292 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 literal 0 HcmV?d00001 diff --git a/source/devapi/symfonycomponents/alert.rst b/source/devapi/symfonycomponents/alert.rst index b0582ed..043176a 100644 --- a/source/devapi/symfonycomponents/alert.rst +++ b/source/devapi/symfonycomponents/alert.rst @@ -37,19 +37,36 @@ content ^^^^^^^ Completely override the message field. - .. code-block:: twig - + + -

- We can also be more like a vue/nuxt component -

+

+ Custom title block +

- My content custom alert content + My alert content
-
+ + +.. image:: /_static/images/symfonycomponents/alert-custom-block.png + :alt: Example with custom twig block Variants -------- +Multiple variation of the Alert exist, you can find the listed options here: + +.. code-block:: twig + + Success alert + Info alert + Warning alert + Danger alert + + Main alert + Main alert with type danger + +.. image:: /_static/images/symfonycomponents/alert-variants.png + :alt: Alert variants From b10186b08069ff1c814c61a1409caa66b1245847 Mon Sep 17 00:00:00 2001 From: Benoit VIGNAL Date: Tue, 31 Mar 2026 14:08:14 +0200 Subject: [PATCH 5/7] Text improvements --- source/devapi/symfonycomponents/alert.rst | 22 ++++++++++-------- source/devapi/symfonycomponents/index.rst | 27 ++++++++++------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/source/devapi/symfonycomponents/alert.rst b/source/devapi/symfonycomponents/alert.rst index 043176a..37ed6b3 100644 --- a/source/devapi/symfonycomponents/alert.rst +++ b/source/devapi/symfonycomponents/alert.rst @@ -3,14 +3,15 @@ Alert .. versionadded:: 12.0.0 -Display an alert in the html where it is placed. +Renders an alert box inline at its position in the HTML. .. image:: /_static/images/symfonycomponents/alert-1.png :alt: Danger alert Props ----- -All fields are optional. + +All props are optional. * :code:`type` **string**. @@ -18,24 +19,26 @@ All fields are optional. * :code:`title` **string**. -* :code:`messages` **string|array**. Message content, a list can be passed. +* :code:`messages` **string|array**. The alert message. An array can be passed to display multiple messages. -* :code:`icon` **string**. CSS icon class, for example :code:`ti ti-info-circle`. +* :code:`icon` **string**. A CSS icon class, for example :code:`ti ti-info-circle`. - * If not defined, it will be calculated based on the alert type. + * If not set, the icon is automatically determined from the alert type. -* :code:`important` **bool**. False by default, highlight the alert. +* :code:`important` **bool**. When ``true``, the alert is visually highlighted. Defaults to ``false``. Blocks ------ title ^^^^^ -Completely override the title field. Even the `

` field + +Completely overrides the title, including the wrapping ``

`` element. content ^^^^^^^ -Completely override the message field. + +Completely overrides the message area. .. code-block:: twig @@ -56,7 +59,8 @@ Completely override the message field. Variants -------- -Multiple variation of the Alert exist, you can find the listed options here: + +Pre-typed variant components are available as shortcuts: .. code-block:: twig diff --git a/source/devapi/symfonycomponents/index.rst b/source/devapi/symfonycomponents/index.rst index cab7d6f..05d2b8a 100644 --- a/source/devapi/symfonycomponents/index.rst +++ b/source/devapi/symfonycomponents/index.rst @@ -3,11 +3,11 @@ Symfony Twig Components .. versionadded:: 12.0 -Twig Components is a `Symfony UX bundle `_ giving us the possibility to configure component in PHP. +Twig Components is a `Symfony UX bundle `_ that allows configuring components in PHP. -It also enable a cleaner integration and :code:`vuejs` like integration making it easier to maintain and review (compared to the old macro integration). +It also enables a cleaner integration with a :code:`Vue.js`-like syntax, making components easier to maintain and review compared to the legacy macro-based integration. -Following components are available: +The following components are available: .. toctree:: :maxdepth: 1 @@ -16,7 +16,8 @@ Following components are available: Usage ----- -Twig component support various integration mode, we recommend using the **Component HTML Syntax** + +Twig components support various integration modes. We recommend using the **Component HTML Syntax**. Component HTML Syntax @@ -24,29 +25,26 @@ Component HTML Syntax `Symfony Documentation `_ - .. code-block:: twig -Using this syntax ressemble a lot like modern frontend framework. +This syntax resembles modern frontend frameworks. -For example, if you want to pass variables, boolean or array you can do a twig block like the following +To pass dynamic values such as variables, booleans, or arrays, prefix the prop name with ``:`` and use a Twig expression: .. code-block:: twig - +

Custom title block

- {{ parent() }} -- Injecting parent datas (here will be `Overridden tittle`) + {{ parent() }} {# Renders the parent content — here: "Overridden title" #}
-Most of the component also have support the default block that should be named :code:`{% block content %}` inside the twig template. - -To inject data into it, you just avec to set data inside the block. +Most components also support a default ``content`` block. To inject content into it, place your markup directly inside the ```` tag: .. code-block:: twig @@ -66,11 +64,10 @@ To inject data into it, you just avec to set data inside the block. :alt: Example with custom twig block - Component Twig Syntax ^^^^^^^^^^^^^^^^^^^^^ -It exist a `component` twig method, this usage is not advise and should be use for rare case as it's less readable and less flexible (no block overload, visually blending with other twig method). +There is also a ``component()`` Twig function, but its use is discouraged except in rare cases. It is less readable and less flexible than the HTML syntax (no block overrides, and it visually blends in with other Twig function calls). .. code-block:: twig @@ -79,4 +76,4 @@ It exist a `component` twig method, this usage is not advise and should be use f title: __('My alert title.') }) }} -In the components documentation we will not display this integration mode. +This integration mode will not be shown in the component documentation. From 30342fcd6386791cf9bbe1d8044a4ea30d924f8f Mon Sep 17 00:00:00 2001 From: Benoit VIGNAL Date: Tue, 31 Mar 2026 15:15:03 +0200 Subject: [PATCH 6/7] Add `Creating a Component` section --- source/devapi/symfonycomponents/index.rst | 104 ++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/source/devapi/symfonycomponents/index.rst b/source/devapi/symfonycomponents/index.rst index 05d2b8a..335f678 100644 --- a/source/devapi/symfonycomponents/index.rst +++ b/source/devapi/symfonycomponents/index.rst @@ -77,3 +77,107 @@ There is also a ``component()`` Twig function, but its use is discouraged except }) }} This integration mode will not be shown in the component documentation. + +Creating a Component +-------------------- + +`Symfony Documentation `_ + +A Twig component consists of two parts: a **PHP class** that declares the props and logic, and a **Twig template** that defines the markup. + +The PHP Class +^^^^^^^^^^^^^ + +Create a class under ``src/Twig/Components/`` and annotate it with ``#[AsTwigComponent]``. + +By default, **Public properties** become the component's props and are automatically available as variables in the template. + +**Public methods** are also accessible from the template via the special ``this`` variable. + +.. code-block:: php + + namespace Twig\Components; + + use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; + + #[AsTwigComponent(name: 'MyComponent', template: 'twig_components/MyComponent.html.twig')] + class MyComponent + { + public string $title = ''; + public bool $important = false; + + public function getComputedClass(): string + { + return $this->important ? 'text-bold' : ''; + } + } + +The ``name`` parameter sets the tag name used in templates (````) — if not defined it will be generated based on the class namespace after ``Twig\Components``. + +The ``template`` parameter is optional — if omitted, Symfony derives the path from the class namespace after ``Twig\Components`` and under ``templates/twig_components``. + +.. note:: + + For components with multiple variants (e.g., ``Alert:Success``, ``Alert:Danger``), the recommended pattern is to extract shared props and logic into an abstract base class, then create lightweight variant classes that extend it and override the relevant defaults. See ``src/Twig/Components/Alert/`` (`Github `_) for a real-world example. + +The Twig Template +^^^^^^^^^^^^^^^^^ + +Place templates under ``templates/twig_components/``. Props are available directly as template variables. The component object itself is accessible via ``this``, which is useful for calling methods: + +.. code-block:: twig + +
+ {% block title %} + {% if title|length %} +

{{ title }}

+ {% endif %} + {% endblock %} + + {% block content %}{% endblock %} +
+ +Define ``{% block %}`` sections for any part of the markup that consumers may need to override. + +The ``{% block content %}`` is a specific block that will received content directly from whiting the Twig Syntax ``Will be injected into content block`` + +Variants +^^^^^^^^ + +Variant components share a base class and, typically, the same template. The class name determines the component tag name: a class ``Twig\Components\Alert\Danger`` automatically resolves to the tag ````. + +.. code-block:: php + + namespace Twig\Components\Alert; + + use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; + + #[AsTwigComponent(template: 'twig_components/Alert/Info.html.twig')] + final class Danger extends AbstractAlert + { + public string $type = 'danger'; + } + +The ``template`` parameter is specified explicitly here because all Alert variants share a single template file (``twig_components/Alert/Info.html.twig``). + +Testing +^^^^^^^ + +Two levels of tests are recommended: + +- **Unit tests**: instantiate the PHP class directly and assert prop defaults and method return values. No GLPI environment needed. +- **Rendering tests**: render a Twig string using ``TemplateRenderer::getInstance()->renderFromStringTemplate()`` and assert the resulting HTML. These extend ``GLPITestCase``. + +Tests live in ``tests/functional/Twig/Components/`` (`Github `_). See ``AlertTest.php`` and ``AlertRenderingTest.php`` for examples. + +Debugging +^^^^^^^^^ + +To list all registered components and their resolved template paths, run: + +.. code-block:: bash + + bin/console symfony:debug:twig-component + + # Using Makefile + make console c='symfony:debug:twig-component' From 033597ef00f8495814b5c2d5e645fb68a2789002 Mon Sep 17 00:00:00 2001 From: Benoit VIGNAL Date: Tue, 31 Mar 2026 15:17:43 +0200 Subject: [PATCH 7/7] Text improvements --- source/devapi/symfonycomponents/index.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/devapi/symfonycomponents/index.rst b/source/devapi/symfonycomponents/index.rst index 335f678..886d948 100644 --- a/source/devapi/symfonycomponents/index.rst +++ b/source/devapi/symfonycomponents/index.rst @@ -112,9 +112,9 @@ By default, **Public properties** become the component's props and are automatic } } -The ``name`` parameter sets the tag name used in templates (````) — if not defined it will be generated based on the class namespace after ``Twig\Components``. +The ``name`` parameter sets the tag name used in templates (````). If omitted, it is derived from the class namespace relative to ``Twig\Components``. -The ``template`` parameter is optional — if omitted, Symfony derives the path from the class namespace after ``Twig\Components`` and under ``templates/twig_components``. +The ``template`` parameter is also optional. If omitted, Symfony derives the template path from the class namespace, resolved under ``templates/twig_components/``. .. note:: @@ -139,7 +139,11 @@ Place templates under ``templates/twig_components/``. Props are available direct Define ``{% block %}`` sections for any part of the markup that consumers may need to override. -The ``{% block content %}`` is a specific block that will received content directly from whiting the Twig Syntax ``Will be injected into content block`` +The ``{% block content %}`` block is special: any markup placed directly inside the component tag (without an explicit ````) is injected into it automatically: + +.. code-block:: twig + + This text is injected into the content block. Variants ^^^^^^^^ @@ -168,7 +172,7 @@ Two levels of tests are recommended: - **Unit tests**: instantiate the PHP class directly and assert prop defaults and method return values. No GLPI environment needed. - **Rendering tests**: render a Twig string using ``TemplateRenderer::getInstance()->renderFromStringTemplate()`` and assert the resulting HTML. These extend ``GLPITestCase``. -Tests live in ``tests/functional/Twig/Components/`` (`Github `_). See ``AlertTest.php`` and ``AlertRenderingTest.php`` for examples. +Tests live in ``tests/functional/Twig/Components/`` (`GitHub `_). See ``AlertTest.php`` and ``AlertRenderingTest.php`` for examples. Debugging ^^^^^^^^^