-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement TreeView component #2396
Comments
I'm not totally familiar with the proposed aria-pattern above, but a nice-to-have feature would be to rescue focus from a tree node that has document focus but is then removed from the DOM. Currently in React Spectrum v2 TreeView, the focus is lost when the focused element is removed. |
I'm interested in potentially working on this. Here is the Spectrum design doc for tree view https://spectrum.adobe.com/page/tree-view/ Where is the "React Spectrum v2 TreeView" defined? |
@curran Thank you for your interest! The team is currently revisiting this to make sure all the information is still pertinent and up to date, we hope to get back to you in a week or so. If you'd like, you could explore implementing Tree using React Aria Components (RAC) and its collections pattern in the meantime. We plan on converting our React Spectrum components to use this new collection pattern so we figure it would be easier to create TreeView for RAC rather than implementing it in React Spectrum first and converting it later. Since it is a RAC implementation, you don't need to match the visuals of the Spectrum Design doc. Instead, the Keep in mind that due to ongoing team priorities we won't have much time to actively support a contribution of this scale, but we'd appreciate any findings and progress you make here! |
Awesome, thanks for the note! Indeed, an implementation in I'm was considering attempting a recursive form of the existing useListBox pattern. I see there are some 2-level examples with a |
Was looking for a react-aria based treeview solution as well. Found this great very recent tutorial (not related to react-aria) in case someone needs a custom solution in the meantime. |
I assume this ticket applies to RAC as well, right? |
I've been working on a tree component for navigating files. One thing I would like to do is make it more accessible using |
Is there any reason for not to use React Stately? |
For what in particular? What would that look like? It may be a good fit, but I'm not very familiar with it. I'm open to using React Stately if the benefits are clear. What would be the benefits of using it? |
I discovered the react spectrum project a week ago, so I am not sure which is the best way to develop new components. Take what I say with a grain of salt. EDIT: |
@edoelas This page may be helpful: https://react-spectrum.adobe.com/architecture.html |
In case some research on treeView components helps, here's what I found: The best options I found are react-arborist and react-complex-tree. As a third honorable mention, the latter's creator is working on his "spiritual successor", headless-tree (still in alpha, and the author doesn't seem to be able to spend much time on it). The website is not mentioned in the GitHub repository, so here it is. The arborist API seems better to me at first glance, although The following libraries have open issues regarding the implementation of a TreeView component: |
To discuss / receive feedback 1. Nested or flat DOM?
I have read Aria's documentation on the treegrid pattern, and I understand that it is possible to implement with a nested or flat DOM (they mention aria-owns), am I understanding correctly? If so, I would like to receive feedback on some observations: 1.1 Drop-target.While a This is possible to do with both a flat and a nested DOM. However, nesting may require accessing all descendants and adding some indicator to them in the markup. Another related thing to keep in mind is that it should not be possible to drag and drop an item on a descendant item to the one being dragged (for example in the gif above you should not be able to DnD 1 inside 1.1. 1.2 VirtualizationIf I'm not mistaken, it should be possible to virtualize both models, although it would surely be much easier with a flat model. The creator of react-complex-tree is making the new headless-tree library as I mentioned in my comment above, precisely because he found complications virtualizing a nested DOM. Some virtualization libraries have not been built with a nested DOM in mind, although in others it appears to be doable. 2. Drop "inside"The useDragAndDrop event exposes
const [dropPosition, setDropPosition] = useState<
"before" | "after" | "inside" | null
>(null);
const { dropProps, isDropTarget } = useDrop({
ref: dropRef,
onDropMove(ev) {
if (!dropRef.current) return;
const itemHeight = dropRef.current.offsetHeight;
if (ev.y < 7) setDropPosition("before");
else if (ev.y > itemHeight - 7) setDropPosition("after");
else setDropPosition("inside");
},
});
Edit: I have now discovered that the dragAndDrop hook used in gridlist has support for dropping inside the item as well as before and after. There is no option to set the distance in pixels, but it has been working well for me in my opinion. 3. Expanding and collapsing APIUsing item selection as a reference, an analogous API could be: type CollectionProps = {
defaultCollapsedKeys: 'all' | Iterable<Key>, // initial state
collapsedKeys: 'all' | Iterable<Key>, // current state
onCollapsedChange: (keys: Collapsed) => any, // setter
} However, for the same reasons I explained here I strongly suggest that the API be determined solely by a setter and a getter: type CollectionProps = {
getCollapsed: (item: object) => boolean, // getter
setCollapsed: (item: object) => void, // setter
} 4. Name of the component
According to the Aria spec the patterns are called "Tree View" and "Treegrid". So wouldn't it be better to call the component |
Hi, I have a question on node selection for this component, as |
@6thpath At the moment that is intended behavior, similar to how macOS's file system allows you to select a parent folder individually from its children. I imagine we could consider adding support for customizing this behavior though. |
Initial component is done We'll track other work in other issues such as #6589 |
That's great @snowystinger! I was going to open 4 threads with the observations or questions from my previous comment and gave up after making the first one. I just hope you take them into account. Thanks for the amazing work you do! |
🙋 Feature Request
A
TreeView
allows users to navigate a hierarchical tree data structure, with expanding and collapsing items. It also allows multiple or single selection of items, focusable elements inside items, and other interactions.ARIA pattern
Since
TreeView
allows focusable elements inside items, it will implement thetreegrid
ARIA pattern rather than thetree
pattern. TheTreeView
Spectrum component supports only a single column, however, the React Aria hooks will not have this limitation.Since
grid
andtreegrid
are so similar, the existing React Aria grid hooks should be extended with treegrid support. See the above pattern and this example for details.useGridState
to handle expanding and collapsinguseGrid
that controls whether it is a treegrid. Basically changes the role. Cannot be changed after initial render (we should throw).useGridRow
, we need to addaria-expanded
for parent rows,aria-level
,aria-setsize
, andaria-posinset
.Spectrum
React Spectrum’s
TreeView
component should follow the existing collections API, which allows nested items in the dynamic case. Static collections with nested children will not be supported for the initial version.The
Virtualizer
should be used to implementTreeView
as with other collection components, and a newTreeLayout
will be needed to handle the layout. It should produce a flattened list of items with indentation since thetreegrid
pattern does not use DOM hierarchy.TreeView
should use theuseGrid
and associated hooks, and use the option that specifies that it is a treegrid. It should useuseTreeState
andTreeCollection
to store the state, which should be converted within the component to useuseGridState
similar toListView
andCardView
.Example
API
Not for initial implementation
The text was updated successfully, but these errors were encountered: