Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
Fix focus management issue when updating folder tree children (#2119)
Browse files Browse the repository at this point in the history
  • Loading branch information
cm9361 authored Apr 4, 2024
1 parent 8ebcd02 commit 4ae47a2
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 33 deletions.
64 changes: 32 additions & 32 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/terra-folder-tree/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Fixed
* Fixed an issue where folder tree items could not receive focus after data was updated.

## 1.0.0 - (March 29, 2024)

* Fixed
Expand Down
2 changes: 1 addition & 1 deletion packages/terra-folder-tree/src/FolderTree.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ const FolderTree = ({
useEffect(() => {
const listItems = listNode.current.querySelectorAll('[data-item-show-focus=true]');
listItems[0].tabIndex = 0;
}, []);
}, [children]);

useEffect(() => {
const listItems = listNode.current.querySelectorAll('[data-item-show-focus=true]');
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions packages/terra-folder-tree/tests/wdio/folder-tree-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,16 @@ Terra.describeViewports('FolderTree', ['medium'], () => {

Terra.validates.screenshot('wrapped label folder tree', { selector: '#wrapped-label-folder-tree' });
});

it('gains focus after updating the children', () => {
browser.url('/raw/tests/cerner-terra-framework-docs/folder-tree/folder-tree-reload');

$('#reload-data-button').click();
browser.keys('Tab');
browser.keys('Tab');
browser.keys('Tab');

Terra.validates.screenshot('reload-focus', { selector: '#folder-tree-reload' });
});
});
});
1 change: 1 addition & 0 deletions packages/terra-framework-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

* Added
* Added examples and tests for `terra-table` to demonstrate auto layout.
* Added test for `terra-folder-tree` to cover focus management after updating its children.

## 1.78.0 - (March 29, 2024)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import React, { useState } from 'react';

import { IconDocuments } from 'terra-icon';
import FolderTree from 'terra-folder-tree';

const data = {
title: 'Documents',
items: [
{ id: 'item-1-level-1', label: 'Information', icon: <IconDocuments /> },
{
id: 'item-2-level-1', label: 'Projects - 2023', icon: <IconDocuments />, isSelectable: false,
},
{
id: 'item-3-level-1',
label: 'Projects - 2023',
isSelectable: false,
items: [
{ id: 'item-1-level-2-1', label: 'Project Data - October', icon: <IconDocuments /> },
{ id: 'item-2-level-2-1', label: 'Project Data - November', icon: <IconDocuments /> },
{ id: 'item-3-level-2-1', label: 'Project Data - December', icon: <IconDocuments /> },
{
id: 'item-4-level-2-1',
label: 'Tests',
isSelectable: false,
items: [
{ id: 'item-1-level-3-1', label: 'Very Very Very Very Very Very Very Long Name Test', icon: <IconDocuments /> },
{ id: 'item-2-level-3-1', label: 'Even Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonger Name Test', icon: <IconDocuments /> },
],
},
],
},
{ id: 'item-4-level-1', label: 'Projects - 2024', icon: <IconDocuments /> },
{
id: 'item-5-level-1',
label: 'Projects - 2024',
isSelectable: false,
items: [
{ id: 'item-1-level-2-2', label: 'Project Data - January', icon: <IconDocuments /> },
],
},
],
reloadItems: [
{ id: 'reload-item-1-level-1', label: 'Information', icon: <IconDocuments /> },
{
id: 'reload-item-2-level-1', label: 'Projects - 2024', icon: <IconDocuments />, isSelectable: false,
},
{
id: 'reload-item-3-level-1',
label: 'Projects - 2024',
isSelectable: false,
items: [
{ id: 'reload-item-1-level-2-1', label: 'Project Data - January', icon: <IconDocuments /> },
{ id: 'reload-item-2-level-2-1', label: 'Project Data - February', icon: <IconDocuments /> },
{ id: 'reload-item-3-level-2-1', label: 'Project Data - March', icon: <IconDocuments /> },
{
id: 'reload-item-4-level-2-1',
label: 'Tests',
isSelectable: false,
items: [
{ id: 'reload-item-1-level-3-1', label: 'Very Very Very Very Very Very Very Long Name Test', icon: <IconDocuments /> },
{ id: 'reload-item-2-level-3-1', label: 'Even Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonger Name Test', icon: <IconDocuments /> },
],
},
],
},
{ id: 'reload-item-4-level-1', label: 'Projects - 2025', icon: <IconDocuments /> },
{
id: 'reload-item-5-level-1',
label: 'Projects - 2025',
isSelectable: false,
items: [
{ id: 'reload-item-1-level-2-2', label: 'Project Data - January', icon: <IconDocuments /> },
],
},
],
};

const folderExpandedState = {
'item-3-level-1': false,
'item-4-level-2-1': false,
'item-5-level-1': false,
};

const FolderTreeReload = () => {
const [selectedKey, setSelectedKey] = useState('');
const [expandedItems, setExpandedItems] = useState(folderExpandedState);
const [isReloaded, setReloaded] = useState(false);

const handleExpandCollapseKeys = (key) => {
const newExpandedItems = {
...expandedItems,
[key]: !expandedItems[key],
};
setExpandedItems(newExpandedItems);
};

const handleExpandAll = () => {
const newExpandedItems = {
...expandedItems,
};
Object.keys(newExpandedItems).forEach(v => { newExpandedItems[v] = true; });

setExpandedItems(newExpandedItems);
};

const handleCollapseAll = () => {
const newExpandedItems = {
...expandedItems,
};
Object.keys(newExpandedItems).forEach(v => { newExpandedItems[v] = false; });

setExpandedItems(newExpandedItems);
};

const buildFolderTreeItems = (items) => {
if (items) {
const elements = [];
items.forEach(item => {
elements.push(
<FolderTree.Item
key={item.id}
label={item.label}
icon={item.icon}
subfolderItems={buildFolderTreeItems(item.items)}
isExpanded={expandedItems[item.id]}
isSelectable={item.isSelectable}
isSelected={selectedKey === item.id}
onSelect={() => { setSelectedKey(item.id); }}
onToggle={() => { handleExpandCollapseKeys(item.id); }}
/>,
);
});
return elements;
}

return null;
};

const reloadItems = () => {
setReloaded(true);

setExpandedItems({
'reload-item-3-level-1': false,
'reload-item-4-level-2-1': false,
'reload-item-5-level-1': false,
});
};

return (
<>
<button id="reload-data-button" type="button" onClick={reloadItems}> Reload Data</button>
<br />
<div id="folder-tree-reload">
<FolderTree
title={data.title}
onExpandAll={handleExpandAll}
onCollapseAll={handleCollapseAll}
>
{buildFolderTreeItems(isReloaded ? data.reloadItems : data.items)}
</FolderTree>
</div>
</>
);
};

export default FolderTreeReload;

0 comments on commit 4ae47a2

Please sign in to comment.