/twig-components

Twig components inspired from blade components

Primary LanguagePHPMIT LicenseMIT

Twig components extension

Latest Version on Packagist GitHub Tests Action Status Total Downloads

This is a twig extension for automatically create components as tags. The name of the tag is based on the filename and the path. This is highly inspired from laravel blade components.

Installation

You can install the package via composer:

composer require performing/twig-components

Setup

Update! You can use just this line of code to setup the extension, this will enable:

  • components from the specified directory
  • safe filters so no need to use |raw
  • html-like as x-tags
\Performing\TwigComponents\Setup::init($twig, '/relative/directory/to/components');

You want can still use the old method:

$extension = new \Performing\TwigComponents\ComponentExtension('/relative/twig/components/directory');
$twig->addExtension($extension); 

Syntax

You can use a component component-name.twig like this anywhere in your templates.

{% x:component-name with {any: 'param'} %}
    <strong>Any Content</strong>
{% endx %}

You can also reach for components files that are in sub-folders with a dot-notation syntax. For example, a component at /components/button/primary.twig would become

{% x:button.primary with {any: 'param'} %}
    <strong>Any Content</strong>
{% endx %}

Components

You can create a file in the components directory like this:

{# /components/button.twig #}
<button {{ attributes.merge({ class:'text-white rounded-md px-4 py-2' }) }}>
  {{ slot }}
</button>

Next, use the new component anywhere in your templates with this syntax or with x-tags.

{# /index.twig #}
{% x:button with {class:'bg-blue-600'} %}
  <span class="text-lg">Click here!</span>
{% endx %}

{# or #}

<x-button class='bg-blue-600'>
  <span class="text-lg">Click here!</span>
</x-button>

The output generated will be like this.

<button class="bg-blue-600 text-white rounded-md px-4 py-2">
  <span class="text-lg">Click here!</span>
</button>

Features

Slots (0.2.0)

{% x:card %}
   {% slot:title %} Some Title {% endslot %}
    
    Some content {# normal slot variable #}
   
   {% slot:buttons %}  
       {% x:button.primary %} Submit {% endx %}
   {% endslot %}
{% endx %}

Pro Tip (VSCode)

Add this your user twig.json snippets

"Component": {
  "prefix": "x:",
  "body": [
    "{% x:$1 %}",
    "$2",
    "{% endx %}",
  ],
  "description": "Twig component"
}

X Tags (0.3.0)

Now, you can enable <x-tags /> for your twig components, here an example:

<x-button>
    <x-slot name="icon">
        <!-- my icon -->
    </x-slot>
    Submit
</x-button>

You can pass attributes like this:

<x-button 
    :any="'evaluate' ~ 'twig'"
    other="{{'this' ~ 'works' ~ 'too'}}" 
    another="or this"
    not-this="{{'this' ~ 'does'}}{{ 'not work' }}"
>
    <x-slot name="icon">
        <!-- my icon -->
    </x-slot>
    Submit
</x-button>

To enable this feature you need to set the lexer on your twig enviroment.

$twig->setLexer(new Performing\TwigComponents\ComponentLexer($twig));

Keep in mind that you should set the lexer after you register all your twig extensions.

Craft CMS

For example in Craft CMS you should do something like this. The if statement ensure you don't get 'Unable to register extension "..." as extensions have already been initialized' as error.

// Module.php

if (Craft::$app->request->getIsSiteRequest()) {    
    Event::on(
        Plugins::class,
        Plugins::EVENT_AFTER_LOAD_PLUGINS,
        function (Event $event) {
            $twig = Craft::$app->getView()->getTwig();
            \Performing\TwigComponents\Setup::init($twig, '/components');
        }
    );
}

Testing

composer test

License

The MIT License (MIT). Please see License File for more information.