Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions UPGRADE-3.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# UPGRADE FROM `2.x` TO `3.0`

Symfony UX follows Symfony's release process, 2.x and 3.0 have the same
features, but Symfony UX 3.0 doesn't include any deprecated features. To
upgrade, make sure to resolve all deprecation notices. Read more about this in
the [Symfony documentation](https://symfony.com/doc/6.4/setup/upgrade_major.html#upgrade-major-symfony-deprecations).

> [!NOTE]
> Requires PHP `8.2` or higher.
>
> Requires Symfony `6.4` or higher.

## LazyImage

* The package has been removed, see the [previous README](https://raw.githubusercontent.com/symfony/ux/refs/heads/2.x/src/LazyImage/README.md)
for migration steps

## LiveComponent

* Remove `csrf` argument from `AsLiveComponent` in favor of same-origin/CORS:
```diff
- #[AsLiveComponent(csrf: true)]
+ #[AsLiveComponent]
class MyLiveComponent {
// ...
}
```

## Map

* The Twig function `render_map()` has been removed, use `ux_map()` instead
* The option `title` from `Polygon`, `Polyline`, `Rectangle` and `Circle`, has been removed, use option `infoWindow` instead
* The property `rawOptions` from `ux:map:*:before-create` events has been removed, use `bridgeOptions` instead

## Swup

* The package has been removed, see the [previous README](https://raw.githubusercontent.com/symfony/ux/refs/heads/2.x/src/Turbo/README.md)
for migration steps

## TogglePassword

* The package has been removed, see the [previous README](https://raw.githubusercontent.com/symfony/ux/refs/heads/2.x/src/TogglePassword/README.md)
for migration steps

## TwigComponent

* The configuration `twig_component.defaults` is now mandatory and must contain at least one namespace/directory pair:
```diff
# config/packages/twig_component.yaml
twig_component:
anonymous_template_directory: 'components/'
+ defaults:
+ # Namespace & directory for components
+ App\Twig\Components\: 'components/'
```

* Remove method `PreCreateForRenderEvent::getProps()` in favor of `PreCreateForRenderEvent::getInputProps()`
```diff
class HookIntoTwigPreCreateForRenderSubscriber implements EventSubscriberInterface
{
public function onPreCreateForRender(PreCreateForRenderEvent $event): void
{
- $event->getProps();
+ $event->getInputProps();
}

public static function getSubscribedEvents(): array
{
return [PreCreateForRenderEvent::class => 'onPreCreateForRender'];
}
}
```

* Remove `cva` Twig function in favor of [`html_cva` Twig function from `twig/html-extra:^3.12`](https://twig.symfony.com/html_cva)

**Before:**
```twig
{% set alert = cva({
base: 'alert',
variants: {
color: { blue: 'bg-blue', red: 'bg-red', green: 'bg-green' },
size: { sm: 'text-sm', md: 'text-md', lg: 'text-lg' }
},
defaultVariants: { size: 'md', color: 'blue' },
compoundVariants: [{
color: ['red'],
size: ['lg'],
class: 'font-bold'
}],
defaultVariants: {
rounded: 'md'
}
}) %}

<div class="{{ alert.apply({color, size}, attributes.render('class')) }}">
{% block content %}{% endblock %}
</div>
```
**After:**
```twig
{% set alert = html_cva(
base: 'alert',
variants: {
color: { blue: 'bg-blue', red: 'bg-red', green: 'bg-green' },
size: { sm: 'text-sm', md: 'text-md', lg: 'text-lg' }
},
compound_variants: [{
color: ['red'],
size: ['lg'],
class: 'font-bold'
}],
default_variants: {
rounded: 'md'
}
) %}

<div class="{{ alert.apply({color, size}, attributes.render('class')) }}">
{% block content %}{% endblock %}
</div>
```

## Typed

* The package has been removed, see the [previous README](https://raw.githubusercontent.com/symfony/ux/refs/heads/2.x/src/Typed/README.md)
for migration steps
1 change: 1 addition & 0 deletions src/LiveComponent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Minimum required Symfony version is now 6.4
- Minimum required PHP version is now 8.2
- Remove `csrf` argument from `AsLiveComponent` in favor of same-origin/CORS

## 2.30

Expand Down
7 changes: 7 additions & 0 deletions src/TwigComponent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

- Minimum required Symfony version is now 6.4
- Minimum required PHP version is now 8.2
- The configuration `twig_component.defaults` could not be nullable anymore
- Remove method `PreCreateForRenderEvent::getProps()` in favor of `PreCreateForRenderEvent::getInputProps()`
- Remove `cva` Twig function in favor of [`html_cva` Twig function from `twig/html-extra`](https://twig.symfony.com/html_cva)
- Passing `null` as an attribute value when using `ComponentAttributes` (or `attributes` Twig variable) will now throw an exception, use `remove()` instead
- Remove method `ComponentAttributes::add()`, use `{{ attributes.defaults(stimulus_controller('...')) }}` instead
- The `ComponentTemplateFinder` does not accept `Twig\Environment` as first argument anymore, pass a `LoaderInterface` instead
- The `ComponentTemplateFinder` does not accept a nullable `directory` argument anymore, pass a string instead

## 2.30

Expand Down
142 changes: 25 additions & 117 deletions src/TwigComponent/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1216,58 +1216,41 @@ The nesting is recursive so you could potentially do something like this:
row:widget:class="ui-form-widget"
/>

Component with Complex Variants (CVA)
-------------------------------------

.. deprecated:: 2.20
Class Variant Authority
-----------------------

The ``cva`` function was deprecated in TwigComponents 2.20, and will be
removed in 3.0. The function is now provided by the ``twig/html-extra:^3.12``
package under the name `html_cva`_.

`CVA (Class Variant Authority)`_ originates from the JavaScript ecosystem. It
enables reusable, customizable components by managing variants (e.g., color, size).
The ``cva()`` Twig function defines ``base`` classes (always applied) and variant-specific
classes:
`CVA (Class Variant Authority)`_ originates from the JavaScript ecosystem.
It enables reusable, customizable components by managing variants (e.g., color, size).
The `html_cva()`_ Twig function from ``twig/html-extra:^3.12`` defines ``base`` classes (always applied)
and variant-specific classes:

.. code-block:: html+twig

{# templates/components/Alert.html.twig #}
{% props color = 'blue', size = 'md' %}

{% set alert = cva({
base: 'alert',
{% set button = html_cva(
base: 'btn',
variants: {
color: {
blue: 'bg-blue',
red: 'bg-red',
green: 'bg-green',
},
size: {
sm: 'text-sm',
md: 'text-md',
lg: 'text-lg',
}
}
}) %}
color: { primary: 'btn-primary', secondary: 'btn-secondary' },
size: { sm: 'btn-sm', md: 'btn-md', lg: 'btn-lg' }
},
default_variant: { color: 'primary', size: 'md' }
) %}

<div class="{{ alert.apply({color, size}, attributes.render('class')) }}">
{% block content %}{% endblock %}
</div>
<button class="{{ button.apply({color, size}, attributes.render('class')) }}">
{% block content %}{% endblock %}
</button>

Then use the ``color`` and ``size`` variants to select the classes needed:
When rendering the component, pass the desired variants:

.. code-block:: html+twig

<twig:Alert color="green" size="sm">
...
</twig:Alert>
{# renders as: <button class="btn btn-primary btn-md">... #}
<twig:Button>Click Me!</twig:Button>

{# will render as: #}
{# renders as: <button class="btn btn-secondary btn-lg">... #}
<twig:Button color="secondary" size="lg">Click Me!</twig:Button>

<div class="alert bg-green text-sm">
...
</div>
{# renders as: <button class="btn btn-primary btn-sm custom-class">... #}
<twig:Button size="sm" class="custom-class">Click Me!</twig:Button>

CVA and Tailwind CSS
~~~~~~~~~~~~~~~~~~~~
Expand All @@ -1278,85 +1261,10 @@ to resolve conflicts:

.. code-block:: html+twig

<div class="{{ alert.apply({color, size}, attributes.render('class'))|tailwind_merge }}">
<div class="{{ button.apply({color, size}, attributes.render('class'))|tailwind_merge }}">
{% block content %}{% endblock %}
</div>

Compound Variants
~~~~~~~~~~~~~~~~~

Define compound variants for conditions involving multiple variants:

.. code-block:: html+twig

{# templates/components/Alert.html.twig #}
{% props color = 'blue', size = 'md' %}

{% set alert = cva({
base: 'alert',
variants: {
color: { red: 'bg-red' },
size: { lg: 'text-lg' }
},
compoundVariants: [{
color: ['red'],
size: ['lg'],
class: 'font-bold'
}]
}) %}

<div class="{{ alert.apply({color, size}) }}">
{% block content %}{% endblock %}
</div>

{# index.html.twig #}

<twig:Alert color="red" size="lg">
...
</twig:Alert>

{# will render as: #}

<div class="alert bg-red text-lg font-bold">
...
</div>

Default Variants
~~~~~~~~~~~~~~~~

If no variants match, you can define a default set of classes to apply:

.. code-block:: html+twig

{# templates/components/Alert.html.twig #}
{% set alert = cva({
base: 'alert',
variants: {
color: {
red: 'bg-red'
},
rounded: {
sm: 'rounded-sm',
md: 'rounded-md'
}
},
defaultVariants: {
rounded: 'md'
}
}) %}

{# index.html.twig #}

<twig:Alert color="red">
...
</twig:Alert>

{# will render as: #}

<div class="alert bg-red rounded-md">
...
</div>

Test Helpers
------------

Expand Down Expand Up @@ -1809,7 +1717,7 @@ https://symfony.com/doc/current/contributing/code/bc.html
.. _`Passing Blocks to Live Components`: https://symfony.com/bundles/ux-live-component/current/index.html#passing-blocks
.. _`Stimulus controller`: https://symfony.com/bundles/StimulusBundle/current/index.html
.. _`CVA (Class Variant Authority)`: https://cva.style/docs/getting-started/variants
.. _`html_cva`: https://twig.symfony.com/doc/3.x/functions/html_cva.html
.. _`html_cva()`: https://twig.symfony.com/doc/3.x/functions/html_cva.html
.. _`tales-from-a-dev/twig-tailwind-extra`: https://github.com/tales-from-a-dev/twig-tailwind-extra
.. _`ignore not defined options`: https://symfony.com/doc/current/components/options_resolver.html#ignore-not-defined-options
.. _`Symfony MakerBundle`: https://symfony.com/bundles/SymfonyMakerBundle/current/index.html
Loading