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
Select: Portal select menu to document.body #36398
Conversation
Awesome job! this is tricky stuff, and we have had max-width / overflow hidden/auto before in the Modal but it issues (esp with selects) made us change that back. There are some other Modals with selects in them (like dashboard SaveAs modal). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! We don't have any use cases of Selects in Modal in Enterprise as far as I can see. Regarding the value mappings and modal in general, I think a nice improvement would be if the button actions wouldn't be a pat of scrolling content and always stayed visible during overflow, but this is probably out of scope of this PR.
@Clarity-89 +1 on that. i think every major design library out there (bootstrap, material, carbon, etc.) separates the actions from the content for this reason. |
An idea would to add a footer prop to Modal that automatically wraps the footer content in a ModalButtonRow, and the footer would live outside the content div |
@@ -41,6 +41,7 @@ export interface SelectCommonProps<T> { | |||
minMenuHeight?: number; | |||
maxVisibleValues?: number; | |||
menuPlacement?: 'auto' | 'bottom' | 'top'; | |||
menuPortalTarget?: HTMLElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The more react-select
stuff we expose in our API, the harder it will be to move away from it. I don't think it's in the current todo, but the Select component has been a real pain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it is okay in this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, that's a good point. i'm not sure how we can avoid it though.
we could attach all selects to document.body
by default? that would have a pretty wide impact though, and is presumably slightly worse for performance.
ideally we'd want something where the select detects it's in a modal and attaches itself to document.body automatically 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I played around a bit with the portaling etc. last year, and it never ended up good. When this is merged we might have to keep an eye out for Select bugs.
Let me just check a few places before you merge this PR.
yep, i don't make raising that/taking it on as an enhancement following this PR 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, let's go! Be on the lookout for weird Select bugs though!
@tskarhed @torkelo what do you think about using context to determine where to attach the we could export a context object from <Portal>
<div className={cx(styles.modal, className)}>
<SelectMenuTargetContext.Provider value={document.body}>
<div className={headerClass}>
{typeof title === 'string' && <DefaultModalHeader {...props} title={title} />}
{typeof title !== 'string' && title}
<div className={styles.modalHeaderClose}>
<IconButton surface="header" name="times" size="xl" onClick={onDismiss} />
</div>
</div>
<div className={cx(styles.modalContent, contentClassName)}>{children}</div>
</SelectMenuTargetContext.Provider>
</div>
<div
className={styles.modalBackdrop}
onClick={onClickBackdrop || (closeOnBackdropClick ? onDismiss : undefined)}
/>
</Portal> that way we wouldn't have to expose any new props on |
ok, i've updated this to portal the only thing left to discuss is what we do about z-index. in this PR the select menu overlays everything, including modals. i can imagine there's cases where that's not desirable. but when a select is within a modal, it has to overlay the modal, else it's broken. so it seems like we'll need to make it configurable in some way. either by exposing a prop, or setting it via context, or something else. |
Love that you included instructions on how to change the tests in this PR! Will help people that might run into this issue! 🙌🏻 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome job on this ash!
only thing that can be improved would be a test helper function to select options so you not have to always pass in the container argument, should make it easier for to change this in the future without updating all tests (I hope we do no need to!!)
unit test util method created. once everything goes green i'll merge 🤞 |
menuPortal: (base: any) => ({ | ||
...base, | ||
zIndex: theme.zIndex.portal, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was that it? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oooo maybe, forgot about that change 😂
* main: (85 commits) Chore: Ease the migration of always using context.Context when interacting with the bus (grafana#36733) Datasource: Improve default timeout settings for HTTP client provider (grafana#36621) Expand the value of math and reduce expressions in annotations and labels (grafana#36611) User analytics: Use user email as Rudderstack id (grafana#36788) Select: Block scroll on select instead of trying to hide the menu (grafana#36783) Chore: Upgrade grafana-plugin-sdk-go to v0.110.0 (grafana#36763) Plugins: Use plugin.pluginDir as source of truth for plugin location (grafana#36711) switch to json resp for errors (grafana#36743) Docs: New index page with list of all visualizations and panels (grafana#36756) OptionsUI: add standard field name picker (grafana#36732) Docs:Adjust azuread.md for Powershell UUID command (grafana#27323) Update _index.md (grafana#35595) AzureMonitor: Improve Azure Resource Graph docs (grafana#34450) Update queries.md (grafana#31941) Update configuration.md (grafana#30695) Remove verify-drone for Windows (grafana#36759) Modal: Force modal content to overflow with scroll (grafana#36754) InfluxDB: InfluxQL: adds tags to timeseries data (grafana#36702) Add AGPL license update to 8.0 changelog, release notes, What's New (grafana#36742) Select: Portal select menu to document.body (grafana#36398) ...
After changes in #36398 the menu is detached from the container div causing useClickAway not recognising that the click happened outside.
What this PR does / why we need it:
Select
menu todocument.body
auto
positions theSelect
menu for better placementSelect
menu when scrolling anywhere outside of theSelect
menuportal
z-index value set to higher than the modalPortal
component as a functional component so it can utiliseuseTheme2
SelectBase
tests as RTL testsreact-select-event
has an extra option to specify where the menu is contained. e.g.@grafana/ui
:Select
container, need to look for options on the body. e.g.selectOption
here: https://github.com/grafana/grafana/blob/main/packages/grafana-e2e/src/flows/selectOption.ts to work with the new structure.Select
in something likeClickOutsideWrapper
will no longer work. the same functionality can be achieved usingSelect
'sonCloseMenu
/isOpen
props.some screenshots:
Which issue(s) this PR fixes:
Special notes for your reviewer: