'Web components with vaadin and rollup with svelte: Primary button ignores theme attribute

Maybe someone tried this before and is able to give me a hint. I have used normal svelte setup (mentioned in the main page) which scaffolds the app;

npx degit sveltejs/template my-svelte-project

I wanted to use vaadin web components in Svelte. I've installed it;

npm install @vaadin/vaadin

the code of main.ts:

<script lang="ts">
    import '@vaadin/button/theme/material'

</script>

<main>
    <vaadin-button theme="primary">Primary</vaadin-button>
    <vaadin-button theme="secondary">Sec</vaadin-button>
</main>

<style>
    main {
        text-align: center;
        padding: 1em;
        max-width: 240px;
        margin: 0 auto;
    }

    @media (min-width: 640px) {
        main {
            max-width: none;
        }
    }
</style>

And the thing is that it almost works :) The buttons are styled, I can click on them but... the theme is ignored;

enter image description here

The primary should have a background color like stated in docs; https://vaadin.com/docs/latest/ds/components/button/#styles

any idea???



Solution 1:[1]

This is happening because of how Svelte sets data on custom elements. If a property exists on the element with the same name as the attribute you set, Svelte will set the property instead of the attribute. Otherwise, it will fall back to the attribute. So, the following...

<vaadin-button theme="primary">Primary</vaadin-button>

...gets compiled to something like:

button.theme = "primary";

Normally this works great, especially when setting array and object properties. However, the vaadin-button styles expect the theme attribute to be set, not the property. Because Svelte sets the property instead, the styles don't apply.

:host([theme~="primary"]) {
  background-color: var(--_lumo-button-primary-background-color, var(--lumo-primary-color));
  color: var(--_lumo-button-primary-color, var(--lumo-primary-contrast-color));
  font-weight: 600;
  min-width: calc(var(--lumo-button-size) * 2.5);
}

I would argue that this is a Vaadin bug - if you expose an attribute and a property for the same data, it shouldn't matter which one the consumer sets. Setting the property should have the same effect as setting the attribute. A quick way to fix this would be for vaadin-button to reflect the theme property, so that setting theme also sets the attribute. Here's how to do that in Lit.

However, that change requires the component library authors to implement it. As a consumer of the library, you can also work around this in Svelte by using an action to force Svelte to set the attribute instead.

<script>
  import "@vaadin/button";

  function setAttributes(node, attributes) {
    for (const [attr, value] of Object.entries(attributes))
      node.setAttribute(attr, value);
  }
</script>

<main>
  <vaadin-button use:setAttributes={{ theme: "primary" }}>Primary</vaadin-button>
  <vaadin-button>Normal</vaadin-button>
</main>

I wrote an article about this behavior and other workarounds at CSS-Tricks, if you want a more in-depth explanation.

Solution 2:[2]

You seem to be importing the Material theme version of the Button component. The "primary" theme variant is only available if you use the default Lumo theme. To import that, use import '@vaadin/button';

For the Material theme, you can use the "outlined" and "contained" theme variants instead: https://cdn.vaadin.com/vaadin-material-styles/1.3.2/demo/buttons.html

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 linto cheeran
Solution 2 Jouni