Skip to content

Introduce a new syntax for twig component #771

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

Conversation

WebMamba
Copy link
Contributor

@WebMamba WebMamba commented Apr 5, 2023

Q A
Bug fix? no
New feature? yes
Tickets
License MIT

Hey all! This PR introduces a new syntax that is more component-oriented 😁

🚨 Just updated this description to feat with the last modification

The problem is: I use components with a lot of parameters, and I use a lot the embedded component feature. So I quickly end up with a hard-to-read template.
So here introduce a new syntax:

<t:myComponent parameter1 parameter2='foo'>

instead of:

{{ component('myComponent', { parameter1: true, parameter2: 'foo' }) }}

The old syntax is not removed. This PR gives the ability to choose.

Here is a more realistic example:

{% extends 'admin.html.twig' %}

{% block dashboard %}
    <t:userDashboard :user="user.id" isAdmin graph="linear" primary>
        <t:block name="actions">
            <t:userActions isAdmin/>
        </t:block>
        <t:block name="footer">
            <t:userDashBoardFooter/>
        </t:block>
    </t:userDashboard>
{% endblock %}

instead of

{% extends 'admin.html.twig' %}

{% block dashboard %}
    {% component 'userDashboard' with {user: user.id, isAdmin: true, graph: 'linear', primary: true} %}
        {% block actions %}
            {{ component('userActions', {isAdmin: 'true'}) }}
        {% endblock %}
        {% block footer %}
            {{ component('userDashboardFooter') }}
        {% endblock %}
    {% endcomponent %}
{% endblock %}

So here is a quick summary:

  • you can use <t:component/>, <t:component></t:component>
  • you also have a special syntax for nested block <t:block name="blockName"></t:block>
  • you can use ':' just before your attribute for a value that should be compiled by twig <t:component :user="user.id"> equal to <t:component :user="{{ user.id }}">
  • you now have a content block by default. For example, if you have:
<t:component :user="user.id">
  <div>
     // my content
  <div>
<t:component/>

then in your component template

{% block content %}
 // your comment will be display here
{% endblock %}

Piouffff!!!! A lot of stuff going on here 😎

This PR is inspired a lot by this library: https://github.com/giorgiopogliani/twig-components

Thanks for your time.
Cheers! 😁

@norkunas
Copy link
Contributor

norkunas commented Apr 5, 2023

Nice. Waiting for this since first time of using twig components :D

Will it be possible to pass arrays/objects as attributes if the component defines it?

@kbond
Copy link
Member

kbond commented Apr 5, 2023

Very nice! I've also wanted this from the beginning!

Some comments/ideas:

  1. I think we'll have to prefix the component tag name (to avoid conflicts with existing html-elements). ie <x-UserDashboard... or maybe <t-UserDashboard...?
  2. Could the following syntax be possible? <UserDashboard :user="user.id"...
  3. <x-block name="actions"> would be awesome! So would default slots...

@WebMamba
Copy link
Contributor Author

WebMamba commented Apr 5, 2023

Hey, thanks for your returns!

Will it be possible to pass arrays/objects as attributes if the component defines it?

Yes of course 😁

I think we'll have to prefix the component tag name (to avoid conflicts with existing html-elements). ie <x-UserDashboard... or maybe <t-UserDashboard...

This is why I uppercase the first letter because I don't think there are any tags starting by uppercase in HTML

Could the following syntax be possible? <UserDashboard :user="user.id"...

I don't know how to do it, but It can be a really really cool feature! I will look at it!

would be awesome! So would default slots...

Yes! super great idea! And this time I know exactly how to do it! 😁

@kbond
Copy link
Member

kbond commented Apr 5, 2023

This is why I uppercase the first letter because I don't think there are any tags starting by uppercase in HTML

I think this could still be a problem if a user also has, say, vue components on the page.

Yes! super great idea! And this time I know exactly how to do it!

Awesome, a default slot concept in twig has always vexed me! Just so we're on the same page, this is what I mean by default slot:

<UserDashboard user="{{ user.id }}" isAdmin graph="linear" primary>
    <div>...</div> <!-- this is the default slot content -->
</UserDashboard>

