Skip to content
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

[TreeView] Add focusedNode prop #11343

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/data/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ const pages: MuiPage[] = [
{ pathname: '/x/react-tree-view/simple-tree-view/items' },
{ pathname: '/x/react-tree-view/simple-tree-view/selection' },
{ pathname: '/x/react-tree-view/simple-tree-view/expansion' },
{ pathname: '/x/react-tree-view/simple-tree-view/focus' },
{ pathname: '/x/react-tree-view/simple-tree-view/customization' },
],
},
Expand All @@ -494,6 +495,7 @@ const pages: MuiPage[] = [
{ pathname: '/x/react-tree-view/rich-tree-view/items' },
{ pathname: '/x/react-tree-view/rich-tree-view/selection' },
{ pathname: '/x/react-tree-view/rich-tree-view/expansion' },
{ pathname: '/x/react-tree-view/rich-tree-view/focus' },
],
},
{
Expand Down
69 changes: 69 additions & 0 deletions docs/data/tree-view/rich-tree-view/focus/FocusedRichTreeView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';

const MUI_X_PRODUCTS = [
{
id: 'grid',
label: 'Data Grid',
children: [
{ id: 'grid-community', label: '@mui/x-data-grid' },
{ id: 'grid-pro', label: '@mui/x-data-grid-pro' },
{ id: 'grid-premium', label: '@mui/x-data-grid-premium' },
],
},
{
id: 'pickers',
label: 'Date and Time Pickers',
children: [
{ id: 'pickers-community', label: '@mui/x-date-pickers' },
{ id: 'pickers-pro', label: '@mui/x-date-pickers-pro' },
],
},
{
id: 'charts',
label: 'Charts',
children: [{ id: 'charts-community', label: '@mui/x-charts' }],
},
{
id: 'tree-view',
label: 'Tree View',
children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }],
},
];

export default function FocusedRichTreeView() {
const [focusedNode, setFocusedNode] = React.useState('charts');

const handleExpandedNodesChange = (event, nodeId) => {
setFocusedNode(nodeId);
};

const handleButtonClick = () => {
setFocusedNode(() => {
if (focusedNode === 'charts') {
return 'grid-pro';
}
return 'charts';
});
};

return (
<Box sx={{ flexGrow: 1, maxWidth: 400 }}>
<Box sx={{ mb: 1 }}>
<Button onClick={handleButtonClick}>
{focusedNode === 'charts' ? 'Focus grid pro' : 'Focus charts'}
</Button>
</Box>
<Box sx={{ height: 264, flexGrow: 1 }}>
<RichTreeView
items={MUI_X_PRODUCTS}
focusedNode={focusedNode}
onFocusedNodeChange={handleExpandedNodesChange}
defaultExpandedNodes={['grid', 'charts']}
/>
</Box>
</Box>
);
}
73 changes: 73 additions & 0 deletions docs/data/tree-view/rich-tree-view/focus/FocusedRichTreeView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';

const MUI_X_PRODUCTS: TreeViewBaseItem[] = [
{
id: 'grid',
label: 'Data Grid',
children: [
{ id: 'grid-community', label: '@mui/x-data-grid' },
{ id: 'grid-pro', label: '@mui/x-data-grid-pro' },
{ id: 'grid-premium', label: '@mui/x-data-grid-premium' },
],
},
{
id: 'pickers',
label: 'Date and Time Pickers',
children: [
{ id: 'pickers-community', label: '@mui/x-date-pickers' },
{ id: 'pickers-pro', label: '@mui/x-date-pickers-pro' },
],
},
{
id: 'charts',
label: 'Charts',
children: [{ id: 'charts-community', label: '@mui/x-charts' }],
},
{
id: 'tree-view',
label: 'Tree View',
children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }],
},
];

