paragon
paragon copied to clipboard
z-index revamp (z-index hooks)
from @bradenmacdonald on slack
Hey folks, does Paragon have a philosophy for handling z-index conflicts? For example, we are trying to use a
Form.Autosuggest
inside a modal, and the autosuggest dropdown is appearing behind parts of the modal (screenshot). I couldn't see any docs about this, and could only find these pre-defined z-index classes. If that's all that Paragon has right now, it's too simplistic. Because obviously a modal should normally be higher than a dropdown, but a dropdown in a modal should be higher than a modal. I would also argue that if you had a proper layer system, you could put popover and tooltip lower than modal as well.
One approach I know of for solving this is using utility classes (Tailwind style). Currently, the
Form.Autosuggest
has some code like.pgn__form-autosuggest__dropdown { ... z-index: $zindex-dropdown; ... }
. Adding CSS rules to give such components a higher z-index conditionally (when they're in a modal) is problematic, because either the Autosuggest component has to be aware of all the possible layers like modals and account for them (.modal-layer & { z-index: $zindex-modal + $zindex-dropdown }
) or the Modal component has to be aware of all the possible components and account for them (& .dropdown { z-index: $zindex-modal + $zindex-dropdown
). => But if you use a small set of predefined classes like.zindex-dropdown
so that the autosuggest has that extra utility class, then it's a bit easier to plan for the interactions like.zindex-modal .zindex-dropdown .zindex-tooltip { z-index: $zindex-modal + $zindex-dropdown + $zindex-tooltip }
(a tooltip over a dropdown in a modal), and your components don't have to otherwise be aware of each other.
But as you can see from the example of "a tooltip in a dropdown in a modal", managing those rules can still get complex. So I have found that a simple zindex hook provides the cleanest solution for this problem, by using the React tree to determine the z-index of each component by using the z-index of its parent (from context) and adding some fixed amount based on the type of component. (example of use in a Modal)
Apparently, using CSS isolation: isolate
may be an even simpler way to solve this issue :)
Ref: https://x.com/adamwathan/status/1798704643222212683