feat(ui): add accessible tree suite - #1065
Draft
EhabY wants to merge 5 commits into
Draft
Conversation
EhabY
force-pushed
the
feat/ui-tree-suite
branch
from
August 5, 2026 14:11
510e466 to
309f05d
Compare
EhabY
force-pushed
the
feat/ui-tree-suite
branch
6 times, most recently
from
August 11, 2026 15:59
ddeb99e to
3117b68
Compare
Add the Tree, TreeItem, and TreeGroup compound components: ARIA tree semantics with roving tabindex, hierarchy navigation, buffered type-ahead, and controlled selection and expansion. Styling matches VS Code tree geometry and states across the shared, Modern, and stable styles, with an explorer variant for icon-less branch rows. Cover the suite with unit tests and pixel stories across all four themes; the nested story forces real :hover via storybook-addon-pseudo-states so screenshots capture hover and selection together.
Pin the ancestors of the topmost visible row like VS Code's tree sticky scroll, opt in with `stickyScroll` and cap the pinned levels with a number. Branch rows pin themselves with `position: sticky` at an offset derived from their level, so the browser produces the push-out as a subtree scrolls past and no scroll listener or duplicate row widget is needed. Rows past the cap and leaves never pin. Pinned rows paint over scrolled content with sideBarStickyScroll's background. Webviews receive no workbench.tree.* settings, so the README shows the host how to read them and pass them in.
Opt in with `multiSelect`, which swaps the singular selection props for `selectedItemIds` and `onSelectedItemsChange` and marks the tree aria-multiselectable, matching VS Code's per-tree multipleSelectionSupport. Ctrl/Cmd click toggles a row, Shift click and Shift arrows extend from the anchor, and Ctrl/Cmd+A takes every visible enabled row. Ranges walk tree order, so disabled and collapsed rows stay out of them. Indent guide owners collapse into a set: siblings selected together share one owner, which a list would have counted twice and republished on every commit.
Render a branch's group only while it is expanded, so cost tracks what is open rather than the size of the tree. A 100k-node tree browsed a folder at a time goes from 4.4s to 357ms to mount, 746MB to 110MB of heap, and 9.7ms to 0.3ms per keystroke, with scrolling back at 60fps. Fully expanded trees are unchanged, so the remaining limit is rows open at once: ~10k is comfortable, 50k degrades, and 100k needs a virtualized tree instead. A group that only exists while open needs neither the hidden attribute nor the rule that forced it to win.
EhabY
force-pushed
the
feat/ui-tree-suite
branch
from
August 11, 2026 21:28
3117b68 to
814fbbf
Compare
Add a Focused story: focus is its own state, so a row can carry the blue outline without being selected while the selected row keeps its background. Give the multi-select story the same active row VS Code draws inside a multi-selection. Both force the pseudo state through the addon and take real DOM focus for the tree's focused class, since React listens for focusin and the synthetic focus event does not bubble to it in a browser. Sticky scroll scrolls on mount rather than from its play function, and into a shorter viewport, so the snapshot actually shows pinned ancestors with a row clipped beneath them.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Tree,TreeItem, andTreeGroupcomponent suite: ARIA tree semantics, roving tabindex, hierarchy navigation, and buffered type-aheadTree.selectedItemId) and branch expansion (TreeItem.expanded)explorervariant for icon-less branch rows:hoverviastorybook-addon-pseudo-statesso screenshots capture hover and selection togetherCloses #1037
Validation
pnpm test:webview- 353 tests passedpnpm typecheckpnpm exec eslinton the changed files