Styling grid cell components when hovering over the grid row - Can't figure

From what I can tell, the only way to style a specific grid row is to use the grid shadow dom and target rows there, which works fine. But I have a grid column with buttons in it, that I want to style when a user hovers over the row that contains them, but I can’t figure out how to select them in CSS. The shadow dom for the table contains a with a component underneath it. I can select that component via the ::slotted() pseudo element, but I can’t select the vaadin-button components that are within it because ::slotted() seems to only accept a single level of selectors (per the documentation and confirmed in my tests).

And I can’t style the buttons or the grid cell directly because they can’t reference the hover state of the row.

Is there any way to accomplish this?

Hi Dan!

It is indeed complicated to achieve this. The way to go is to utilize CSS custom properties.

For vaadin-grid shadow dom styles:

[part="row"]
:not(:hover) {
  --row-button-visibility: hidden;
}

For vaadin-button shadow dom styles:

:host {
  visibility: var(--row-button-visibility);
}

Note, that I didn’t actually try this for real, so there might be some things you need to tweak. But the concept should work.

Ah ha! I had never thought to use custom properties this way. I have not tested it, but I assume the custom properties must not be scoped to the individual components if they are able to be used like this.

I will test your method, but I was also able to implement another method that may be of help to others, which is to hide the entire grid cell as opposed to elements within it. This works because you can reference the vaadin-grid-cell-content. Though your method is more robust.

[id="items"]
 [part="row"]
  [part~="body-cell"]
.hidden-button-column ::slotted(vaadin-grid-cell-content) {
	visibility:hidden;
	opacity:0;
}

[id="items"]
 [part="row"]
:hover  [part~="body-cell"]
.hidden-button-column ::slotted(vaadin-grid-cell-content) {
	visibility:visible;
	opacity:1;
}