@norkunas
Copy link
Contributor

norkunas commented Apr 5, 2023

What if we could do?:

{% import_component UserDashboard 'FQCN\to\component' %}

This probably could avoid conflicts?

@WebMamba
Copy link
Contributor Author

WebMamba commented Apr 7, 2023

Hey all! I made some updated base on the previous comment:

1 - New syntax you now prefix your tag block with

    <x-userDashboard>
       ...
    <x-userDashboard/>
  
   </x-userDashboard>

2 - You can now prefix your argument with an ':' in order to pass an object or array or anything that Twig should process

    <x-userDashboard :user='user.id' isAdmin graph='linear' primary>
       ...
    <x-userDashboard/>

3 - You can use a special syntax for block in embedded component

    <x-userDashboard :user='user.id' isAdmin graph='linear' primary>
       <x-block name='actions'>
            <x-userActions isAdmin/>
        <x-block/>
       <x-block name='footer'>
            <x-userDashBoardFooter/>
       <x-block/>
    <x-userDashboard/>

Awesome, a default slot concept in twig has always vexed me! Just so we're on the same page, this is what I mean by default slot

For the default slot I propose to work on this in a next-up PR since we have to make changes out of range of this PR in order to do it 😁

@WebMamba
Copy link
Contributor Author

WebMamba commented Apr 7, 2023

This PR should be ready for review. I need to figure out why all these tests are passing locally but not on the CI

@norkunas
Copy link
Contributor

norkunas commented Apr 8, 2023

That x- is ugly 😔 😅

@norkunas
Copy link
Contributor

norkunas commented Apr 8, 2023

Will it be possible to pass arrays/objects as attributes if the component defines it?

Yes of course grin

Could you add a test for passing an object? 😃

@WebMamba WebMamba force-pushed the webmamba/new_syntax_for_twig_component branch from dd79ad8 to a9f4d9e Compare April 8, 2023 15:01
@yguedidi
Copy link

yguedidi commented Apr 8, 2023

Awesome work!!! bring JSX-like way of writing components to PHP/Twig! I like!
But I must admit I find the x- prefix ugly too 😅

Here some random ideas I have to solve this:

  1. prefix but make it configurable
  2. no prefix and exclude components matching a provided list of forbidden ones (HTML tags, custom HTML tags)
  3. no prefix and assume Twig files will contain only HTML, and WebComponent are using kebab-case for components, so we could support only CamelCase for Twig component
  4. no prefix and forbid only self referencing, e.g. a button Twig component is likely to wrap a <button> HTML tag, so never parse <button> as a Twig component from within the scope of button Twig component
  5. no prefix and documentation to warn that Twig components written this way takes precedence over any HTML custom tag

What do you think?
Me I prefer them from bottom (5) to top (1)

@asispts
Copy link
Contributor

asispts commented Apr 8, 2023

Does this new syntax also support both react and vue components?

@WebMamba
Copy link
Contributor Author

WebMamba commented Apr 8, 2023

So here is what this PR does:

  • Let's say you have the following template:
{% extends 'base.html.twig' %}
 <x-userDashboard :user='user.id' isAdmin graph='linear' primary>
       ...
    <x-userDashboard/>
  • then your render your template as usual
  • but now because of this PR the twig Lexer is decorated. So before Twig parses your template the decorator looks for your tag and replaces that by the traditional syntax {{ component('userDashboard') }}
  • and then the decorator calls Twig and the template is parsed as your never use this syntax

Does this new syntax also support both react and vue components?

So, of course, this new syntax support React and Vue since React and Vue are Js Framework, and here everything happens on the server in the PHP.

That x- is ugly

Please don't use the word ugly to express your opinion on a template syntax.

Actually, there is no real conflict between React and this PR. Tell me if I am wrong but React uses what they call a virtual DOM. So in React, you add your component on this virtual DOM, and then React compiles everything to pure HTML and adds that to the root you are defined. And all of that happens in the js, and your HTML is not aware of this compilation.

Then if you mean the Symfony Ux React and Vue components. There is no conflict your custom tag gonna be parsed in {{ component('userDashboard') }} and you can still use the react_component() function for your react component where you want them to be.

