✨ feat: expose Sidebar drawer slot classNames and raise root z-index#631
Merged
Conversation
Open drawers were rendering behind sticky/fixed app bars because the
Drawer's root wrapper at `z-40` creates a stacking context that traps
its panel — even with `z-[51]` on the panel, the drawer as a whole stays
below a `z-50` header from the outside. The Sidebar wrapper now passes
`classNames.root: 'z-[60]'` to the Drawer in `drawer` mode so the
stacking context itself wins over standard sticky headers and most
floating triggers without consumers having to fight twmerge through the
panel className.
Adds a `drawerClassNames` prop on the Sidebar (mirroring `Drawer`'s
`classNames` shape: `root`, `overlay`, `panel`, `closeButton`, `content`,
`header`, `body`, `footer`, `resizeHandle`) so apps can:
- Raise the root z-index further (`drawerClassNames={{ root: 'z-[100]' }}`)
when the host has higher-z layers it must still cover.
- Re-position the close button (`drawerClassNames={{ closeButton: 'top-1/2 -translate-y-1/2' }}`)
to align with a custom header layout.
- Drop the panel's horizontal padding (`drawerClassNames={{ panel: 'px-0' }}`)
so dividers below the logo or between groups can span edge-to-edge.
User-provided classes are merged with internal defaults via `cn`, so they
win on conflicts thanks to twmerge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related Sidebar fixes for
drawermode:Drawer rendered behind sticky app bars. The Drawer wraps its overlay and panel inside a
fixed inset-0 z-40root that creates a stacking context. Even withz-[51]on the panel, the whole drawer stays trapped at z-40 from the outside, so a host app with a stickyz-50header (a very common pattern) painted on top of the open drawer instead of being covered by it. The Sidebar Wrapper now passesclassNames.root: 'z-[60]'to the Drawer indrawermode so the stacking-context root itself wins over standard sticky headers and most floating triggers without consumers having to fight twmerge through the panel className.No way to style individual drawer slots. The Sidebar previously only allowed customizing the panel via
wrapperClassName(and even that was applied to the panel, not the root). Apps can now pass adrawerClassNamesprop matchingDrawer's fullclassNamesshape —root,overlay,panel,closeButton,content,header,body,footer,resizeHandle.Implementation
Sidebar.types.ts— addsdrawerClassNames?: DrawerClassNames(imported from@/components/Drawer/Drawer.types).Wrapper.tsx— destructuresdrawerClassNames, spreads it onto theDrawer'sclassNamesand merges viacnagainst the internal defaults so user classes win on conflict:root: defaultz-[60]+ user'sroot.panel:wrapperSiderbarVariants({ mode: 'expanded' })+'h-full border-r-0'+wrapperClassName+ user'spanel.content: default'gap-0'+ user'scontent.closeButton,overlay,header,body,footer,resizeHandle) are forwarded as-is via spread.Use cases
Backwards compatibility
No breaking changes. New prop is optional. Default
z-[60]for the drawer root is the only behavior change — apps that depended on the previousz-40and had higher-z elements they wanted to keep on top can override viadrawerClassNames={{ root: 'z-40' }}to opt back in.Tests
Existing
Sidebar.test.tsxcovers drawer open/close/auto-close paths. Full suite:429 / 429passing locally.Test plan
z-50sticky AppBar: drawer panel covers the AppBar when open (previously hidden behind it).drawerClassNames={{ closeButton: 'top-1/2 -translate-y-1/2' }}re-positions the X button.drawerClassNames={{ panel: 'px-0' }}lets a childborder-bspan the full panel width.drawerClassNames={{ root: 'z-[100]' }}raises the drawer above other high-z layers.