Skip to content

Commit

Permalink
Replaces the width on Tree virtual items with --_iui-width (#2170)
Browse files Browse the repository at this point in the history
Also fixes an issue where `style` passed into `TreeNode` for virtualized `Tree` components would not be respected.
  • Loading branch information
Ben-Pusey-Bentley authored Jul 29, 2024
1 parent c83a2c8 commit d122861
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/light-chefs-confess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@itwin/itwinui-react': patch
---

Fixed an issue in virtualized `Tree` where the style prop passed to `TreeNode` was not respected.
5 changes: 5 additions & 0 deletions .changeset/perfect-parents-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@itwin/itwinui-react': patch
---

Fixed an issue in virtualized `Tree` where horizontal scroll was impossible to achieve.
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.
112 changes: 112 additions & 0 deletions apps/react-workshop/src/Tree.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -682,3 +682,115 @@ export const Small = () => {
/>
);
};

export const VirtualizedWithHorizontalScroll = () => {
type StoryData = {
id: string;
label: string;
subItems: StoryData[];
};

const [selectedNodes, setSelectedNodes] = useState<Record<string, boolean>>({
'Node-0': true,
'Node-3-2': true,
'Node-22': true,
});
const onSelectedNodeChange = useCallback(
(nodeId: string, isSelected: boolean) => {
if (isSelected) {
setSelectedNodes((oldSelected) => ({ ...oldSelected, [nodeId]: true }));
console.log(`Selected node ${nodeId}`);
} else {
setSelectedNodes((oldSelected) => ({
...oldSelected,
[nodeId]: false,
}));
console.log(`Unselected node ${nodeId}`);
}
},
[],
);

const [expandedNodes, setExpandedNodes] = useState<Record<string, boolean>>({
'Node-0': true,
'Node-0-0': true,
'Node-0-0-0': true,
'Node-0-0-0-0': true,
'Node-2': true,
'Node-2-1': true,
'Node-3': true,
});
const onNodeExpanded = useCallback((nodeId: string, isExpanded: boolean) => {
if (isExpanded) {
setExpandedNodes((oldExpanded) => ({ ...oldExpanded, [nodeId]: true }));
console.log(`Expanded node ${nodeId}`);
} else {
setExpandedNodes((oldExpanded) => ({
...oldExpanded,
[nodeId]: false,
}));
console.log(`Closed node ${nodeId}`);
}
}, []);
const generateItem = useCallback(
(index: number, parentNode = '', depth = 0): StoryData => {
const keyValue = parentNode ? `${parentNode}-${index}` : `${index}`;
return {
id: `Node-${keyValue}`,
label: `Node ${keyValue}`,
subItems:
depth < 10
? Array(1)
.fill(null)
.map((_, index) => generateItem(index, keyValue, depth + 1))
: [],
};
},
[],
);

const data = useMemo(
() =>
Array(100000)
.fill(null)
.map((_, index) => generateItem(index)),
[generateItem],
);

const getNode = useCallback(
(node: StoryData): NodeData<StoryData> => {
return {
subNodes: node.subItems,
nodeId: node.id,
node: node,
isExpanded: expandedNodes[node.id],
isSelected: selectedNodes[node.id],
hasSubNodes: node.subItems.length > 0,
};
},
[expandedNodes, selectedNodes],
);

return (
<Tree<StoryData>
data={data}
getNode={getNode}
enableVirtualization
nodeRenderer={useCallback(
({ node, ...rest }) => (
<TreeNode
label={node.label}
onExpanded={onNodeExpanded}
onSelected={onSelectedNodeChange}
checkbox={<Checkbox variant='eyeball' disabled={rest.isDisabled} />}
icon={<SvgPlaceholder />}
style={{ width: 'fit-content', minWidth: '100%' }}
{...rest}
/>
),
[onNodeExpanded, onSelectedNodeChange],
)}
style={{ height: 'min(400px, 90vh)', width: '250px' }}
/>
);
};
2 changes: 2 additions & 0 deletions apps/react-workshop/src/Tree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ describe('Tree', () => {
'Customized Expander',
'Async Loading',
'Small',
'Virtualized',
'Virtualized With Horizontal Scroll',
];

tests.forEach((testName) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/itwinui-react/src/core/Tree/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ export const Tree = <T,>(props: TreeProps<T>) => {
'data-iui-virtualizer': 'item',
ref: virtualizer.measureElement,
style: {
width: '100%',
...children.props.style,
'--_iui-width': '100%',
transform: `translateY(${virtualItem.start}px)`,
},
}))
Expand Down

0 comments on commit d122861

Please sign in to comment.