Repository navigation
[docs] Add sticky headers recipe to RichTreeView customization - #22908
michelengelen merged 7 commits into
Conversation
Signed-off-by: michel <jsnerdic@gmail.com>
Deploy previewBundle size
Check out the code infra dashboard for more information about this PR. |
LukasTy
left a comment
There was a problem hiding this comment.
Looks nice. 👍
WDYT about adding some extra padding at the bottom of the tree view to trigger stickiness for all parents?
Claude Opus 5 review
Verdict
Nice, well-scoped recipe and the mechanism does work -- verified on the deploy preview that depth-0 headers pin at 0px, depth-1 at 32px, z-index: calc(...) resolves to 100/99, and Collapse is overflow: visible once entered so nothing clips the sticky rows. Three things worth fixing before merge.
Findings
-
Expanded rows lose their hover / focus / selection styling.
.css-hash .MuiTreeItem-content[data-expanded]is specificity (0,3,0), which beatsTreeItem's own:hover,[data-focused]and[data-selected](0,2,0), and also wins the tie against[data-selected]:hoverand[data-selected][data-focused]on source order. Confirmed on the preview: an expanded row staysrgb(255,255,255)whendata-focused/data-selectedare set, while a leaf row correctly showsrgba(0,0,0,0.12)/rgba(25,118,210,0.08). BecauseTreeItemRootsetsoutline: 0, that leaves every expanded item with no visible keyboard focus indicator at all. The opaque background is genuinely needed, so layer the state colors on top of it instead of dropping them -- I tested this variant on the preview and it keeps the opaque base while restoring the state colors:backgroundColor: (theme.vars || theme).palette.background.paper, backgroundImage: 'linear-gradient(var(--sticky-overlay, transparent), var(--sticky-overlay, transparent))', '&:hover': { '--sticky-overlay': (theme.vars || theme).palette.action.hover }, '&[data-focused]': { '--sticky-overlay': (theme.vars || theme).palette.action.focus }, // and the same for '&[data-selected]' -
The recipe only works with the nested DOM structure. With flat DOM (
RichTreeViewProdefault,domStructure="flat", or virtualization) everyliis a direct child of theuland is exactly one row tall, so the sticky content can never leave its containing block and the CSS silently does nothing. The two demos immediately above this one on the same page already carry that flat-vs-nested caveat; this section should say the same. -
ITEM_HEIGHT = 32is an unenforced assumption and its comment describes the wrong thing. The comment reads "One level of indentation, must match the depth used intopbelow", but the constant is the row height, not the indentation. Nothing pins the row to 32px -- it just happens to bebody1's 24px line-height plus 8px of padding, so any typography or density change silently breaks the stacking offsets.RichTreeViewacceptsitemHeight, which sets--TreeView-itemHeightand forces the content height, so passingitemHeight={ITEM_HEIGHT}makes the recipe self-consistent. -
Nit:
theme.vars ?? theme-- every other docs demo usestheme.vars || theme(33 occurrences, 0 with??).
…8324-sticky-headers
Signed-off-by: michel <jsnerdic@gmail.com>
noraleonte
left a comment
There was a problem hiding this comment.
LGTM after a few nits 👌 Great job
| // Extra space at the bottom so the last parents can also reach the top | ||
| // of the scroll container and stick. | ||
| paddingBottom: 224, | ||
| // Expanded items stick to the top of the scroll container while any of |
There was a problem hiding this comment.
I think we can shorten all of these code comments and only leave a one liner comm if it is truly necessary. i.e. on the top or zIndex calculation
Otherwise they seem to 'pollute' the demo and also a bit redundant since most of these are stated in the .md above
| import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; | ||
| import { treeItemClasses } from '@mui/x-tree-view/TreeItem'; | ||
|
|
||
| const MUI_X_PRODUCTS = [ |
There was a problem hiding this comment.
can't we separate this to a new file? (there might already be a demo data file like this)
There was a problem hiding this comment.
yes, extraction to a file is an established docs pattern, but there is no existing file to reuse
We would need to create a new variable to test this. The reason why: in order to properly show the sticky header demo we need a data tree that has at least 3 levels.
If you want I can add a new variable and align the other demos with this as well (since most of them use inline data anyways) in a follow-up to this.
WDYT?
… files Signed-off-by: michel <jsnerdic@gmail.com>
Adds a new "Sticky headers" demo to the Tree View customization docs, showing how to pin expanded items to the top of a scrollable
RichTreeViewusingposition: stickyand the--TreeView-itemDepthCSS variable so deeper nested headers stack below shallower ones.Fixes #18324