How to create own tagged component and load component.css inside of <theme>/components/ ?

hi guys,
i have my custom component (also tried with LitTemplate)

@Tag("svg-icon")
@CssImport(value = "./components/svg-icon.css")
public class SvgWrapper extends Component implements HasSize, HasTheme, ClickNotifier<SvgWrapper>, HasOrderedComponents {

    public SvgWrapper(PlanSvgIntf plainSvg) {
        super();
        this.getThemeNames().add(plainSvg.getSvgVariant());
        this.setSvgContent(plainSvg);
    }

    public void setSvgContent(PlanSvgIntf svgContent) {

        this.getElement().getNode().runWhenAttached(ui -> {
            ui.beforeClientResponse(this, executionContext -> {
                this.getElement().setProperty("innerHTML", svgContent.getPlainSvg());
            });
        });

    }
}

by import that css file from frontend/components/svg-icon.css my css is loaded, but is classic css :frowning_with_open_mouth:
i want to add shadow-dom css, to use LitTemplate.

so i defined my svg-icon.css in frontend/themes/mytheme/components/svg-icon.css - where i already overwritten other vaadin-themed components
( see attachment screen)
so, here is my css from the components folder:

:host {
  display: flex;
  justify-content: center;
}

i also can see, that in the frontend-generated theme.js that the import is generated
import svgIconCss from 'themes/lumodark/components/svg-icon.css?inline';

so, when using

@Tag("svg-icon")
public class SvgWrapper extends Component implements HasSize, HasTheme, ClickNotifier<SvgWrapper>, HasOrderedComponents {

...
} 

the CSS is not applied. :frowning_with_open_mouth:
i did not found anything about mixing customcomponent and custom component styles.
Any ideas, what i missed?
image.png

the generated js includes also the other registration part

registerStyles(
      'svg-icon',
      unsafeCSS(svgIconCss.toString())
    );
    registerStyles(
      'vaadin-app-layout',
      unsafeCSS(vaadinAppLayoutCss.toString())
    );
    registerStyles(
      'vaadin-context-menu-item',
      unsafeCSS(vaadinContextMenuItemCss.toString())
    );
    registerStyles(
      'vaadin-context-menu-list-box',
      unsafeCSS(vaadinContextMenuListBoxCss.toString())
    );
    registerStyles(
      'vaadin-drawer-toggle',
      unsafeCSS(vaadinDrawerToggleCss.toString())
    );
    registerStyles(
      'vaadin-menu-bar-button',
      unsafeCSS(vaadinMenuBarButtonCss.toString())
    );

but as you can see on the screen, nothing of css is applied :frowning_with_open_mouth:
any help would be appriciate
image.png

The js side of your component has to support it. It has something to do with ThemeableMixing or so, but that’s all I know by hand

Here I don’t see any webcomponent, so there is no shadow Dom. In your case you can just replace :host to svg-icon in your css ans use light dom

I don’t recommend to use the themable-mixin. It’s specific to Vaadin and inject css inside the shadow Dom to allow change in the private structure of your component.

It’s much better to use :part which is standard ( and now supported by the browsers)

( edit: no that’s an error)

what you mean with “the js side of your component” ?
if you mean the LitElement ts file, this is it.

import {css, html, LitElement } from 'lit';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';

export class SvgIcon extends ThemableMixin(LitElement) {
  // @property()
  // innerContent = "";


  static get styles() {
    return css`
      :host {
        /* Styles for the <my-view> host element */
        display: flex;
      }
    `;
  }

  render() {
    return html`<slot name="content"></slot>`;
  }
}

customElements.define('svg-icon', SvgIcon);

but also nothing happend, when using:

@Tag("svg-icon")
@JsModule("./templates/svg-icon.ts")
public class SvgWrapper extends LitTemplate implements HasSize, HasTheme, ClickNotifier<SvgWrapper>, HasOrderedComponents {

    public SvgWrapper(PlanSvgIntf plainSvg) {
        super();
        this.getThemeNames().add(plainSvg.getSvgVariant());
        this.setSvgContent(plainSvg);
        this.setWidth(plainSvg.getDefaultWidth());
        this.setHeight(plainSvg.getDefaultHeight());
    }

    public void setSvgContent(PlanSvgIntf svgContent) {

      ...
    }

i only get the css from the .ts file
image.png

@faithful-emu
that is what i am doing currently :frowning_with_open_mouth:
by using @CssImport(value = "./components/svg-icon.css") and using

svg-icon {
  display: flex;
  justify-content: center;
}

but hoped, i can place in in the theme to have theme based styles.

@faithful-emu is totally right here - with the upcoming V24+ it would be way better on the long run to go without the internal styling API of Vaadin and instead go with the part API.

Instead of providing a CssImport in Java, it should be enough to just place your css file within your theme folder and import it from styles.css

so the <theme>/components/*.css is only for vaadin components?

With this js component, it should load the css properly. But you need to add the Jsmodule in your java code. Maybe something is not loaded properly ( like the component), or something I didn’t see in the code.

/components has been created because the browsers didn’t support a way to style webcomponent. With this, it’s not necessary: ::part() - CSS: Cascading Style Sheets | MDN

ok understood that ::part() … is like the ::slot()
so, to have the theme-based support, i place the CSS file with the

svg-icon {
  display: flex;
  justify-content: center;
}

into my theme and let import it by the styles.css?

Yes

ok, thanks @faithful-emu will try it :slightly_smiling_face:

btw i lust liked the v14 … but with v23 it’s one level more easier to use vaadin, custom css, custom components etc :slightly_smiling_face:
also nice documentations :slightly_smiling_face: so, the VTeam did a great job here :slightly_smiling_face: many thanks for that framework

ok, with that import in the theme and using tag names, seems its working :slightly_smiling_face:
Tanks for your advises @quirky-zebra and @faithful-emu :slightly_smiling_face:
:heart_eyes:
image.png

https://tenor.com/view/thumbs-up-okay-good-great-job-good-job-gif-17699355