[Bug]: Popover - autoSize, Arrow, overflow and scroll
Component
Popover
Package version
9.72.3
React version
17~18
Environment
System:
OS: Windows 11 10.0.26100
CPU: (16) x64 Intel(R) Core(TM) Ultra 7 255H
Memory: 4.76 GB / 31.46 GB
Browsers:
Chrome: 141.0.7390.123
Edge: Chromium (141.0.3537.99)
Firefox: 127.0 - C:\Program Files\Mozilla Firefox\firefox.exe
Internet Explorer: 11.0.26100.1882
npmPackages:
@fluentui/react: ^8.125.0 => 8.125.0
@fluentui/react-calendar-compat: ^0.3.12 => 0.3.12
@fluentui/react-components: ^9.72.3 => 9.72.3
@fluentui/react-datepicker-compat: ^0.6.17 => 0.6.17
@fluentui/react-file-type-icons: ^8.15.0 => 8.15.0
@fluentui/react-icons-mdl2: ^1.4.0 => 1.4.0
@fluentui/react-migration-v8-v9: ^9.9.12 => 9.9.12
@fluentui/style-utilities: ^8.13.3 => 8.13.3
@types/react: 17.0.45 => 17.0.45
@types/react-dom: 17.0.17 => 17.0.17
react: 17.0.1 => 17.0.1
react-dom: 17.0.1 => 17.0.1
Current Behavior
If you use a popover with the autosize option and an arrow, when the scrollbar appears, the arrow is no longer visible; this is due to the overflow.
Expected Behavior
the arrow must appear
Reproduction
https://stackblitz.com/edit/jwx4z77l?file=src%2Fexample.tsx
Steps to reproduce
Drag the cursor onto the button. The popover opens. Check that there is a scroll bar within the popover. If there is a scroll bar, there is no arrow.
Are you reporting an Accessibility issue?
None
Suggested severity
Urgent - No workaround and Products/sites are affected
Products/sites affected
No response
Are you willing to submit a PR to fix?
yes
Validations
- [x] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [x] The provided reproduction is a minimal reproducible example of the bug.
Hello @rgcircum
Thanks for reporting. Can confirm this is happening, it's due to styles applied in maxSize middleware, arrow is in the same container, so when the overflow is applied, arrow is not visible
Analysis
As @mainframev mentioned, the arrow is cropped when positioning={{ autoSize: true }} is used. This occurs because the react-positioning package's maxSize middleware automatically applies overflow-x/overflow-y: auto to the popover surface element when the content exceeds the available space. Since the arrow is a direct child of the popover surface and is positioned outside its parent's boundaries (using negative offsets), the overflow property clips the arrow.
Potential Solutions
We've evaluated several approaches to address this issue:
1. Restructure the DOM (Breaking Change)
Introduce an additional wrapper element to separate the overflow container from the arrow's positioning context:
Current structure:
<PopoverSurface style={{ overflowY: 'auto' }}>
<PopoverArrow style={{ left: '10px', bottom: '-10px' }} />
{children}
</PopoverSurface>
Proposed structure:
<PopoverSurface> {/* No overflow - arrow positioned relative to this */}
<PopoverArrow style={{ left: '10px', bottom: '-10px' }} />
<PopoverContent style={{ overflowY: 'auto' }}> {/* Overflow moved here */}
{children}
</PopoverContent>
</PopoverSurface>
Considerations:
- This is a breaking change that would affect the public API
- Would require modifications to
react-positioningpackage's middleware to target the inner content wrapper instead of the floating element - Could impact multiple components that rely on the current structure (Tooltip, Menu, etc.)
- May break existing custom styling that targets the current DOM structure
2. Automatically Disable Arrow with autoSize
When both withArrow and positioning={{ autoSize: true }} are provided, automatically hide the arrow and optionally show a console warning in development mode.
Considerations:
- Simple implementation with no breaking changes
- Clear trade-off between features
- May not meet user expectations if they explicitly request both features
- Requires clear documentation about the limitation
3. Document as Known Limitation with Workaround (Recommended)
Treat this as a documented limitation and provide a workaround pattern for users who need both features.
Workaround:
<Popover withArrow positioning={{ autoSize: true }}>
<PopoverTrigger disableButtonEnhancement>
<Button>Trigger</Button>
</PopoverTrigger>
<PopoverSurface
style={{ overflowY: 'unset' }} // Override the auto overflow from middleware
tabIndex={-1}
>
<div style={{ overflowY: 'auto', height: '100%' }}> // Add overflow and inherit hight from parent
{/* Long content here */}
</div>
</PopoverSurface>
</Popover>
Live example: https://stackblitz.com/edit/jwx4z77l-atcdxcuy?file=src%2Fexample.tsx
Considerations:
- No breaking changes required
- Users who need both features have a clear, documented path forward
- Maintains flexibility for different use cases
- Can be implemented in userland without library changes
Recommendation
I recommend Option 3 (document as a known limitation) for the following reasons:
- Architectural constraints: The fundamental issue stems from CSS overflow behavior, which cannot easily be worked around without significant structural changes or trade-offs
- Impact scope: Options 1 and 2 would either introduce breaking changes or remove functionality for all users, even those who don't encounter this edge case
-
Rare combination: Using
autoSizewith arrows is relatively uncommon, as most scrollable popovers don't need directional arrows - User flexibility: The workaround gives users full control and is straightforward to implement
- Future compatibility: This approach doesn't prevent us from implementing a more comprehensive solution (like Option 1) in a future major version
So I'd suggest to add this limitation to the Popover documentation with the workaround example, and potentially add a development-mode console warning when both props are used together to guide users to the documentation.
@dmytrokirpa
A breaking change doesn't seem like an option, so we're left with options 2 and 3. I don’t think we should try to render something that won't actually be visible. Ideally, we should combine both options: don't show the arrow when autoSize is enabled, and clearly document this behavior as a known limitation that will be fixed in vNext
A breaking change doesn't seem like an option, so we're left with options 2 and 3. I don’t think we should try to render something that won't actually be visible. Ideally, we should combine both options: don't show the arrow when autoSize is enabled, and clearly document this behavior as a known limitation that will be fixed in vNext
I don't agree; if we choose option 2 - don’t show the arrow when autoSize is enabled - the consumer-side workaround won’t be possible. I think it’s better to add a dev warning that includes a link to the issue/explanation and a workaround example.
@dmytrokirpa A breaking change doesn't seem like an option, so we're left with options 2 and 3. I don’t think we should try to render something that won't actually be visible. Ideally, we should combine both options: don't show the arrow when autoSize is enabled, and clearly document this behavior as a known limitation that will be fixed in vNext
I don't agree; if we choose option 2 -
don’t show the arrow when autoSize is enabled- the consumer-side workaround won’t be possible. I think it’s better to add a dev warning that includes a link to the issue/explanation and a workaround example.
Yeah, I get it, they're mutually exclusive :) Another option we discussed in DMs was adding a new prop to toggle the behavior. That would avoid a breaking change, but it would also add complexity to the positioning API and to the components using it, with questionable benefit since partners probably wouldn’t use it often. Given that, option 3 is the way.
This issue has been automatically marked as stale because it has marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. Thank you for your contributions to Fluent UI!
Apparently, you're waiting for feedback. What can I say? I think the bug should be fixed now, but you don't seem willing to do it in version 9.x.x, and I don't think you ever will.
Apparently, you're waiting for feedback. What can I say? I think the bug should be fixed now, but you don't seem willing to do it in version 9.x.x, and I don't think you ever will.
Hey, we're looking to fix this issue, but it seems like we'd have to make some breaking changes to do so. Since this doesn't happen often and there's a workaround available, it's not considered as urgent - no workaround available. Just let us know if the workaround works for you and if it helps sort things out. If you see a better way to solve the issue that doesn’t involve breaking changes, we’d love to chat about it!
Thanks, the workaround works. Would you like me to close the ticket or leave it open so I don't forget to document this point?