leptos-rs / leptos

Build fast web applications with Rust.
https://leptos.dev
MIT License
15.94k stars 628 forks source link

Using multiple `class` props on elements causes the last class props overwrite other classes #3032

Open sabify opened 2 days ago

sabify commented 2 days ago

Describe the bug

Using multiple class props on elements causes the last class prop overwrite other class props when navigating back to the element.

Leptos Dependencies

leptos = 0.6.15

To Reproduce

  1. Write a component that has an element with multiple class prop. Assume we have a sign in page and a home page with appropriate route to /signin and / respectively.

Element example in /signin:

<button
    type="submit"
    class="py-2 px-4 text-sm font-medium rounded-md border"
    class="flex relative justify-center w-full"
>
    continue
</button>
  1. Open /signin and everything works as expected and we have merged classes: class="py-2 px-4 text-sm font-medium rounded-md border flex relative justify-center w-full"
  2. Now navigate to home page and then go back to /signin
  3. The issue arises when last class prop overwrites others: class="flex relative justify-center w-full"

Expected behavior We should have merged classes when navigating back to components: class="py-2 px-4 text-sm font-medium rounded-md border flex relative justify-center w-full".

gbj commented 2 days ago

This is not intended to work, when rendering either on the server or in the browser. I would classify the fact that it does work during SSR as a bug, but not one that I will likely spend time going back and fixing at this point.

It explicitly errors in the view macro in 0.7.

sabify commented 1 day ago

Thanks for the explanation. You are right, it only works in SSR mode.

Can we have an attributes/props fusion feature for selected ones like class, style and others? By doing this we can have different logic for at least static attributes/props. This can be helpful in applying patterns on elements.

let button_layout = "py-2 px-4 text-sm font-medium rounded-md border";

// Button1
view! {
<button
    type="submit"
    class=button_layout
    class="flex relative justify-center w-full"
>
    continue
</button>
}

// Button2
view! {
<button
    type="reset"
    class=button_layout
    class="grid mt-8 items-center w-1/2"
>
    reset
</button>
}

I'm aware of formatting strings, but this approach could be much cleaner and tooling compatible, or I'm missing something here...

gbj commented 1 day ago

format!() is definitely the way to go here, i.e., class=format!("flex relative justify-center w-full {button_layout}"). I'm not sure I understand what you mean by "cleaner and tooling compatible," maybe there's something I'm missing.