Skip to content

Commit

Permalink
[TreeView] Allow to customize the indentation of nested items (mui#13225
Browse files Browse the repository at this point in the history
)
  • Loading branch information
flaviendelangle authored and thomasmoon committed Sep 6, 2024
1 parent d64827a commit 8fea5f5
Show file tree
Hide file tree
Showing 24 changed files with 304 additions and 10 deletions.
9 changes: 8 additions & 1 deletion docs/data/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ const pages: MuiPage[] = [
children: [
{ pathname: '/x/react-tree-view', title: 'Overview' },
{ pathname: '/x/react-tree-view/getting-started' },
{ pathname: '/x/react-tree-view/accessibility' },
{
pathname: '/x/react-tree-view/simple-tree-view',
subheader: 'Simple Tree View',
Expand All @@ -505,6 +504,14 @@ const pages: MuiPage[] = [
{ pathname: '/x/react-tree-view/rich-tree-view/focus' },
],
},
{
pathname: '/x/react-tree-view/common-features',
subheader: 'Common features',
children: [
{ pathname: '/x/react-tree-view/accessibility' },
{ pathname: '/x/react-tree-view/tree-item-customization', title: 'Item customization' },
],
},
{
pathname: '/x/api/tree-view-group',
title: 'API Reference',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import Box from '@mui/material/Box';

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' },
],
},
];

export default function IndentationAtItemLevel() {
return (
<Box sx={{ height: 220, flexGrow: 1, maxWidth: 400 }}>
<RichTreeView
items={MUI_X_PRODUCTS}
experimentalFeatures={{ indentationAtItemLevel: true }}
defaultExpandedItems={['grid']}
/>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';

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' },
],
},
];

export default function IndentationAtItemLevel() {
return (
<Box sx={{ height: 220, flexGrow: 1, maxWidth: 400 }}>
<RichTreeView
items={MUI_X_PRODUCTS}
experimentalFeatures={{ indentationAtItemLevel: true }}
defaultExpandedItems={['grid']}
/>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<RichTreeView
items={MUI_X_PRODUCTS}
experimentalFeatures={{ indentationAtItemLevel: true }}
defaultExpandedItems={['grid']}
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import Box from '@mui/material/Box';

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' },
],
},
];

export default function ItemChildrenIndentationProp() {
return (
<Box sx={{ height: 220, flexGrow: 1, maxWidth: 400 }}>
<RichTreeView
items={MUI_X_PRODUCTS}
itemChildrenIndentation={24}
defaultExpandedItems={['grid']}
/>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';

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' },
],
},
];

