[Tree widget]: header buttons adjustments on next - #1751
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request updates the Models and Categories tree header button behavior to be more consistent and cancellable by running visibility changes through a buffered viewport workflow, while also improving plan projection model detection so the 2D/3D toggle state correctly reflects what’s displayed.
Changes:
- Refactors Models/Categories header actions (show/hide/invert) to use buffered, cancellable visibility operations and updated visibility utilities.
- Improves 2D/3D toggle logic by detecting plan projection models and reacting to displayed-model changes.
- Expands
VisibilityUtilsunit test coverage for the new buffered visibility behaviors.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/tree-widget/src/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.tsx | Updates model header buttons to use buffered visibility operations and fixes 2D/3D toggle detection/state. |
| packages/tree-widget/src/tree-widget-react/components/trees/common/Utils.ts | Removes old visibility helpers relocated to internal visibility utilities. |
| packages/tree-widget/src/tree-widget-react/components/trees/common/internal/VisibilityUtils.ts | Introduces buffered/cancellable visibility operations (show/hide/invert) and category display modification utilities. |
| packages/tree-widget/src/tree-widget-react/components/trees/common/internal/Utils.ts | Adds setIntersection helper used by plan projection model detection. |
| packages/tree-widget/src/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.ts | Adds plan projection model query/caching and intersects results with cached model set. |
| packages/tree-widget/src/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.ts | Exposes getPlanProjectionModels() through BaseIdsCache. |
| packages/tree-widget/src/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.tsx | Refactors category header buttons to use buffered/cancellable visibility operations and category info mapping. |
| packages/tree-widget/src/test/trees/common/internal/VisibilityUtils.test.ts | Updates and expands tests for the new visibility utilities and cancellation behavior. |
| change/@itwin-tree-widget-react-c3197d23-0763-4d55-a452-0716c6140208.json | Adds changelog entry for the behavior consistency update and 2D toggle fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Tree-Widget Next benchmark
| Benchmark suite | Current: 7c71de8 | Previous: 9ab33ea | Deviation | Status |
|---|---|---|---|---|
models tree 50k 3D elements search > get search paths |
1413 ms |
1326 ms |
6.56% |
〰️ |
models tree 50k 3D elements search > get search paths (P95 of main thread blocks) |
60 ms |
50 ms |
20% |
〰️ |
models tree 50k 3D elements search > load hierarchy from search paths |
123619 ms |
115619 ms |
6.92% |
〰️ |
models tree 50k 3D elements search > load hierarchy from search paths (P95 of main thread blocks) |
44 ms |
38 ms |
15.79% |
〰️ |
models tree 50k categories > collect nodes |
2998 ms |
2961 ms |
1.25% |
〰️ |
models tree 50k categories > collect nodes (P95 of main thread blocks) |
101 ms |
107 ms |
-5.61% |
〰️ |
models tree 50k categories > validate initial visibility |
2041 ms |
1790 ms |
14.02% |
🚨 |
models tree 50k categories > validate initial visibility (P95 of main thread blocks) |
39 ms |
0 ms |
3900% |
〰️ |
models tree 50k categories > change visibility |
211 ms |
203 ms |
3.94% |
〰️ |
models tree 50k categories > change visibility (P95 of main thread blocks) |
57 ms |
57 ms |
0% |
🟰 |
models tree 50k categories > validate changed visibility |
2408 ms |
2280 ms |
5.61% |
〰️ |
models tree 50k categories > validate changed visibility (P95 of main thread blocks) |
24 ms |
25 ms |
-4% |
〰️ |
models tree 50k 3D elements > collect nodes |
51888 ms |
47201 ms |
9.93% |
〰️ |
models tree 50k 3D elements > collect nodes (P95 of main thread blocks) |
83 ms |
50 ms |
66% |
〰️ |
models tree 50k 3D elements > validate initial visibility |
1428 ms |
1384 ms |
3.18% |
〰️ |
models tree 50k 3D elements > validate initial visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
models tree 50k 3D elements > change model visibility |
116 ms |
110 ms |
5.45% |
〰️ |
models tree 50k 3D elements > change model visibility (P95 of main thread blocks) |
25 ms |
0 ms |
2500% |
〰️ |
models tree 50k 3D elements > validate changed model visibility |
2271 ms |
2163 ms |
4.99% |
〰️ |
models tree 50k 3D elements > validate changed model visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
models tree 50k 3D elements > change category node visibility |
484 ms |
472 ms |
2.54% |
〰️ |
models tree 50k 3D elements > change category node visibility (P95 of main thread blocks) |
68 ms |
43 ms |
58.14% |
〰️ |
models tree 50k 3D elements > validate changed category visibility |
1588 ms |
1476 ms |
7.59% |
〰️ |
models tree 50k 3D elements > validate changed category visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
models tree 50k 3D elements > validate per-model category override |
1636 ms |
1449 ms |
12.91% |
🚨 |
models tree 50k 3D elements > validate per-model category override (P95 of main thread blocks) |
112 ms |
0 ms |
11200% |
🚨 |
models tree 50k 3D elements > change element visibility |
46 ms |
39 ms |
17.95% |
〰️ |
models tree 50k 3D elements > change element visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
models tree 50k 3D elements > validate changed element visibility |
2321 ms |
2228 ms |
4.17% |
〰️ |
models tree 50k 3D elements > validate changed element visibility (P95 of main thread blocks) |
69 ms |
70 ms |
-1.43% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > collect nodes |
72097 ms |
65769 ms |
9.62% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > collect nodes (P95 of main thread blocks) |
58 ms |
55 ms |
5.45% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > validate initial visibility |
2029 ms |
2137 ms |
-5.05% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > validate initial visibility (P95 of main thread blocks) |
0 ms |
49 ms |
-100% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > change visibility |
52 ms |
53 ms |
-1.89% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > change visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
models tree 50k 3D child elements with different categories and excluded classes > validate changed visibility |
5793 ms |
5533 ms |
4.70% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > validate changed visibility (P95 of main thread blocks) |
107 ms |
88 ms |
21.59% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > collect nodes |
71092 ms |
65769 ms |
8.09% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > collect nodes (P95 of main thread blocks) |
79 ms |
55 ms |
43.64% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > validate initial visibility |
2186 ms |
2137 ms |
2.29% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > validate initial visibility (P95 of main thread blocks) |
0 ms |
49 ms |
-100% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > change visibility |
52 ms |
53 ms |
-1.89% |
〰️ |
models tree 50k 3D child elements with different categories and excluded classes > change visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
models tree 50k 3D child elements with different categories and excluded classes > validate changed visibility |
7667 ms |
5533 ms |
38.57% |
🚨 |
models tree 50k 3D child elements with different categories and excluded classes > validate changed visibility (P95 of main thread blocks) |
67 ms |
88 ms |
-23.86% |
〰️ |
categories tree 50k subCategories search > get search paths |
1787 ms |
1715 ms |
4.20% |
〰️ |
categories tree 50k subCategories search > get search paths (P95 of main thread blocks) |
116 ms |
110 ms |
5.45% |
〰️ |
categories tree 50k subCategories search > load hierarchy from search paths |
6177 ms |
5819 ms |
6.15% |
〰️ |
categories tree 50k subCategories search > load hierarchy from search paths (P95 of main thread blocks) |
65 ms |
58 ms |
12.07% |
〰️ |
categories tree 50k subCategories > collect nodes |
6679 ms |
6415 ms |
4.12% |
〰️ |
categories tree 50k subCategories > collect nodes (P95 of main thread blocks) |
43 ms |
43 ms |
0% |
🟰 |
categories tree 50k subCategories > validate initial visibility |
1022 ms |
986 ms |
3.65% |
〰️ |
categories tree 50k subCategories > validate initial visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
categories tree 50k subCategories > change visibility |
372 ms |
347 ms |
7.20% |
〰️ |
categories tree 50k subCategories > change visibility (P95 of main thread blocks) |
28 ms |
29 ms |
-3.45% |
〰️ |
categories tree 50k subCategories > validate changed visibility |
1091 ms |
1063 ms |
2.63% |
〰️ |
categories tree 50k subCategories > validate changed visibility (P95 of main thread blocks) |
32 ms |
28 ms |
14.29% |
〰️ |
categories tree 50k categories and excluded classes > collect nodes |
126828 ms |
114664 ms |
10.61% |
🚨 |
categories tree 50k categories and excluded classes > collect nodes (P95 of main thread blocks) |
113 ms |
110 ms |
2.73% |
〰️ |
categories tree 50k categories and excluded classes > validate initial visibility |
5507 ms |
5218 ms |
5.54% |
〰️ |
categories tree 50k categories and excluded classes > validate initial visibility (P95 of main thread blocks) |
65 ms |
37 ms |
75.68% |
〰️ |
categories tree 50k categories and excluded classes > change visibility |
899 ms |
788 ms |
14.09% |
🚨 |
categories tree 50k categories and excluded classes > change visibility (P95 of main thread blocks) |
84 ms |
52 ms |
61.54% |
〰️ |
categories tree 50k categories and excluded classes > validate changed visibility |
5982 ms |
5496 ms |
8.84% |
〰️ |
categories tree 50k categories and excluded classes > validate changed visibility (P95 of main thread blocks) |
50 ms |
38 ms |
31.58% |
〰️ |
categories tree 50k categories and excluded classes > collect nodes |
129130 ms |
114664 ms |
12.62% |
🚨 |
categories tree 50k categories and excluded classes > collect nodes (P95 of main thread blocks) |
206 ms |
110 ms |
87.27% |
🚨 |
categories tree 50k categories and excluded classes > validate initial visibility |
6184 ms |
5218 ms |
18.51% |
🚨 |
categories tree 50k categories and excluded classes > validate initial visibility (P95 of main thread blocks) |
53 ms |
37 ms |
43.24% |
〰️ |
categories tree 50k categories and excluded classes > change visibility |
856 ms |
788 ms |
8.63% |
〰️ |
categories tree 50k categories and excluded classes > change visibility (P95 of main thread blocks) |
64 ms |
52 ms |
23.08% |
〰️ |
categories tree 50k categories and excluded classes > validate changed visibility |
8849 ms |
5496 ms |
61.01% |
🚨 |
categories tree 50k categories and excluded classes > validate changed visibility (P95 of main thread blocks) |
53 ms |
38 ms |
39.47% |
〰️ |
classifications tree 50k classifications search > get search paths |
2744 ms |
2521 ms |
8.85% |
〰️ |
classifications tree 50k classifications search > get search paths (P95 of main thread blocks) |
226 ms |
190 ms |
18.95% |
〰️ |
classifications tree 50k classifications search > load hierarchy from search paths |
69114 ms |
64162 ms |
7.72% |
〰️ |
classifications tree 50k classifications search > load hierarchy from search paths (P95 of main thread blocks) |
27 ms |
27 ms |
0% |
🟰 |
classifications tree 50k classifications and excluded classes > collect nodes |
35573 ms |
33874 ms |
5.02% |
〰️ |
classifications tree 50k classifications and excluded classes > collect nodes (P95 of main thread blocks) |
66 ms |
99 ms |
-33.33% |
〰️ |
classifications tree 50k classifications and excluded classes > validate initial visibility |
3075 ms |
2846 ms |
8.05% |
〰️ |
classifications tree 50k classifications and excluded classes > validate initial visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
classifications tree 50k classifications and excluded classes > change visibility |
184 ms |
159 ms |
15.72% |
〰️ |
classifications tree 50k classifications and excluded classes > change visibility (P95 of main thread blocks) |
24 ms |
0 ms |
2400% |
〰️ |
classifications tree 50k classifications and excluded classes > validate changed visibility |
3756 ms |
3484 ms |
7.81% |
〰️ |
classifications tree 50k classifications and excluded classes > validate changed visibility (P95 of main thread blocks) |
80 ms |
98 ms |
-18.37% |
〰️ |
classifications tree 50k classifications and excluded classes > collect nodes |
36648 ms |
33874 ms |
8.19% |
〰️ |
classifications tree 50k classifications and excluded classes > collect nodes (P95 of main thread blocks) |
52 ms |
99 ms |
-47.47% |
〰️ |
classifications tree 50k classifications and excluded classes > validate initial visibility |
3073 ms |
2846 ms |
7.98% |
〰️ |
classifications tree 50k classifications and excluded classes > validate initial visibility (P95 of main thread blocks) |
0 ms |
0 ms |
0% |
🟰 |
classifications tree 50k classifications and excluded classes > change visibility |
177 ms |
159 ms |
11.32% |
〰️ |
classifications tree 50k classifications and excluded classes > change visibility (P95 of main thread blocks) |
24 ms |
0 ms |
2400% |
〰️ |
classifications tree 50k classifications and excluded classes > validate changed visibility |
3647 ms |
3484 ms |
4.68% |
〰️ |
classifications tree 50k classifications and excluded classes > validate changed visibility (P95 of main thread blocks) |
51 ms |
98 ms |
-47.96% |
〰️ |
This comment was automatically generated by workflow using github-action-benchmark.
|
@saskliutas I have made changes to when buttons are disabled and their tooltips. Previously we would allow clicking header buttons even when models/categories arrays were empty, now they are disabled. Tooltip of disabled buttons now shows |
I don't like disabled buttons with loading tooltip. Can we leave it as is? It will be noop until data is loaded? Ideally we would show skeleton buttons while loading but I think active noop button should be fine because if I understand correctly in that case where buttons are loading data tree will be loading too? |
Well, not exactly. Tree nodes can be loaded without loading that data in. Models/Categories trees don't use that data to load the root hierarchy level, they use it to validate visibility. So, there is a point (especially noticeable on larger imodels) where root nodes are loaded, but |

BufferingViewport.