Mathias
Mathias

Reputation: 324

Vaadin ComboBox set text-field width to 0 (CSS shadow dom)

I use a Vaadin ComboBox to create a dropdown menu, where the user can set a state which will be displayed in another element of the web page. So I really do not need the text-field-part of the ComboBox (the blue line in the image).

This is how it looks like now. The blue line should disappear.

Setting the width manually to 0 in the browser gives the perfect result (no line visible, no text input area available for focus), however I am unable to achieve this using code. Please help me.

I used the example in this tutorial (see vaadin-text-field-styles.css), which changes all ComboBoxes on my web page. The current status looks like this:

//Java-code:
comboBox.addClassName("RemoveTextField");

HTML-stack

/* CSS-File */
:host([class="RemoveTextField"]) [part="input-field"] {
    width: 0px;
}

The CSS rule is not used, I guess the problem is that the .host-selector is not working as I think. As I am a CSS noob please enlighten me how I can use a selector for an element outside the shadow dom.

Upvotes: 3

Views: 744

Answers (1)

Erik Lumme
Erik Lumme

Reputation: 5342

See the end for an alternative solution.

Styling is a bit tricky when you are dealing with nested shadow roots. The part input-field is inside the shadow root of vaadin-text-field, which is inside the shadow root of vaadin-combo-box. As such, it can't be styled from the combo box.

What you can do is create some styles for the text field, like this text-styles.css:

[part="input-field"] {
    width: 0;
}

Next, you can apply this to all text fields by adding this annotation to a Flow view:

@CssImport(value = "text-styles.css", themeFor = "vaadin-text-field")

Now all your input fields have zero width. In order to have it apply only to the text field in your combo box, you can set the theme attribute on it:

myComboBox.getElement().setAttribute("theme", "my-combo");

Then you can update your text-styles.css:

:host([theme="my-combo"]) [part="input-field"] {
    width: 0;
}

So how does this work?

All Vaadin web components implement a ThemableMixin, that does a couple of things:

  1. It enables you to use the themeFor="..." in your @CssImport to inject styles into the shadow root of a Vaadin component.
  2. It propagates any theme attribute you set on the component to any child components inside the shadow root.

In the browser developer tools you will see that the theme attribute has propagated to the vaadin-text-field, and therefore we can use it to limit the scope of our styles. Only the theme attribute is propagated, it will not work with classes, ids etc.

A screenshot of the DOM with the theme attribute propagated from the combo box to the text field

If you were to look into the highlighted style tag, you would also find that the contents of the text-styles.css have been injected there (although the contents might be too long for the devtools to show).

Alternative solution

A combo box might not be the best component for this. Have a look at the MenuBar or ContextMenu.

Upvotes: 4

Related Questions