SymfonyCasts / 30-days-last

Screencast code, script and glitter behind the "30 Days with LAST Stack" tutorial
https://symfonycasts.com/screencast/30-days-last
Other
7 stars 11 forks source link

Twig components in form types #1

Open alexz707 opened 3 months ago

alexz707 commented 3 months ago

Hey @weaverryan ! thanks for making this great course!

I'm trying to set up a new project using tailwind with the flowbite-bundle and symfony ux components. I've created the Button component from the tutorial with some css classes so it looks like the flowbite admin dashboard and works really fine as long as I just use twig templates.

Now I would like to use a form type class e.g. ChangePasswordType.php. In that class i have added a button

->add('submit', SubmitType::class, [
                'label' => 'label.update_password',
                'row_attr' => ['class' => 'col-span-6 sm:col-full'],
            ])

How can I use my button component to get the correct classes? Because now it uses the twig templates from flowbite-bundle and I would need to overwrite these entries manually:

{%- block button_widget -%}
    {%- set attr = attr|merge({class: (attr.class|default(block('class_button')))|trim}) -%}
    {{- parent() -}}
{%- endblock button_widget %}

{% block class_button -%}
    text-gray-900 bg-white font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 border border-gray-200 hover:text-blue-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:bg-gray-800 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 dark:focus:ring-gray-700
{%- endblock class_button %}

My button component looks like this:

<{{ tag }}{{ attributes.defaults({
    class: 'font-medium rounded-lg text-center focus:ring-4 focus:outline-none me-2 mb-2 '~this.sizeClasses~' '~this.variantClasses
}) }}>
    {% block content %}{% endblock %}
</{{ tag }}>
<?php

namespace App\Twig\Components;

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent]
final class Button
{
    public string $variant = 'primary';
    public string $tag = 'button';
    public string $size = 'md';

    public function getVariantClasses(): string
    {
        return match ($this->variant) {
            'primary' => 'text-white bg-primary-700 hover:bg-primary-800 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800',
            default => throw new \LogicException(sprintf('Unknown button type "%s"', $this->variant)),
        };
    }

    public function getSizeClasses(): string
    {
        return match ($this->size) {
            'md' => 'px-5 py-2.5 text-sm',
            default => throw new \LogicException(sprintf('Unknown button size "%s"', $this->size)),
        };
    }
}

So currently I would need to overwrite the flowbite template and would have the css definition in two places - in the button component as well as in the forms template.

Maybe I missunderstood something but I could not find out how to use just the components ;-) What is the best way to do this?

Best regards Alex

bocharsky-bw commented 3 months ago

Hey @alexz707 ,

The best way probably is to not use that SubmitType::class at all and instead put the button component manually in your form :)

Otherwise, you would need to override some core form templates which would lead to some duplications or code complications.

Cheers!

alexz707 commented 3 months ago

Hey @bocharsky-bw,

thanks for your answer. Of course I could remove the button and use the component in the template but that just hides the problem I guess ;)

What if I want to style other elements by using components. currently as you mentioned the only way would be to edit the styles (or whatever you want to change) in 2 different locations.

So using the components is only 50% "of the job" are there any plans or ideas to get to 100% ?

Best regards alex

bocharsky-bw commented 3 months ago

Hey @alexz707 ,

This sounds fair, but fairly speaking i'm not sure about it. The problem is that there're 2 different "syntax" or how to name it, form themes has their own syntax for the windgets, etc, and you can't just re-use the same HTML code for both. What about styles (in specific, CSS classes) - it's easier I think. You can probably set it on a var and reuse it in both places. I'm not sure how that should work out of the box, but sure, it would be good to have some. If you have any ideas, or want to help with it by contributing into Symfony - PRs are warmly welcome.