Skip to content

Commit

Permalink
Update documentation, base class can be a list
Browse files Browse the repository at this point in the history
  • Loading branch information
WebMamba committed Feb 28, 2024
1 parent 25ade8f commit aa82322
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 44 deletions.
125 changes: 91 additions & 34 deletions src/TwigComponent/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1066,28 +1066,32 @@ It's a concept used by the famous shadcn/ui library (https://ui.shadcn.com).
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 first argument of the cva function is the base classes, the classes present in all variants. Then the second
argument is an array of variants.
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.

.. code-block:: html+twig

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

{% set alert = cva('alert ' ~ attributes.render('class'), {
color: {
blue: 'bg-blue',
red: 'bg-red',
green: 'bg-green',
},
size: {
sm: 'text-sm',
md: 'text-md',
lg: 'text-lg',
{% 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}) }}">
<div class="{{ alert.apply({color, size}, attributes.render('class')) }}">
{% block content %}{% endblock %}
</div>

Expand Down Expand Up @@ -1126,20 +1130,23 @@ https://github.com/tales-from-a-dev/twig-tailwind-extra
{# templates/components/Alert.html.twig #}
{% props color = 'blue', size = 'md' %}

{% set alert = cva('alert ' ~ attributes.render('class'), {
color: {
blue: 'bg-blue',
red: 'bg-red',
green: 'bg-green',
},
size: {
sm: 'text-sm',
md: 'text-md',
lg: 'text-lg',
{% 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}) | tailwind_merge }}">
<div class="{{ alert.apply({color, size}, attributes.render('class')) | tailwind_merge }}">
{% block content %}{% endblock %}
</div>

Expand All @@ -1154,16 +1161,19 @@ when multiple other variant conditions are met.
{# templates/components/Alert.html.twig #}
{% props color = 'blue', size = 'md' %}

{% set alert = cva('alert ' ~ attributes.render('class'), {
color: {
blue: 'bg-blue',
red: 'bg-red',
green: 'bg-green',
},
size: {
sm: 'text-sm',
md: 'text-md',
lg: 'text-lg',
{% 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',
}
},
compound: {
colors: ['red'],
Expand Down Expand Up @@ -1193,6 +1203,53 @@ when multiple other variant conditions are met.
</twig:Alert>
// class="alert bg-green text-lg font-bold"

Default variants
~~~~~~~~~~~~~~~~

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

.. code-block:: html+twig

{# templates/components/Alert.html.twig #}
{% 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',
},
rounded: {
sm: 'rounded-sm',
md: 'rounded-md',
lg: 'rounded-lg',
}
},
defaultsVariants: {
rounded: 'rounded-md',
}
}) %}

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

{# index.html.twig #}

<twig:Alert color="red" size="lg">
<div>My content</div>
</twig:Alert>
// class="alert bg-red text-lg font-bold rounded-md"


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

Expand Down
13 changes: 9 additions & 4 deletions src/TwigComponent/src/CVA.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@
final class CVA
{
/**
* @var string|null
* @var string|list<string|null>|null
* @var array<string, array<string, string>>|null the array should have the following format [variantCategory => [variantName => classes]]
* ex: ['colors' => ['primary' => 'bleu-8000', 'danger' => 'red-800 text-bold'], 'size' => [...]]
* @var array<array<string, string[]>>|null the array should have the following format ['variantsCategory' => ['variantName', 'variantName'], 'class' => 'text-red-500']
* @var array<string, string>|null
*/
public function __construct(
private ?string $base = null,
private string|array|null $base = null,
private ?array $variants = null,
private ?array $compoundVariants = null,
private ?array $defaultVariants = null
private ?array $defaultVariants = null,
) {
}

Expand All @@ -45,7 +46,11 @@ public function apply(array $recipes, string ...$classes): string

public function resolve(array $recipes): string
{
$classes = $this->base ?? '';
if (\is_array($this->base)) {
$classes = implode(' ', $this->base);
} else {
$classes = $this->base ?? '';
}

foreach ($recipes as $recipeName => $recipeValue) {
if (!isset($this->variants[$recipeName][$recipeValue])) {
Expand Down
10 changes: 5 additions & 5 deletions src/TwigComponent/src/Twig/ComponentExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function finishEmbeddedComponentRender(): void

/**
* @param array{
* base: string,
* base: string|string[]|null,
* variants: array<string, array<string, string>>,
* compoundVariants: array<array<string, string>>,
* defaultVariants: array<string, string>
Expand All @@ -102,10 +102,10 @@ public function finishEmbeddedComponentRender(): void
public function cva(array $cva): CVA
{
return new CVA(
$cva['base'] ?? [],
$cva['variants'] ?? [],
$cva['compoundVariants'] ?? [],
$cva['defaultVariants'] ?? [],
$cva['base'] ?? null,
$cva['variants'] ?? null,
$cva['compoundVariants'] ?? null,
$cva['defaultVariants'] ?? null,
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% props color = 'blue', size = 'md' %}

{% set alert = cva({
base: 'alert',
base: ['alert'],
variants: {
color: {
blue: 'alert-blue',
Expand Down

0 comments on commit aa82322

Please sign in to comment.