export default function FocusedRichTreeView() {
const [focusedNode, setFocusedNode] = React.useState<string | null>('charts');

const handleExpandedNodesChange = (
event: React.SyntheticEvent,
nodeId: string | null,
) => {
setFocusedNode(nodeId);
};

const handleButtonClick = () => {
setFocusedNode(() => {
if (focusedNode === 'charts') {
return 'grid-pro';
}
return 'charts';
});
};

return (
<Box sx={{ flexGrow: 1, maxWidth: 400 }}>
<Box sx={{ mb: 1 }}>
<Button onClick={handleButtonClick}>
{focusedNode === 'charts' ? 'Focus grid pro' : 'Focus charts'}
</Button>
</Box>
<Box sx={{ height: 264, flexGrow: 1 }}>
<RichTreeView
items={MUI_X_PRODUCTS}
focusedNode={focusedNode}
onFocusedNodeChange={handleExpandedNodesChange}
defaultExpandedNodes={['grid', 'charts']}
/>
</Box>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Box sx={{ mb: 1 }}>
<Button onClick={handleButtonClick}>
{focusedNode === 'charts' ? 'Focus grid pro' : 'Focus charts'}
</Button>
</Box>
<Box sx={{ height: 264, flexGrow: 1 }}>
<RichTreeView
items={MUI_X_PRODUCTS}
focusedNode={focusedNode}
onFocusedNodeChange={handleExpandedNodesChange}
defaultExpandedNodes={['grid', 'charts']}
/>
</Box>
28 changes: 28 additions & 0 deletions docs/data/tree-view/rich-tree-view/focus/focus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
productId: x-tree-view
title: Rich Tree View - Focus
components: RichTreeView, TreeItem
packageName: '@mui/x-tree-view'
githubLabel: 'component: tree view'
waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
---

# Rich Tree View - Focus

<p class="description">Handle how users can focus items.</p>

## Controlled focus

Use the `focusedNode` prop to control the focused item.

You can use the `onFocusedNodeChange` prop to listen to changes in the focused item and update the prop accordingly.

{{"demo": "FocusedRichTreeView.js"}}

:::info

- The focus is **controlled** when its parent manages it by providing a `focusedNode` prop.
- The focus is **uncontrolled** when it is managed by the component's own internal state. This state can be initialized using the `defaultFocusedNode` prop.

Learn more about the _Controlled and uncontrolled_ pattern in the [React documentation](https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components).
:::
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
import { TreeItem } from '@mui/x-tree-view/TreeItem';

export default function FocusedSimpleTreeView() {
const [focusedNode, setFocusedNode] = React.useState('charts');

const handleExpandedNodesChange = (event, nodeId) => {
setFocusedNode(nodeId);
};

const handleButtonClick = () => {
setFocusedNode(() => {
if (focusedNode === 'charts') {
return 'grid-pro';
}
return 'charts';
});
};

return (
<Box sx={{ flexGrow: 1, maxWidth: 400 }}>
<Box sx={{ mb: 1 }}>
<Button onClick={handleButtonClick}>
{focusedNode === 'charts' ? 'Focus grid pro' : 'Focus charts'}
</Button>
</Box>
<Box sx={{ height: 264, flexGrow: 1 }}>
<SimpleTreeView
focusedNode={focusedNode}
onFocusedNodeChange={handleExpandedNodesChange}
defaultExpandedNodes={['grid', 'charts']}
>
<TreeItem nodeId="grid" label="Data Grid">
<TreeItem nodeId="grid-community" label="@mui/x-data-grid" />
<TreeItem nodeId="grid-pro" label="@mui/x-data-grid-pro" />
<TreeItem nodeId="grid-premium" label="@mui/x-data-grid-premium" />
</TreeItem>
<TreeItem nodeId="pickers" label="Date and Time Pickers">
<TreeItem nodeId="pickers-community" label="@mui/x-date-pickers" />
<TreeItem nodeId="pickers-pro" label="@mui/x-date-pickers-pro" />
</TreeItem>
<TreeItem nodeId="charts" label="Charts">
<TreeItem nodeId="charts-community" label="@mui/x-charts" />
</TreeItem>
<TreeItem nodeId="tree-view" label="Tree View">
<TreeItem nodeId="tree-view-community" label="@mui/x-tree-view" />
</TreeItem>
</SimpleTreeView>
</Box>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
import { TreeItem } from '@mui/x-tree-view/TreeItem';

export default function FocusedSimpleTreeView() {
const [focusedNode, setFocusedNode] = React.useState<string | null>('charts');

const handleExpandedNodesChange = (
event: React.SyntheticEvent,
nodeId: string | null,
) => {
setFocusedNode(nodeId);
};

const handleButtonClick = () => {
setFocusedNode(() => {
if (focusedNode === 'charts') {
return 'grid-pro';
}
return 'charts';
});
};

return (
<Box sx={{ flexGrow: 1, maxWidth: 400 }}>
<Box sx={{ mb: 1 }}>
<Button onClick={handleButtonClick}>
{focusedNode === 'charts' ? 'Focus grid pro' : 'Focus charts'}
</Button>
</Box>
<Box sx={{ height: 264, flexGrow: 1 }}>
<SimpleTreeView
focusedNode={focusedNode}
onFocusedNodeChange={handleExpandedNodesChange}
defaultExpandedNodes={['grid', 'charts']}
>
<TreeItem nodeId="grid" label="Data Grid">
<TreeItem nodeId="grid-community" label="@mui/x-data-grid" />
<TreeItem nodeId="grid-pro" label="@mui/x-data-grid-pro" />
<TreeItem nodeId="grid-premium" label="@mui/x-data-grid-premium" />
</TreeItem>
<TreeItem nodeId="pickers" label="Date and Time Pickers">
<TreeItem nodeId="pickers-community" label="@mui/x-date-pickers" />
<TreeItem nodeId="pickers-pro" label="@mui/x-date-pickers-pro" />
</TreeItem>
<TreeItem nodeId="charts" label="Charts">
<TreeItem nodeId="charts-community" label="@mui/x-charts" />
</TreeItem>
<TreeItem nodeId="tree-view" label="Tree View">
<TreeItem nodeId="tree-view-community" label="@mui/x-tree-view" />
</TreeItem>
</SimpleTreeView>
</Box>
</Box>
);
}
28 changes: 28 additions & 0 deletions docs/data/tree-view/simple-tree-view/focus/focus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
productId: x-tree-view
title: Simple Tree View - Focus
components: SimpleTreeView, TreeItem
packageName: '@mui/x-tree-view'
githubLabel: 'component: tree view'
waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
---

# Simple Tree View - Focus

<p class="description">Handle how users can focus items.</p>

## Controlled focus

Use the `focusedNode` prop to control the focused item.

You can use the `onFocusedNodeChange` prop to listen to changes in the focused item and update the prop accordingly.

{{"demo": "FocusedSimpleTreeView.js"}}

:::info

- The focus is **controlled** when its parent manages it by providing a `focusedNode` prop.
- The focus is **uncontrolled** when it is managed by the component's own internal state. This state can be initialized using the `defaultFocusedNode` prop.

Learn more about the _Controlled and uncontrolled_ pattern in the [React documentation](https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components).
:::
Loading