Skip to content

Commit 260eb70

Browse files
authored
chore: Update TreeView API (#7613)
* chore: Update TreeView API * fix docs * fix dynamic example * actually save * fix docs * review comments * Revert change to not use hasChildItems * add prop table * fix docs example * remove extra border attributes in theme * fix snapshots * fix: S2 treeview haschildnodes (#7694) * fix logic to determine hasChildNodes * revert breaking changes but use prop override * match rac logic with hook * Fix spacing regression * fix chromatic merge * fix lint
1 parent 56da82e commit 260eb70

File tree

21 files changed

+1068
-843
lines changed

21 files changed

+1068
-843
lines changed

packages/@react-aria/gridlist/src/useGridListItem.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ export interface AriaGridListItemOptions {
2828
/** Whether the list row is contained in a virtual scroller. */
2929
isVirtualized?: boolean,
3030
/** Whether selection should occur on press up instead of press down. */
31-
shouldSelectOnPressUp?: boolean
31+
shouldSelectOnPressUp?: boolean,
32+
/** Whether this item has children, even if not loaded yet. */
33+
hasChildItems?: boolean
3234
}
3335

3436
export interface GridListItemAria extends SelectableItemStates {
@@ -86,13 +88,14 @@ export function useGridListItem<T>(props: AriaGridListItemOptions, state: ListSt
8688
};
8789

8890
let treeGridRowProps: HTMLAttributes<HTMLElement> = {};
89-
let hasChildRows;
91+
let hasChildRows = props.hasChildItems;
9092
let hasLink = state.selectionManager.isLink(node.key);
9193
if (node != null && 'expandedKeys' in state) {
9294
// TODO: ideally node.hasChildNodes would be a way to tell if a row has child nodes, but the row's contents make it so that value is always
9395
// true...
9496
let children = state.collection.getChildren?.(node.key);
95-
hasChildRows = [...(children ?? [])].length > 1;
97+
hasChildRows = hasChildRows || [...(children ?? [])].length > 1;
98+
9699
if (onAction == null && !hasLink && state.selectionManager.selectionMode === 'none' && hasChildRows) {
97100
onAction = () => state.toggleKey(node.key);
98101
}

packages/@react-spectrum/s2/chromatic/TreeView.stories.tsx

+110-58
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
import {ActionMenu, Content, Heading, IllustratedMessage, Link, MenuItem, Text, TreeView, TreeViewItem} from '../src';
13+
import {ActionMenu, Collection, Content, Heading, IllustratedMessage, Link, MenuItem, Text, TreeItemContent, TreeView, TreeViewItem} from '../src';
1414
import Delete from '../s2wf-icons/S2_Icon_Delete_20_N.svg';
1515
import Edit from '../s2wf-icons/S2_Icon_Edit_20_N.svg';
1616
import FileTxt from '../s2wf-icons/S2_Icon_FileText_20_N.svg';
@@ -36,35 +36,26 @@ function TreeExample(props) {
3636
disabledKeys={['projects-1']}
3737
aria-label="test static tree"
3838
expandedKeys={['projects']}>
39+
3940
<TreeViewItem id="Photos" textValue="Photos">
40-
<Text>Photos</Text>
41-
<Folder />
42-
<ActionMenu>
43-
<MenuItem id="edit">
44-
<Edit />
45-
<Text>Edit</Text>
46-
</MenuItem>
47-
<MenuItem id="delete">
48-
<Delete />
49-
<Text>Delete</Text>
50-
</MenuItem>
51-
</ActionMenu>
41+
<TreeItemContent>
42+
<Text>Photos</Text>
43+
<Folder />
44+
<ActionMenu>
45+
<MenuItem id="edit">
46+
<Edit />
47+
<Text>Edit</Text>
48+
</MenuItem>
49+
<MenuItem id="delete">
50+
<Delete />
51+
<Text>Delete</Text>
52+
</MenuItem>
53+
</ActionMenu>
54+
</TreeItemContent>
5255
</TreeViewItem>
5356
<TreeViewItem id="projects" textValue="Projects">
54-
<Text>Projects</Text>
55-
<Folder />
56-
<ActionMenu>
57-
<MenuItem id="edit">
58-
<Edit />
59-
<Text>Edit</Text>
60-
</MenuItem>
61-
<MenuItem id="delete">
62-
<Delete />
63-
<Text>Delete</Text>
64-
</MenuItem>
65-
</ActionMenu>
66-
<TreeViewItem id="projects-1" textValue="Projects-1">
67-
<Text>Projects-1</Text>
57+
<TreeItemContent>
58+
<Text>Projects</Text>
6859
<Folder />
6960
<ActionMenu>
7061
<MenuItem id="edit">
@@ -76,9 +67,11 @@ function TreeExample(props) {
7667
<Text>Delete</Text>
7768
</MenuItem>
7869
</ActionMenu>
79-
<TreeViewItem id="projects-1A" textValue="Projects-1A">
80-
<Text>Projects-1A</Text>
81-
<FileTxt />
70+
</TreeItemContent>
71+
<TreeViewItem id="projects-1" textValue="Projects-1">
72+
<TreeItemContent>
73+
<Text>Projects-1</Text>
74+
<Folder />
8275
<ActionMenu>
8376
<MenuItem id="edit">
8477
<Edit />
@@ -89,35 +82,55 @@ function TreeExample(props) {
8982
<Text>Delete</Text>
9083
</MenuItem>
9184
</ActionMenu>
85+
</TreeItemContent>
86+
<TreeViewItem id="projects-1A" textValue="Projects-1A">
87+
<TreeItemContent>
88+
<Text>Projects-1A</Text>
89+
<FileTxt />
90+
<ActionMenu>
91+
<MenuItem id="edit">
92+
<Edit />
93+
<Text>Edit</Text>
94+
</MenuItem>
95+
<MenuItem id="delete">
96+
<Delete />
97+
<Text>Delete</Text>
98+
</MenuItem>
99+
</ActionMenu>
100+
</TreeItemContent>
92101
</TreeViewItem>
93102
</TreeViewItem>
94103
<TreeViewItem id="projects-2" textValue="Projects-2">
95-
<Text>Projects-2</Text>
96-
<FileTxt />
97-
<ActionMenu>
98-
<MenuItem id="edit">
99-
<Edit />
100-
<Text>Edit</Text>
101-
</MenuItem>
102-
<MenuItem id="delete">
103-
<Delete />
104-
<Text>Delete</Text>
105-
</MenuItem>
106-
</ActionMenu>
104+
<TreeItemContent>
105+
<Text>Projects-2</Text>
106+
<FileTxt />
107+
<ActionMenu>
108+
<MenuItem id="edit">
109+
<Edit />
110+
<Text>Edit</Text>
111+
</MenuItem>
112+
<MenuItem id="delete">
113+
<Delete />
114+
<Text>Delete</Text>
115+
</MenuItem>
116+
</ActionMenu>
117+
</TreeItemContent>
107118
</TreeViewItem>
108119
<TreeViewItem id="projects-3" textValue="Projects-3">
109-
<Text>Projects-3</Text>
110-
<FileTxt />
111-
<ActionMenu>
112-
<MenuItem id="edit">
113-
<Edit />
114-
<Text>Edit</Text>
115-
</MenuItem>
116-
<MenuItem id="delete">
117-
<Delete />
118-
<Text>Delete</Text>
119-
</MenuItem>
120-
</ActionMenu>
120+
<TreeItemContent>
121+
<Text>Projects-3</Text>
122+
<FileTxt />
123+
<ActionMenu>
124+
<MenuItem id="edit">
125+
<Edit />
126+
<Text>Edit</Text>
127+
</MenuItem>
128+
<MenuItem id="delete">
129+
<Delete />
130+
<Text>Delete</Text>
131+
</MenuItem>
132+
</ActionMenu>
133+
</TreeItemContent>
121134
</TreeViewItem>
122135
</TreeViewItem>
123136
</TreeView>
@@ -207,14 +220,53 @@ let rows = [
207220
]}
208221
];
209222

223+
const DynamicTreeItem = (props) => {
224+
let {childItems, name, icon} = props;
225+
return (
226+
<>
227+
<TreeViewItem id={props.id} childItems={childItems} textValue={name} href={props.href}>
228+
<TreeItemContent>
229+
<Text>{name}</Text>
230+
{icon}
231+
<ActionMenu>
232+
<MenuItem id="edit">
233+
<Edit />
234+
<Text>Edit</Text>
235+
</MenuItem>
236+
<MenuItem id="delete">
237+
<Delete />
238+
<Text>Delete</Text>
239+
</MenuItem>
240+
</ActionMenu>
241+
</TreeItemContent>
242+
<Collection items={childItems}>
243+
{(item: any) => (
244+
<DynamicTreeItem
245+
id={item.id}
246+
icon={item.icon}
247+
childItems={item.childItems}
248+
textValue={item.name}
249+
name={item.name}
250+
href={props.href}>
251+
{item.name}
252+
</DynamicTreeItem>
253+
)}
254+
</Collection>
255+
</TreeViewItem>
256+
</>
257+
);
258+
};
259+
210260
const TreeExampleDynamic = (args) => (
211261
<div style={{width: '300px', height: '320px', display: 'flex', flexDirection: 'column'}}>
212262
<TreeView aria-label="test dynamic tree" items={rows} {...args}>
213263
{(item: any) => (
214-
<TreeViewItem childItems={item.childItems} textValue={item.name}>
215-
<Text>{item.name}</Text>
216-
{item.icon}
217-
</TreeViewItem>
264+
<DynamicTreeItem
265+
id={item.id}
266+
icon={item.icon}
267+
childItems={item.childItems}
268+
textValue={item.name}
269+
name={item.name} />
218270
)}
219271
</TreeView>
220272
</div>

0 commit comments

Comments
 (0)