That x- is ugly

Actually, I am not a big fan,and at first, see in the first comment I proposed this syntax
So there is no real conflict by using this syntax . Everything gonna still works, but the question is more do we want people to have potentially the same name for a react and twig component? Or should we provide a syntax for TwigComponent?

The other reason is now we introduce the slot syntax

<x-userDashboard :user='user.id' isAdmin graph='linear' primary>
       <x-block name='actions'>
            <x-userActions isAdmin/>
        <x-block/>
       <x-block name='footer'>
            <x-userDashBoardFooter/>
       <x-block/>
    <x-userDashboard/>

So if we get back on the first syntax: we also have to find a syntax for slot.

I think we gonna use this syntax only in Twig templates. And so even with this syntax it's gonna be clear that it's a TwigComponent.
So I am voting to get back on the first syntax. 😁
What do you think @kbond?

@yguedidi
Copy link

yguedidi commented Apr 8, 2023

Please don't use the word ugly to express your opinion on a template syntax.

Sorry for the offense. 😕
I meant it looks superfluous to me, breaking a bit the readability.

Then if you mean the Symfony Ux React and Vue components. There is no conflict your custom tag gonna be parsed in {{ component('userDashboard') }} and you can still use the react_component() function for your react component where you want them to be.

I completely agree!
My understanding of this feature is that it's a syntax sugar for {{ component('userDashboard') }}, not for {{ react_component('userDashboard') }}.

we also have to find a syntax for slot.

What do you think about kinda mimic Twig syntax?
With something like {% slot 'actions' %}...{% endslot %} and {% slot default %}...{% endslot %}.
It may be possible as the new lexer run before Twig parse the real Twig code

Just realizing the TwigComponent already supports slots 😅
So if I get it correctly we need a solution only for a default slot if we write:

<UserDashboard>
    Content for the default slot
</UserDashboard>

So I am voting to get back on the first syntax.

For what it counts, same vote from me

@weaverryan
Copy link
Member

@WebMamba THANK YOU FOR THIS 😍!!! I have also been wanting this badly, and it's been crawling higher and higher on my list.

I've been on vacation (and I still am for a few days), but I can say a few things quickly:

A) About naming: since we are not the first people to come up with this idea, it likely makes sense to look at how other systems (e.g Laravel) do their naming - https://laravel.com/docs/10.x/blade#components - for Blade components, if you have a component named UserDashboard, they would render it with <x-user-dashboard>. Additionally, like other frontend frameworks, if you have a "prop" named isAdmin, they would render it as is-admin:

<x-user-dashboard is-admin :user='user.id'>

B) About slots, I like the "named" slot (well, you call them "blocks", which likely makes sense) syntax 👍. We definitely need a "default" block syntax, and ideally we would get it all done in one PR. But if needed, it can be added after.

Thank you for this wonderful post-vacation gift!

@norkunas
Copy link
Contributor

norkunas commented Apr 9, 2023

I still have same opinion that we could do like in php/js - import the component under default or aliased name so then we could have many components with the same name.

For example we have material v2 spec components, but v3 is already released, so if we'd add component with the same name I don't know which it would render.

@WebMamba
Copy link
Contributor Author

WebMamba commented Apr 10, 2023

My understanding of this feature is that it's a syntax sugar for {{ component('userDashboard') }}, not for {{ react_component('userDashboard') }}.

yes exactly

Hey Ryan thanks for your review! Have a nice Easter holiday time 🐰
Actually the Blade <x- syntax is not bad for me. But what I don't like with the Blade syntax is having to change your component name and properties name to camelcase. I don't think we have to do that, and I fill this a bit disturbing for the user to not have the same names on his templates and on his php files.
So I think we can just keep the syntax as so:

<x-userDashboard :user='user.id' isAdmin graph='linear' primary>

Or maybe you know the reasons why they made this?

I still have same opinion that we could do like in php/js - import the component under default or aliased name so then we could have many components with the same name.

yes, but let's keep this PR short, I think this is already hard enough to review. But this I agree an important feature. Laravel already solve this, and I like the way they took: https://laravel.com/docs/10.x/blade#manually-registering-package-components

@weaverryan
Copy link
Member

weaverryan commented Apr 11, 2023

But what I don't like with the Blade syntax is having to change your component name and properties name to camelcase.

Hmm, perhaps you're right. I think the motivation from places like Blade is that this is meant to look like an HTML tag... and HTML tags are case-insensitive (and almost always shown in all lowercase). But then React always uses upper camel case. So I think you're right.

Though, if we DO keep it like <x-userDashboard, WDYT about using a : instead: <x:userDashboard? For some reason, having a lowercase x then a - then a string that is NOT lowercase bothers me (it looks like an HTML tag where I can't decide if I want to use upper or lowercase). The <something:else> actually matches the HTML spec for creating a custom element in a "namespace". That won't apply to our situation as the element won't actually be rendered, but there may be pros/cons to using this syntax. Livewire actually uses <livewire:user-dashboard> for reference.

Upper Camel Case Naming Convention?

Related to this topic (but not this PR, sorry - but it's a good time to talk about it) is naming conventions for Twig components. So far, we've done something like this:

#[AsTwigComponent('success_alert')]
class SuccessAlert

So:

PHP class: SuccessAlert
component: success_alert
template: success_alert.html.twig
rendered as: <x-success_alert message="seeya later alligator!">

What does everyone thing about (as a convention) using the class name everywhere:

// maybe the argument is even optional?
#[AsTwigComponent('SuccessAlert')]
class SuccessAlert

So:

PHP class: SuccessAlert
component: SuccessAlert
template: SuccessAlert.html.twig
rendered as: <x-SuccessAlert message="seeya later alligator!">

Thoughts?I don't want to bike shed, just want to see if there is any big consensus one way or another.

@kbond
Copy link
Member

kbond commented Apr 11, 2023

  1. I really like the namespace idea! If we're using a namespace, why not be explicit: <twig:component_name> or <t:component_name> (or allow both or make it configurable). I think this is nice when scanning a twig file - you know exactly what it is.
  2. For the tag name, I think we should keep it simple:
    • Component name: MyComponent: <twig:MyComponent>
    • Component name: my_component: <twig:my_component>
    • Component name: my-component: <twig:myicomponent>
  3. For the attributes, again, I think we should keep it simple (at least to start):
    • <twig:my_component isAdmin> maps to prop $isAdmin
    • <twig:my_component is_admin> fails if prop is $isAdmin

@asispts
Copy link
Contributor

asispts commented Apr 11, 2023

I really like the namespace idea! If we're using a namespace, why not be explicit: twig:component_name or <t:component_name> (or allow both or make it configurable). I think this is nice when scanning a twig file - you know exactly what it is.

I agree with the t: namespace

It's easier to use this convention because we can simply copy and paste from the PHP class name.

PHP class: SuccessAlert
component: SuccessAlert
template: SuccessAlert.html.twig
rendered as: <x-SuccessAlert message="seeya later alligator!">

Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just did some initial testing! Hit some rough patches - but seems like minor stuff.

@WebMamba
Copy link
Contributor Author

WDYT about using a : instead: <x:userDashboard

Agree with you, on this point. Is way much nicer to have: if we don't camel case everything

I made the change to fit this syntax. It looks really as @kbond described it in his last comment 😁

@weaverryan
Copy link
Member

weaverryan commented Apr 12, 2023

Ping @WebMamba - I've taken your excellent work and extended it a bit. Please see WebMamba#1 for a new (hopefully more powerful, but still pretty simple) implementation.

As a BONUS, that implementation adds support for default blocks:

<t:alert type="danger">
    <p>Watch our for the dangerously cool new Twig component syntax</p>
</t:alert>

In this case, the <p> tag becomes a block called default inside the component template :).

@norkunas
Copy link
Contributor

In this case, the <p> tag becomes a block called default inside the component template :).

What if it would be called children like in js land?

@WebMamba WebMamba force-pushed the webmamba/new_syntax_for_twig_component branch from 28fd38b to bd4a214 Compare April 12, 2023 19:42
@weaverryan
Copy link
Member

What if it would be called children like in js land?

