From 010e074a9ed3214cecdb52fc7512104c1ac909e3 Mon Sep 17 00:00:00 2001 From: "totally-not-ai[bot]" <290682512+totally-not-ai[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2026 19:27:36 +0200 Subject: [PATCH] docs: add Tree Grid subtree highlight example (#6211) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a **Recipes** sub-page to the Tree Grid documentation (`articles/components/tree-grid/recipes.adoc`), with a **Highlighting a Subtree** (Flow) section as its first recipe. The new rendered `TreeGridSubtreeHighlight` example gives every descendant of the selected row a `selected-subtree` part name. The part name generator checks whether the selected item is an ancestor of the rendered item. Because part names are generated only when a row is rendered, the selection listener refreshes the descendants of both the previously and the newly selected item. The styling (`tree-grid-subtree-highlight.css`, imported in `styles.css`) sets two properties on `vaadin-grid::part(selected-subtree)`, because the themes use different ones for the cell background: - `--vaadin-grid-cell-background-color` for Aura - `--vaadin-grid-cell-background` for Lumo This PR also adds the `vaadin-grid-tree-toggle` import to `tree-grid-imports.ts`, the preimport for Java-only Tree Grid examples. Without it, the hierarchy column showed no toggles on pages where no Lit example imports the tree column. This change was split out of #6188. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: totally-not-ai[bot] <290682512+totally-not-ai[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 Co-authored-by: Sascha Ißbrücker --- articles/components/tree-grid/recipes.adoc | 36 +++++++++ .../component/tree-grid/tree-grid-imports.ts | 1 + frontend/themes/docs/styles.css | 1 + .../docs/tree-grid-subtree-highlight.css | 9 +++ .../treegrid/TreeGridSubtreeHighlight.java | 73 +++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 articles/components/tree-grid/recipes.adoc create mode 100644 frontend/themes/docs/tree-grid-subtree-highlight.css create mode 100644 src/main/java/com/vaadin/demo/component/treegrid/TreeGridSubtreeHighlight.java diff --git a/articles/components/tree-grid/recipes.adoc b/articles/components/tree-grid/recipes.adoc new file mode 100644 index 0000000000..ca94801fde --- /dev/null +++ b/articles/components/tree-grid/recipes.adoc @@ -0,0 +1,36 @@ +--- +title: Recipes +page-title: Tree Grid recipes for common use cases | Vaadin components +description: Examples that combine Tree Grid features to solve common use cases. +meta-description: Examples that combine Tree Grid features to solve common use cases. +order: 60 +--- + += Tree Grid Recipes + +This page contains examples that combine Tree Grid features to solve common use cases. + + +== Highlighting a Subtree [badge-flow]#Flow# + +Custom part names can depend on the position of an item in the hierarchy. In the example below, selecting a row highlights all of its descendants with a `selected-subtree` part name. The part name generator checks whether the selected item is an ancestor of the rendered item. Because part names are generated only when a row is rendered, the selection listener refreshes the descendants of both the previously and the newly selected item. + +[.example,themes="lumo,aura"] +-- +[source,typescript] +---- +include::{root}/frontend/demo/component/tree-grid/tree-grid-imports.ts[preimport,hidden] +---- + +[source,java] +---- +include::{root}/src/main/java/com/vaadin/demo/component/treegrid/TreeGridSubtreeHighlight.java[render,tags=snippet,indent=0] +---- + +[source,css] +---- +include::{root}/frontend/themes/docs/tree-grid-subtree-highlight.css[] +---- +-- + +See <<../grid/styling#part-name-generator,Dynamically Styling Rows & Columns>> for more information about custom part names. diff --git a/frontend/demo/component/tree-grid/tree-grid-imports.ts b/frontend/demo/component/tree-grid/tree-grid-imports.ts index 2effb98775..6061046ba9 100644 --- a/frontend/demo/component/tree-grid/tree-grid-imports.ts +++ b/frontend/demo/component/tree-grid/tree-grid-imports.ts @@ -1,5 +1,6 @@ import 'Frontend/demo/init'; import '@vaadin/grid'; +import '@vaadin/grid/vaadin-grid-tree-toggle.js'; import '@vaadin/select'; // This file only has the required imports for the Java-only example diff --git a/frontend/themes/docs/styles.css b/frontend/themes/docs/styles.css index 26691b6df1..dc9b521360 100644 --- a/frontend/themes/docs/styles.css +++ b/frontend/themes/docs/styles.css @@ -11,6 +11,7 @@ @import './grid-cell-focus.css'; @import './grid-styling.css'; @import './grid-header-footer-styling.css'; +@import './tree-grid-subtree-highlight.css'; @import './menu-bar-class-name.css'; @import './message-list-class-name.css'; @import './multi-select-combo-box-chip-class-name.css'; diff --git a/frontend/themes/docs/tree-grid-subtree-highlight.css b/frontend/themes/docs/tree-grid-subtree-highlight.css new file mode 100644 index 0000000000..d3ce867573 --- /dev/null +++ b/frontend/themes/docs/tree-grid-subtree-highlight.css @@ -0,0 +1,9 @@ +/* Add this to your global CSS, for example in: */ +/* src/main/resources/META-INF/resources/styles.css */ + +vaadin-grid::part(selected-subtree) { + /* Aura */ + --vaadin-grid-cell-background-color: color-mix(in srgb, currentColor 4%, transparent); + /* Lumo */ + --vaadin-grid-cell-background: color-mix(in srgb, currentColor 4%, transparent); +} diff --git a/src/main/java/com/vaadin/demo/component/treegrid/TreeGridSubtreeHighlight.java b/src/main/java/com/vaadin/demo/component/treegrid/TreeGridSubtreeHighlight.java new file mode 100644 index 0000000000..ea691f9a44 --- /dev/null +++ b/src/main/java/com/vaadin/demo/component/treegrid/TreeGridSubtreeHighlight.java @@ -0,0 +1,73 @@ +package com.vaadin.demo.component.treegrid; + +import com.vaadin.demo.DemoExporter; // hidden-source-line +import com.vaadin.demo.domain.DataService; +import com.vaadin.demo.domain.Person; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.treegrid.TreeGrid; +import com.vaadin.flow.data.provider.hierarchy.HierarchicalDataProvider.HierarchyFormat; +import com.vaadin.flow.data.provider.hierarchy.TreeData; +import com.vaadin.flow.data.provider.hierarchy.TreeDataProvider; +import com.vaadin.flow.router.Route; + +@Route("tree-grid-subtree-highlight") +public class TreeGridSubtreeHighlight extends Div { + + private final TreeGrid treeGrid = new TreeGrid<>(); + private final TreeData treeData = new TreeData<>(); + + public TreeGridSubtreeHighlight() { + treeData.addItems(DataService.getManagers(), + manager -> DataService.getPeople(manager.getId())); + treeGrid.setDataProvider( + new TreeDataProvider<>(treeData, HierarchyFormat.FLATTENED)); + treeGrid.addHierarchyColumn(Person::getFullName).setHeader("Full name"); + treeGrid.addColumn(Person::getProfession).setHeader("Profession"); + + // tag::snippet[] + treeGrid.setPartNameGenerator(person -> { + Person selected = treeGrid.asSingleSelect().getValue(); + return isDescendantOf(person, selected) ? "selected-subtree" : null; + }); + + treeGrid.asSingleSelect().addValueChangeListener(event -> { + // Regenerate the part names of the previous and new subtree + refreshDescendants(event.getOldValue()); + refreshDescendants(event.getValue()); + }); + // end::snippet[] + + treeGrid.expand(DataService.getManagers().get(0)); + add(treeGrid); + } + + // tag::snippet[] + private boolean isDescendantOf(Person person, Person ancestor) { + if (ancestor == null) { + return false; + } + Person parent = treeData.getParent(person); + while (parent != null) { + if (parent.equals(ancestor)) { + return true; + } + parent = treeData.getParent(parent); + } + return false; + } + + private void refreshDescendants(Person person) { + if (person == null) { + return; + } + for (Person child : treeData.getChildren(person)) { + treeGrid.getDataProvider().refreshItem(child); + refreshDescendants(child); + } + } + // end::snippet[] + + public static class Exporter // hidden-source-line + extends DemoExporter { // hidden-source-line + } // hidden-source-line +}