Skip to content

Update CVA docs and fixes #1564

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 1, 2024
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
3 changes: 1 addition & 2 deletions src/TwigComponent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@
- Introduce CVA to style TwigComponent #1416
- Drop Twig 2 support #1436
- Fix full context is stored in profiler #1552
- Add CVA (Class variant authority) integration #1416

## 2.15.0

- Add the ability to render specific attributes from the `attributes` variable #1442
- Restrict Twig 3.9 for now #1486
- Build reproducible TemplateMap to fix possible post-deploy breakage #1497
- Add CVA (Class variant authority) integration #1416

## 2.14.0

- Make `ComponentAttributes` traversable/countable
- Fixed lexing some `{# twig comments #}` with HTML Twig syntax
- Fix various usages of deprecated Twig code
- Add attribute rendering system

## 2.13.0

Expand Down
63 changes: 29 additions & 34 deletions src/TwigComponent/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1061,14 +1061,16 @@ Exclude specific attributes:
Component with Complex Variants (CVA)
-------------------------------------

CVA (Class Variant Authority) is a concept from the JS world (https://cva.style/docs/getting-started/variants).
It's a concept used by the famous shadcn/ui library (https://ui.shadcn.com).
.. versionadded:: 2.16

The ``cva`` function was added in TwigComponents 2.16.

`CVA (Class Variant Authority)`_ is a concept from the JavaScript world and used
by the well-known `shadcn/ui`_.
CVA allows you to display a component with different variants (color, size, etc.),
to create highly reusable and customizable components.
You can use the cva function to define variants for your component.
The cva function take as argument an array key-value pairs.
The base key allow you define a set of classes commune to all variants.
In the variants key you define the different variants of your component.
to create highly reusable and customizable components. This is powered by a ``cva()`` Twig
function where you define ``base`` classes that should always be present and then different
``variants`` and the corresponding classes:

.. code-block:: html+twig

Expand All @@ -1095,9 +1097,11 @@ In the variants key you define the different variants of your component.
{% block content %}{% endblock %}
</div>

Then use the ``color`` and ``size`` variants to select the classes needed:

{# index.html.twig #}
.. code-block:: html+twig

{# index.html.twig #}
<twig:Alert color="red" size="lg">
<div>My content</div>
</twig:Alert>
Expand All @@ -1108,18 +1112,18 @@ In the variants key you define the different variants of your component.
</twig:Alert>
// class="alert bg-green text-sm"

<twig:Alert class="flex items-center justify-center">
<twig:Alert color="red" class="flex items-center justify-center">
<div>My content</div>
</twig:Alert>
// class="alert bg-blue text-md flex items-center justify-center"
// class="alert bg-red text-md flex items-center justify-center"

CVA and Tailwind CSS
~~~~~~~~~~~~~~~~~~~~

CVA work perfectly with tailwindcss. The only drawback is you can have class conflicts,
to have a better control you can use this following bundle (
https://github.com/tales-from-a-dev/twig-tailwind-extra
) in addition to the cva function:
CVA work perfectly with Tailwind CSS. The only drawback is that you can have class conflicts.
To "merge" conflicting classes together and keep only the ones you need, use the
``tailwind_merge()` method from `tales-from-a-dev/twig-tailwind-extra`_
with the ``cva()`` function:

.. code-block:: terminal

Expand All @@ -1131,29 +1135,17 @@ https://github.com/tales-from-a-dev/twig-tailwind-extra
{% props color = 'blue', size = 'md' %}

{% 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',
}
}
// ...
}) %}

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

Compounds variants
~~~~~~~~~~~~~~~~~~
Compound Variants
~~~~~~~~~~~~~~~~~

You can define compound variants. A compound variant is a variants that apply
You can define compound variants. A compound variant is a variant that applies
when multiple other variant conditions are met.

.. code-block:: html+twig
Expand All @@ -1175,7 +1167,8 @@ when multiple other variant conditions are met.
lg: 'text-lg',
}
},
compound: {
compoundVariants: {
// if colors=red AND size = (md or lg), add the `font-bold` class
colors: ['red'],
size: ['md', 'lg'],
class: 'font-bold'
Expand Down Expand Up @@ -1203,11 +1196,10 @@ when multiple other variant conditions are met.
</twig:Alert>
// class="alert bg-green text-lg font-bold"

Default variants
Default Variants
~~~~~~~~~~~~~~~~

You can define defaults variants, so if no variants are matching you
can still defined a default set of class to apply.
If no variants match, you can define a default set of classes to apply:

.. code-block:: html+twig

Expand Down Expand Up @@ -1615,3 +1607,6 @@ https://symfony.com/doc/current/contributing/code/bc.html
.. _`Live Nested Components`: https://symfony.com/bundles/ux-live-component/current/index.html#nested-components
.. _`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
.. _`shadcn/ui`: https://ui.shadcn.com
.. _`tales-from-a-dev/twig-tailwind-extra`: https://github.com/tales-from-a-dev/twig-tailwind-extra
23 changes: 23 additions & 0 deletions src/TwigComponent/tests/Unit/CVATest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@ public function testRecipes(array $recipe, array $recipes, string $expected): vo
$this->assertEquals($expected, $recipeClass->resolve($recipes));
}

public function testApply(): void
{
$recipe = new CVA('font-semibold border rounded', [
'colors' => [
'primary' => 'text-primary',
'secondary' => 'text-secondary',
],
'sizes' => [
'sm' => 'text-sm',
'md' => 'text-md',
'lg' => 'text-lg',
],
], [
[
'colors' => ['primary'],
'sizes' => ['sm'],
'class' => 'text-red-500',
],
]);

$this->assertEquals('font-semibold border rounded text-primary text-sm text-red-500', $recipe->apply(['colors' => 'primary', 'sizes' => 'sm']));
}

public static function recipeProvider(): iterable
{
yield 'base null' => [
Expand Down