Yea, React does this. I think Vue uses slots and doesn't have a default name at all (Blade's default "slot" is also nameless - just $slot)? I want to be as consistent as possible with other things, but I think children might feel more like "children components" whereas in Twig, this is really just "content" (we could call it content). You CAN put child components inside of this default block, but it's really just "content".

@norkunas
Copy link
Contributor

What if it would be called children like in js land?

Yea, React does this. I think Vue uses slots and doesn't have a default name at all (Blade's default "slot" is also nameless - just $slot)? I want to be as consistent as possible with other things, but I think children might feel more like "children components" whereas in Twig, this is really just "content" (we could call it content). You CAN put child components inside of this default block, but it's really just "content".

In DOM it's also children or childNodes:)

@mahono
Copy link

mahono commented Apr 13, 2023

What about using "<ux:" as prefix? (To match the Symfony UX project.)

Somehow I find "t" a bit confusing. Is it "template", is it "twig"..? What has "t" to do with "component"?

@WebMamba
Copy link
Contributor Author

You CAN put child components inside of this default block, but it's really just "content"

I like the naming 'content' as well! I think it's a mistake to be to close the React naming since we took a really different path.

Somehow I find "t" a bit confusing. Is it "template", is it "twig"..? What has "t" to do with "component"

Yes this is t for Twig

@weaverryan
Copy link
Member

Oh I see - you’re looking now at what the component template itself looks like. I’m not sure: so far the special <twig: syntax is used when rendering a component, not inside the component template itself. That doesn’t mean we can’t change that, just mentioning it. And since we are ultimately using blocks everywhere, I kinda like using “block content” in the component template. But I welcome anyone else to disagree!

@kbond
Copy link
Member

kbond commented Apr 13, 2023

I’m not sure: so far the special <twig: syntax is used when rendering a component, not inside the component template itself.

You can choose to use <twig:block name="x"> inside the component template, right?

Anyway, I don't feel very strongly about it. I'm fine leaving as just a special named block (this also allows the twig template to use a standard {% block x %} tag)

@weaverryan
Copy link
Member

You can choose to use <twig:block name="x"> inside the component template, right?

No you can't. It wouldn't be hard to add that (IF we wanted it). But currently, we only even start looking for <twig:block name="x"> if we're inside of a <twig:foo> "tag" already - i.e. when we're currently rendering a component using the new syntax. I think we leave it for now - and call it content. If we find soon that we absolutely hate this or want a fancier syntax, we can change. I think we should introduce this feature as experimental originally.

@WebMamba
Copy link
Contributor Author

@weaverryan just added your code about the default block! 😁

Could you take an attempt at adding some docs for this? My opinion is that we should add a section to the Twig components docs for this "HTML Component Syntax

Yeap sure I will open a PR for it!

Keep in mind we have to make it known that this syntax is not supported by live components (...yet 😄)

Good catch 😁

I agree with Ryan on this one, 'content' feels more apparent. Maybe we can add an error if someone tries to do <:t block="content"> we can raise an error like block content is reserved world, please choose another block name. 😁

@kbond
Copy link
Member

kbond commented Apr 13, 2023

No you can't.

Ahh, ok, got it.

I agree with Ryan on this one, 'content' feels more apparent.

Ok, let's go with content

Maybe we can add an error if someone tries to do <:t block="content"> we can raise an error like block content is reserved world, please choose another block name.

Let's save that for a followup PR

@WebMamba, could you adjust this PR's description to show the updated syntax and what's possible with default blocks?

@WebMamba
Copy link
Contributor Author

WebMamba commented Apr 13, 2023

@WebMamba, could you adjust this PR's description to show the updated syntax and what's possible with default blocks?

@kbond Done! 😁

And I made the change to content from default! 😁

@kbond
Copy link
Member

kbond commented Apr 13, 2023

t: => twig:?

@WebMamba
Copy link
Contributor Author

t: => twig:?

voting for t

@kbond
Copy link
Member

kbond commented Apr 13, 2023

Support both?

@mahono
Copy link

mahono commented Apr 14, 2023

Support both?

