From e7f676fda5fd56b881766bd3e52a92db71124ec1 Mon Sep 17 00:00:00 2001 From: Matheo Daninos Date: Fri, 16 Aug 2024 13:01:34 +0200 Subject: [PATCH] apply review --- doc/functions/html_cva.rst | 61 ++++++++++--------- extra/html-extra/Cva.php | 11 +--- extra/html-extra/HtmlExtension.php | 14 +---- extra/html-extra/README.md | 2 +- extra/html-extra/Tests/CVATest.php | 15 +++-- .../Fixtures/{cva.test => html_cva.test} | 0 ...te.test => html_cva_pass_to_template.test} | 0 7 files changed, 46 insertions(+), 57 deletions(-) rename extra/html-extra/Tests/Fixtures/{cva.test => html_cva.test} (100%) rename extra/html-extra/Tests/Fixtures/{cva_pass_to_template.test => html_cva_pass_to_template.test} (100%) diff --git a/doc/functions/html_cva.rst b/doc/functions/html_cva.rst index 65c9ee2fb1a..720d87a2b6c 100644 --- a/doc/functions/html_cva.rst +++ b/doc/functions/html_cva.rst @@ -1,12 +1,11 @@ -``cva`` +``html_cva`` ======= `CVA (Class Variant Authority)`_ is a concept from the JavaScript world and used by the well-known `shadcn/ui`_. -The Cva concept is used to render multiple variations of components, applying +The CVA concept is used to render multiple variations of components, applying a set of conditions and recipes to dynamically compose CSS class strings (color, size, etc.), -to create highly reusable and customizable templates. This function work best by being combined with -`TwigComponent`_ +to create highly reusable and customizable templates. .. note:: @@ -19,16 +18,16 @@ to create highly reusable and customizable templates. This function work best by Then, on Symfony projects, install the ``twig/extra-bundle``: -This is powered by a ``html_cva()`` Twig +The concept of CVA is powered by a ``html_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 {# templates/alert.html.twig #} - {% set alert = html_cva({ - base: 'alert ', - variants: { + {% set alert = html_cva( + base='alert ', + variants={ color: { blue: 'bg-blue', red: 'bg-red', @@ -46,18 +45,18 @@ function where you define ``base`` classes that should always be present and the ... -Then use the ``color`` and ``size`` variants to select the classes needed: +Then use the ``color`` and ``size`` variants to select the needed classes: .. code-block:: twig {# index.html.twig #} - {% include 'alert.html.twig' with {'color': 'blue', 'size': 'md'} %} + {{ include('alert.html.twig', {'color': 'blue', 'size': 'md'}) }} // class="alert bg-red text-lg" - {% include 'alert.html.twig' with {'color': 'green', 'size': 'sm'} %} + {{ include('alert.html.twig', {'color': 'green', 'size': 'sm'}) }} // class="alert bg-green text-sm" - {% include 'alert.html.twig' with {'color': 'red', 'class': 'flex items-center justify-center'} %} + {{ include('alert.html.twig', {'color': 'red', 'class': 'flex items-center justify-center'}) }} // class="alert bg-red text-md flex items-center justify-center" CVA and Tailwind CSS @@ -74,11 +73,11 @@ with the ``html_cva()`` function: .. code-block:: html+twig - {% set alert = html_cva({ + {% set alert = html_cva( // ... - }) %} + ) %} -
+
...
@@ -86,13 +85,13 @@ Compound Variants ~~~~~~~~~~~~~~~~~ You can define compound variants. A compound variant is a variant that applies -when multiple other variant conditions are met. +when multiple other variant conditions are met: .. code-block:: html+twig - {% set alert = html_cva({ - base: 'alert ', - variants: { + {% set alert = html_cva( + base='alert', + variants={ color: { blue: 'bg-blue', red: 'bg-red', @@ -104,13 +103,13 @@ when multiple other variant conditions are met. lg: 'text-lg', } }, - compoundVariants: [{ + compoundVariants=[{ // if color = red AND size = (md or lg), add the `font-bold` class color: ['red'], size: ['md', 'lg'], class: 'font-bold' }] - }) %} + ) %}
... @@ -118,13 +117,13 @@ when multiple other variant conditions are met. {# index.html.twig #} - {% include 'alert.html.twig' with {color: 'red', size: 'lg'} %} + {{ include('alert.html.twig', {color: 'red', size: 'lg'}) }} // class="alert bg-red text-lg font-bold" - {% include 'alert.html.twig' with {color: 'green', size: 'sm'} %} + {{ include('alert.html.twig', {color: 'green', size: 'sm'}) }} // class="alert bg-green text-sm" - {% include 'alert.html.twig' with {color: 'red', size: 'md'} %} + {{ include('alert.html.twig', {color: 'red', size: 'md'}) }} // class="alert bg-green text-lg font-bold" Default Variants @@ -134,9 +133,9 @@ If no variants match, you can define a default set of classes to apply: .. code-block:: html+twig - {% set alert = html_cva({ - base: 'alert ', - variants: { + {% set alert = html_cva( + base='alert ', + variants={ color: { blue: 'bg-blue', red: 'bg-red', @@ -153,10 +152,10 @@ If no variants match, you can define a default set of classes to apply: lg: 'rounded-lg', } }, - defaultVariants: { + defaultVariants={ rounded: 'md', } - }) %} + ) %}
... @@ -164,9 +163,11 @@ If no variants match, you can define a default set of classes to apply: {# index.html.twig #} - {% include 'alert.html.twig' with {color: 'red', size: 'lg'} %} + {{ include('alert.html.twig', {color: 'red', size: 'lg'}) }} // class="alert bg-red text-lg font-bold rounded-md" +This function works best when used with `TwigComponent`_. + .. _`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 diff --git a/extra/html-extra/Cva.php b/extra/html-extra/Cva.php index c975d2b8939..3c7abe41ac8 100644 --- a/extra/html-extra/Cva.php +++ b/extra/html-extra/Cva.php @@ -12,18 +12,9 @@ namespace Twig\Extra\Html; /** - * Class Variant Authority (Cva) resolver. - * - * The Cva concept is used to render multiple variations of components, applying - * a set of conditions and recipes to dynamically compose CSS class strings. - * - * @see https://cva.style/docs - * - * @doc https://symfony.com/bundles/ux-twig-component/current/index.html + * Class Variant Authority (CVA) resolver. * * @author Mathéo Daninos - * - * @experimental */ final class Cva { diff --git a/extra/html-extra/HtmlExtension.php b/extra/html-extra/HtmlExtension.php index 8f4e2bdc0f4..a3e2c78d22e 100644 --- a/extra/html-extra/HtmlExtension.php +++ b/extra/html-extra/HtmlExtension.php @@ -113,12 +113,7 @@ public static function htmlClasses(...$args): string } /** - * base some base class you want to have in every matching recipes - * variants your recipes class - * compoundVariants compounds allow you to add extra class when multiple variation are matching in the same time - * defaultVariants allow you to add a default class when no recipe is matching - * - * @param string|list|null $base + * @param string|list $base * @param array> $variants * @param array>> $compoundVariants * @param array $defaultVariant @@ -126,11 +121,6 @@ public static function htmlClasses(...$args): string */ public static function htmlCva(array|string $base = [], array $variants = [], array $compoundVariants = [], array $defaultVariant = []): Cva { - return new Cva( - $base, - $variants, - $compoundVariants, - $defaultVariant - ); + return new Cva($base, $variants, $compoundVariants, $defaultVariant); } } diff --git a/extra/html-extra/README.md b/extra/html-extra/README.md index 842e3d6efe7..b39435b870b 100644 --- a/extra/html-extra/README.md +++ b/extra/html-extra/README.md @@ -9,7 +9,7 @@ This package is a Twig extension that provides the following: * [`html_classes`][2] function: returns a string by conditionally joining class names together. - * [`html_cva`][3] function: return a Cva object to handle class variants. + * [`html_cva`][3] function: returns a `Cva object to handle class variants. [1]: https://twig.symfony.com/data_uri [2]: https://twig.symfony.com/html_classes diff --git a/extra/html-extra/Tests/CVATest.php b/extra/html-extra/Tests/CVATest.php index b2e79dd27e8..b8b32fbef1b 100644 --- a/extra/html-extra/Tests/CVATest.php +++ b/extra/html-extra/Tests/CVATest.php @@ -14,7 +14,7 @@ use PHPUnit\Framework\TestCase; use Twig\Extra\Html\Cva; -class CVATest extends TestCase +class CvaTest extends TestCase { /** * @dataProvider recipeProvider @@ -51,7 +51,7 @@ public function testApply() public function testApplyWithNullString() { - $recipe = new CVA('font-semibold border rounded', [ + $recipe = new Cva('font-semibold border rounded', [ 'colors' => [ 'primary' => 'text-primary', 'secondary' => 'text-secondary', @@ -360,6 +360,7 @@ public static function recipeProvider(): iterable ['colors' => 'primary', 'sizes' => 'sm'], 'font-semibold border rounded text-primary text-sm', ]; + yield 'default variables' => [ [ 'base' => 'font-semibold border rounded', @@ -395,6 +396,7 @@ public static function recipeProvider(): iterable ['colors' => 'primary', 'sizes' => 'sm'], 'font-semibold border rounded text-primary text-sm rounded-md', ]; + yield 'default variables all overwrite' => [ [ 'base' => 'font-semibold border rounded', @@ -430,6 +432,7 @@ public static function recipeProvider(): iterable ['colors' => 'primary', 'sizes' => 'sm', 'rounded' => 'lg'], 'font-semibold border rounded text-primary text-sm rounded-lg', ]; + yield 'default variables without matching variants' => [ [ 'base' => 'font-semibold border rounded', @@ -622,8 +625,8 @@ public static function recipeProvider(): iterable */ public function testAdditionalClasses(string|array $base, array|string $additionals, string $expected) { - $cva = new CVA($base); - if ([] === $additionals || '' === $additionals) { + $cva = new Cva($base); + if (!$additionals) { $this->assertEquals($expected, $cva->apply([])); } else { $this->assertEquals($expected, $cva->apply([], ...(array) $additionals)); @@ -637,21 +640,25 @@ public static function provideAdditionalClassesCases(): iterable 'foo', 'foo', ]; + yield 'additional_are_used' => [ '', 'foo', 'foo', ]; + yield 'additionals_are_used' => [ '', ['foo', 'bar'], 'foo bar', ]; + yield 'additionals_preserve_order' => [ ['foo'], ['bar', 'foo'], 'foo bar', ]; + yield 'additional_are_deduplicated' => [ '', ['bar', 'bar'], diff --git a/extra/html-extra/Tests/Fixtures/cva.test b/extra/html-extra/Tests/Fixtures/html_cva.test similarity index 100% rename from extra/html-extra/Tests/Fixtures/cva.test rename to extra/html-extra/Tests/Fixtures/html_cva.test diff --git a/extra/html-extra/Tests/Fixtures/cva_pass_to_template.test b/extra/html-extra/Tests/Fixtures/html_cva_pass_to_template.test similarity index 100% rename from extra/html-extra/Tests/Fixtures/cva_pass_to_template.test rename to extra/html-extra/Tests/Fixtures/html_cva_pass_to_template.test