There is playground example on Popper component page of material-ui. To add arrow they use arrowRef. Please explain me where do they get it from?
-
Did you get arrowRef from where , If yes please feel free to reply as am troubling with same issue – Sooraj Jose Feb 23 '20 at 07:00
4 Answers
You can find the source code of the Material UI Popper "Scroll Playgroud" example here: https://github.com/mui-org/material-ui/blob/4f2a07e140c954b478a6670c009c23a59ec3e2d4/docs/src/pages/components/popper/ScrollPlayground.js
As you can see, there is some extra styling that you will need to add to your app to display the arrow correctly, because it's not included in the Material UI library itself.

- 358
- 2
- 7
-
1Best answer (although I would have pointed to the [master branch](https://github.com/mui-org/material-ui/blob/master/docs/src/pages/components/popper/ScrollPlayground.js) instead). Since MUI is using Popper.js, also check out the [Arrow tutorial](https://popper.js.org/docs/v2/tutorial/#arrow) on their website. – Gyum Fox Jun 18 '21 at 07:51
For others looking for a concrete, reusable component that is simple to use like Tooltip
but has a more interactive nature like Popper
or Popover
you can lift and shift the RichTooltip
component from the following sandbox I created - it's typescript too. Hope this helps the next person and hides the complexity of arrows for you.

- 4,908
- 3
- 35
- 52
-
This may not be the acceptable answer, but it's a VERY good solution, with workable codes and demonstration in CodeSandbox. Thanks for the great demo! – Someone Special Oct 20 '20 at 10:38
-
-
-
-
For anyone else that needs it, the OP is asking about Material-UI Poppers.
Dmitriy,
Think of React Refs as a variable that always references the element (if rendered) OUTSIDE of the DOM. React best practices are typically to stay out of the DOM if at all possible. There are of course exceptions to this, but it's the rule of thumb.
In this particular instance, it appears that they are creating an element elsewhere and referencing it using the ref so that it can be utilized by the Popper. I found an example of this here. It's a little hard to read through, but the jist is that he creates a span and styles it how he wants to be applied.

- 1,562
- 8
- 15
-
I’ve seen this style for arrow in several places before, but I couldn’t expect that it is arrow by itself!! I mean that it’s totally unexpected effect (at least for me) , that setting zero height and width and non-zero borders brings an arrow. Wouldn’t you be so kind explaining, why they use && at the beginning of tagged template literal for StyledPopper in your example code? – DmitriyBelovol Aug 15 '19 at 19:51
-
I've actually never seen it before, but it's apparently a way to bump the classNames up for overwriting inline styles. https://medium.com/@pitipatdop/10-useful-tips-for-styled-components-b7710b021e6a – technicallynick Aug 15 '19 at 20:06
-
I’ve found explanation in styled-components FAQ. The aim is to rise rule specificity. Every & becomes a generated classname selector. – DmitriyBelovol Aug 15 '19 at 20:13
-
One more question. What is the reason for &:before clause in aforementioned example? I’ve tried to change rules under this selector in playground- nothing changed. – DmitriyBelovol Aug 16 '19 at 06:08
-
Looking at the DOM, I don't see any of those :before pseudo selectors applied. It seems you could safely not use that part of the style. – technicallynick Aug 16 '19 at 14:45
MUI v5
- Add the modifiers for arrow. Make sure a proper ref is provided.
const [arrowRef, setArrowRef] = useState(null);
<Popper
modifiers={[
{
name: 'arrow',
enabled: true,
options: {
element: arrowRef,
}
}
]}
>
<Box component="span" className="arrow" ref={setArrowRef} />
</Popper>
- Add arrow specific styles.
const styles = {
arrow: {
position: 'absolute',
fontSize: 7,
width: '3em',
height: '3em',
'&::before': {
content: '""',
margin: 'auto',
display: 'block',
width: 0,
height: 0,
borderStyle: 'solid',
},
}
};
<Box component="span" className="arrow" ref={setArrowRef} sx={styles.arrow}/>
- Add styles for making CSS triangles used by arrow. Make a styled Popper, as Popper doesn't support
sx
prop.
const StyledPopper = styled(Popper)(({ theme }) => ({ // You can replace with `PopperUnstyled` for lower bundle size.
zIndex: 1,
maxWidth: '375px',
width: '100%',
'&[data-popper-placement*="bottom"] .arrow': {
top: 0,
left: 0,
marginTop: '-0.9em',
width: '3em',
height: '1em',
'&::before': {
borderWidth: '0 1em 1em 1em',
borderColor: `transparent transparent ${theme.palette.background.paper} transparent`,
},
},
'&[data-popper-placement*="top"] .arrow': {
bottom: 0,
left: 0,
marginBottom: '-0.9em',
width: '3em',
height: '1em',
'&::before': {
borderWidth: '1em 1em 0 1em',
borderColor: `${theme.palette.background.paper} transparent transparent transparent`,
},
},
'&[data-popper-placement*="right"] .arrow': {
left: 0,
marginLeft: '-0.9em',
height: '3em',
width: '1em',
'&::before': {
borderWidth: '1em 1em 1em 0',
borderColor: `transparent ${theme.palette.background.paper} transparent transparent`,
},
},
'&[data-popper-placement*="left"] .arrow': {
right: 0,
marginRight: '-0.9em',
height: '3em',
width: '1em',
'&::before': {
borderWidth: '1em 0 1em 1em',
borderColor: `transparent transparent transparent ${theme.palette.background.paper}`,
},
},
}));
Replace the Popper
with the above StyledPopper
<StyledPopper
modifiers={[
{
name: 'arrow',
enabled: true,
options: {
element: arrowRef,
}
]}
>
<Box component="span" className="arrow" ref={setArrowRef} />
// rest of the code
</StyledPopper>

- 89
- 1
- 2
- 10

- 2,499
- 11
- 23