To be honest I was thinking about providing a way to allow custom namespaces. Could be interesting when someone builds a CMS or something on top of that and wants to "rebrand" the prefix for their components.

weaverryan added a commit that referenced this pull request Apr 14, 2023
…nal name (weaverryan)

This PR was squashed before being merged into the 2.x branch.

Discussion
----------

[TwigComponent] Change component naming standard + optional name

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| Tickets       | None
| License       | MIT

Changes the naming convention of components to upper camel case + makes the `name` argument optional (defaults to class name). Components now look like:

```php
    #[AsTwigComponent]
    class Alert
    {
        public string $type = 'success';
        public string $message;
    }
```

The template is `templates/components/Alert.html.twig` and you render with `{{ component('Alert') }}`. This removes the need for the user to invent & keep track of an arbitrary name, but they *can* still pass a name to `AsTwigComponent`. No BC break on this.

Relates to a conversation on #771 (comment)

TODO:

* [ ] Update MakerBundle to follow this convention

Commits
-------

8dc9a7d [TwigComponent] Change component naming standard + optional name
@weaverryan
Copy link
Member

I'd vote for twig: - a lot of extra clarity of "wtf is that tag! Is that some Vue component, some custom HTML element?" for just 3 extra chars.

To be honest I was thinking about providing a way to allow custom namespaces. Could be interesting when someone builds a CMS or something on top of that and wants to "rebrand" the prefix for their components.

Definitely this is something we need to think about, but probably in another PR.