export default function ItemChildrenIndentationProp() {
return (
<Box sx={{ height: 220, flexGrow: 1, maxWidth: 400 }}>
<RichTreeView
items={MUI_X_PRODUCTS}
itemChildrenIndentation={24}
defaultExpandedItems={['grid']}
/>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<RichTreeView
items={MUI_X_PRODUCTS}
itemChildrenIndentation={24}
defaultExpandedItems={['grid']}
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
productId: x-tree-view
title: Tree Item Customization
components: SimpleTreeView, RichTreeView, TreeItem, TreeItem2
packageName: '@mui/x-tree-view'
githubLabel: 'component: tree view'
waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
---

# Tree Item Customization

<p class="description">Learn how to customize the Tree Item component.</p>

## Basics

### Change nested item's indentation

Use the `itemChildrenIndentation` prop to change the indentation of the nested items.
By default, a nested item is indented by `12px` from its parent item.

{{"demo": "ItemChildrenIndentationProp.js"}}

:::success
This feature is compatible with both the `TreeItem` and `TreeItem2` components
If you are using a custom Tree Item component, and you want to override the padding,
then apply the following padding to your `groupTransition` element:

```ts
const CustomTreeItem2GroupTransition = styled(TreeItem2GroupTransition)(({ theme }) => ({
// ...other styles
paddingLeft: `var(--TreeView-itemChildrenIndentation)`,
}
```
If you are using the `indentationAtItemLevel` prop, then instead apply the following padding to your `content` element:
```ts
const CustomTreeItem2Content = styled(TreeItem2Content)(({ theme }) => ({
// ...other styles
paddingLeft:
`calc(${theme.spacing(1)} + var(--TreeView-itemChildrenIndentation) * var(--TreeView-itemDepth))`,
}
```
:::
### Apply the nested item's indentation at the item level
By default, the indentation of nested items is applied by the `groupTransition` slot of its parent (i.e.: the DOM element that wraps all the children of a given item).
This approach is not compatible with upcoming features like the reordering of items using drag & drop.
To apply the indentation at the item level (i.e.: have each item responsible for setting its own indentation using the `padding-left` CSS property on its `content` slot),
you can use the `indentationAtItemLevel` experimental feature.
It will become the default behavior in the next major version of the Tree View component.
{{"demo": "IndentationAtItemLevel.js"}}
:::success
This feature is compatible with both the `TreeItem` and `TreeItem2` components and with the `itemChildrenIndentation` prop.
If you are using a custom Tree Item component, and you want to override the padding,
then apply the following padding to your `content` element:
```ts
const CustomTreeItem2Content = styled(TreeItem2Content)(({ theme }) => ({
// ...other styles
paddingLeft:
`calc(${theme.spacing(1)} + var(--TreeView-itemChildrenIndentation) * var(--TreeView-itemDepth))`,
}
```
:::
6 changes: 5 additions & 1 deletion docs/pages/x/api/tree-view/rich-tree-view.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
"returned": "boolean"
}
},
"itemChildrenIndentation": {
"type": { "name": "union", "description": "number<br>&#124;&nbsp;string" },
"default": "12px"
},
"multiSelect": { "type": { "name": "bool" }, "default": "false" },
"onExpandedItemsChange": {
"type": { "name": "func" },
Expand Down Expand Up @@ -138,6 +142,6 @@
"forwardsRefTo": "HTMLUListElement",
"filename": "/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/x/react-tree-view/getting-started/\">Tree View - Getting Started</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/customization/\">Rich Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/expansion/\">Rich Tree View - Expansion</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/focus/\">Rich Tree View - Focus</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/items/\">Rich Tree View - Items</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/selection/\">Rich Tree View - Selection</a></li></ul>",
"demos": "<ul><li><a href=\"/x/react-tree-view/getting-started/\">Tree View - Getting Started</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/customization/\">Rich Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/expansion/\">Rich Tree View - Expansion</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/focus/\">Rich Tree View - Focus</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/items/\">Rich Tree View - Items</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/selection/\">Rich Tree View - Selection</a></li>\n<li><a href=\"/x/react-tree-view/tree-item-customization/\">Tree Item Customization</a></li></ul>",
"cssComponent": false
}
6 changes: 5 additions & 1 deletion docs/pages/x/api/tree-view/simple-tree-view.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" }
},
"id": { "type": { "name": "string" } },
"itemChildrenIndentation": {
"type": { "name": "union", "description": "number<br>&#124;&nbsp;string" },
"default": "12px"
},
"multiSelect": { "type": { "name": "bool" }, "default": "false" },
"onExpandedItemsChange": {
"type": { "name": "func" },
Expand Down Expand Up @@ -103,6 +107,6 @@
"forwardsRefTo": "HTMLUListElement",
"filename": "/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/x/react-tree-view/getting-started/\">Tree View - Getting Started</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/customization/\">Simple Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/expansion/\">Simple Tree View - Expansion</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/focus/\">Simple Tree View - Focus</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/items/\">Simple Tree View - Items</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/selection/\">Simple Tree View - Selection</a></li></ul>",
"demos": "<ul><li><a href=\"/x/react-tree-view/getting-started/\">Tree View - Getting Started</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/customization/\">Simple Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/expansion/\">Simple Tree View - Expansion</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/focus/\">Simple Tree View - Focus</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/items/\">Simple Tree View - Items</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/selection/\">Simple Tree View - Selection</a></li>\n<li><a href=\"/x/react-tree-view/tree-item-customization/\">Tree Item Customization</a></li></ul>",
"cssComponent": false
}
2 changes: 1 addition & 1 deletion docs/pages/x/api/tree-view/tree-item-2.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,6 @@
"muiName": "MuiTreeItem2",
"filename": "/packages/x-tree-view/src/TreeItem2/TreeItem2.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/x/react-tree-view/rich-tree-view/customization/\">Rich Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/customization/\">Simple Tree View - Customization</a></li></ul>",
"demos": "<ul><li><a href=\"/x/react-tree-view/rich-tree-view/customization/\">Rich Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/customization/\">Simple Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/tree-item-customization/\">Tree Item Customization</a></li></ul>",
"cssComponent": false
}
2 changes: 1 addition & 1 deletion docs/pages/x/api/tree-view/tree-item.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,6 @@
"forwardsRefTo": "HTMLLIElement",
"filename": "/packages/x-tree-view/src/TreeItem/TreeItem.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/x/react-tree-view/getting-started/\">Tree View - Getting Started</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/customization/\">Rich Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/expansion/\">Rich Tree View - Expansion</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/focus/\">Rich Tree View - Focus</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/items/\">Rich Tree View - Items</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/selection/\">Rich Tree View - Selection</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/customization/\">Simple Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/expansion/\">Simple Tree View - Expansion</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/focus/\">Simple Tree View - Focus</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/items/\">Simple Tree View - Items</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/selection/\">Simple Tree View - Selection</a></li></ul>",
"demos": "<ul><li><a href=\"/x/react-tree-view/getting-started/\">Tree View - Getting Started</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/customization/\">Rich Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/expansion/\">Rich Tree View - Expansion</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/focus/\">Rich Tree View - Focus</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/items/\">Rich Tree View - Items</a></li>\n<li><a href=\"/x/react-tree-view/rich-tree-view/selection/\">Rich Tree View - Selection</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/customization/\">Simple Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/expansion/\">Simple Tree View - Expansion</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/focus/\">Simple Tree View - Focus</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/items/\">Simple Tree View - Items</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/selection/\">Simple Tree View - Selection</a></li>\n<li><a href=\"/x/react-tree-view/tree-item-customization/\">Tree Item Customization</a></li></ul>",
"cssComponent": false
}
4 changes: 4 additions & 0 deletions docs/pages/x/api/tree-view/tree-view.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" }
},
"id": { "type": { "name": "string" } },
"itemChildrenIndentation": {
"type": { "name": "union", "description": "number<br>&#124;&nbsp;string" },
"default": "12px"
},
"multiSelect": { "type": { "name": "bool" }, "default": "false" },
"onExpandedItemsChange": {
"type": { "name": "func" },
Expand Down
7 changes: 7 additions & 0 deletions docs/pages/x/react-tree-view/tree-item-customization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
import * as pageProps from 'docsx/data/tree-view/tree-item-customization/tree-item-customization.md?muiMarkdown';

export default function Page() {
return <MarkdownDocs {...pageProps} />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
"boolean": "<code>true</code> if the item should be disabled."
}
},
"itemChildrenIndentation": {
"description": "Horizontal indentation between an item and its children. Examples: 24, &quot;24px&quot;, &quot;2rem&quot;, &quot;2em&quot;."
},
"multiSelect": {
"description": "If <code>true</code>, <code>ctrl</code> and <code>shift</code> will trigger multiselect."
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
"id": {
"description": "This prop is used to help implement the accessibility logic. If you don&#39;t provide this prop. It falls back to a randomly generated id."
},
"itemChildrenIndentation": {
"description": "Horizontal indentation between an item and its children. Examples: 24, &quot;24px&quot;, &quot;2rem&quot;, &quot;2em&quot;."
},
"multiSelect": {
"description": "If <code>true</code>, <code>ctrl</code> and <code>shift</code> will trigger multiselect."
},
Expand Down
3 changes: 3 additions & 0 deletions docs/translations/api-docs/tree-view/tree-view/tree-view.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
"id": {
"description": "This prop is used to help implement the accessibility logic. If you don&#39;t provide this prop. It falls back to a randomly generated id."
},
"itemChildrenIndentation": {
"description": "Horizontal indentation between an item and its children. Examples: 24, &quot;24px&quot;, &quot;2rem&quot;, &quot;2em&quot;."
},
"multiSelect": {
"description": "If <code>true</code>, <code>ctrl</code> and <code>shift</code> will trigger multiselect."
},
Expand Down
6 changes: 6 additions & 0 deletions packages/x-tree-view/src/RichTreeView/RichTreeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ RichTreeView.propTypes = {
* @returns {boolean} `true` if the item should be disabled.
*/
isItemDisabled: PropTypes.func,
/**
* Horizontal indentation between an item and its children.
* Examples: 24, "24px", "2rem", "2em".
* @default 12px
*/
itemChildrenIndentation: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
items: PropTypes.array.isRequired,
/**
* If `true`, `ctrl` and `shift` will trigger multiselect.
Expand Down
6 changes: 6 additions & 0 deletions packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ SimpleTreeView.propTypes = {
* If you don't provide this prop. It falls back to a randomly generated id.
*/
id: PropTypes.string,
/**
* Horizontal indentation between an item and its children.
* Examples: 24, "24px", "2rem", "2em".
* @default 12px
*/
itemChildrenIndentation: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
/**
* If `true`, `ctrl` and `shift` will trigger multiselect.
* @default false
Expand Down
Loading

0 comments on commit 8fea5f5

Please sign in to comment.