If some CMS wants to add new components under some sort of a namespace, that should also affect the way the component is used with the simple syntax {{ component() }}. For example, perhaps we add the ability to make something like {{ component('MyCMS:Alert') }} (actually, other than the fact that this component would need to specify a custom template name so that it doesn't have a :, this should already be possible). Naturally, with the new syntax, that would be come <twig:MyCMS:Alert>. Do we allow that to become <MyCMS:Alert>. Maybe? But definitely for later.

WebMamba added a commit to WebMamba/ux that referenced this pull request Apr 14, 2023
WebMamba added a commit to WebMamba/ux that referenced this pull request Apr 14, 2023
@WebMamba
Copy link
Contributor Author

@kbond @weaverryan just updated to have the syntax with the twig prefix 😁 Maybe in a following PR I will make a proposal to support both syntaxes 😇

Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few super minor last things. Also - could you add an entry in the CHANGELOG for 2.8 for TwigComponent?

There is also a failing test for DeterministicTwigIdCalculatorTest. This is actually highlighting a problem. With the new setup, TwigEnvironmentConfigurator::configure() instantiates new ComponentLexer($environment), which extends the core Lexer. The actually causes the Lexer __construct() code to run earlier than it would have before. Hopefully this won't be an issue in real apps - as I don't see a way to work around this currently.

Anyways, to fix the test, we probably need to register the test-only get_id_for_test twig extension inside the Kernel itself - there is Kernel.php file in the TwigComponent test directory where we would wire this in properly.

@weaverryan
Copy link
Member

Btw, if it helps, here's the test fix - WebMamba#2 :)

@WebMamba
Copy link
Contributor Author

Great thanks @weaverryan! Everything is green now! 😁

@weaverryan weaverryan force-pushed the webmamba/new_syntax_for_twig_component branch from c1c5ce9 to 0f14b03 Compare April 16, 2023 23:27
@weaverryan weaverryan force-pushed the webmamba/new_syntax_for_twig_component branch from 0f14b03 to 371edad Compare April 16, 2023 23:29
@weaverryan
Copy link
Member

Thank you @WebMamba and @giorgiopogliani for the original inspiration!

@weaverryan weaverryan merged commit 867ce06 into symfony:2.x Apr 16, 2023
weaverryan added a commit that referenced this pull request Apr 16, 2023
This PR was squashed before being merged into the 2.x branch.

Discussion
----------

Add docs for the new Twig Component syntax

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| Tickets       |
| License       | MIT

see #771

Commits
-------

11047c3 Add docs for the new Twig Component syntax
@WebMamba
Copy link
Contributor Author

Thanks @weaverryan for your big help on this one! Thanks all for your reviews! 😁

weaverryan added a commit that referenced this pull request Apr 21, 2023
…ples, few fixes (weaverryan)

This PR was merged into the 2.x branch.

Discussion
----------

[Site] More Functional Code, 2x Complex Live Components Examples, few fixes

| Q             | A
| ------------- | ---
| Bug fix?      | yes (with respect to Twig errors)
| New feature?  | no
| Tickets       | None
| License       | MIT

Hi!

Prepping ux.symfony.com for 2.8 - very excited about this! Join me on a tour:

## 1) Invoice Creator Live Component Demo

https://user-images.githubusercontent.com/121003/232886502-7f8da8f5-fe8a-4251-8e92-c2b56895b1ee.mp4

Parent component + collection of child components communicating by emitting events!

## 2) Product form + modal to create a Category

https://user-images.githubusercontent.com/121003/232888282-ab12c4a1-8153-4fe5-babf-cbf4a313c47b.mp4

Opens a Bootstrap modal with a child component inside - and closes that modal from a `LiveAction`.

### 3) Much nicer code blocks

Before:

<img width="609" alt="Screenshot 2023-04-18 at 3 45 34 PM" src="https://user-images.githubusercontent.com/121003/232888991-67cad476-6836-4b10-9eb5-1ec6b43aafc6.png">

After:

<img width="604" alt="Screenshot 2023-04-18 at 3 45 41 PM" src="https://user-images.githubusercontent.com/121003/232889021-01efedd9-c062-4072-a120-1b437d342634.png">

* "Copy" button
* Link to view the file on GitHub
* use statements are collapsed (click to show them)
* "Expand code" to show longer code blocks

### 4) Explanations on longer examples

Some examples deserve pointing out a few of the more complex parts. Some of the live component demos now do this:

<img width="443" alt="Screenshot 2023-04-18 at 3 48 42 PM" src="https://user-images.githubusercontent.com/121003/232889344-3a776683-40a5-4ef9-8fa7-d909343f563a.png">

### 5) Using a LOT of new features

[Smart rendering](https://symfony.com/bundles/ux-live-component/current/index.html#the-smart-re-render-algorithm), [emitting events](https://symfony.com/bundles/ux-live-component/current/index.html#communication-between-components-emitting-events), [browser events](https://symfony.com/bundles/ux-live-component/current/index.html#dispatching-browser-javascript-events), etc, etc - MANY new features are being used on the site now.

We're also using (in som
e places) the new `<twig:Component>` syntax from #771. Even though editor support (e.g. for auto-completion) doesn't exist yet, I LOVE this. For example, to render a code block:

```html
<twig:CodeBlock filename="src/Twig/SearchPackages.php" />

{# or more complex - logic for extracting" a specific Twig block lives in the CodeBlock.php component #}
<twig:CodeBlock
    filename="templates/main/homepage.html.twig"
    targetTwigBlock="markdown_example"
    :showTwigExtends="false"
    :stripExcessHtml="true"
/>
```

Thanks everyone for the work, review & testing on a lot of this new stuff. Using the new features on the site has been BLAST.

Commits
-------

e6edbde [Site] Adding InvoiceCreator live demo + modal demo
fullstackdeveloperwebapp added a commit to fullstackdeveloperwebapp/ux that referenced this pull request Aug 1, 2023
…nal name (weaverryan)

This PR was squashed before being merged into the 2.x branch.

Discussion
----------

[TwigComponent] Change component naming standard + optional name

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| Tickets       | None
| License       | MIT

Changes the naming convention of components to upper camel case + makes the `name` argument optional (defaults to class name). Components now look like:

```php
    #[AsTwigComponent]
    class Alert
    {
        public string $type = 'success';
        public string $message;
    }
```

The template is `templates/components/Alert.html.twig` and you render with `{{ component('Alert') }}`. This removes the need for the user to invent & keep track of an arbitrary name, but they *can* still pass a name to `AsTwigComponent`. No BC break on this.

Relates to a conversation on symfony/ux#771 (comment)

TODO:

* [ ] Update MakerBundle to follow this convention

Commits
-------

8dc9a7d0 [TwigComponent] Change component naming standard + optional name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants