@@ -112,21 +112,39 @@ export const DropdownMenu = ({ children, className, buttonRef, ...props }) => {
112
112
const [ isPositionCalculated , setIsPositionCalculated ] = useState ( false ) ;
113
113
114
114
useEffect ( ( ) => {
115
- if ( open ) {
116
- if ( buttonRef ?. current ) {
117
- const rect = buttonRef . current . getBoundingClientRect ( ) ;
118
- setMenuPosition ( {
119
- top : rect . bottom ,
120
- left : rect . right ,
121
- } ) ;
122
- setIsPositionCalculated ( true ) ;
123
- } else {
124
- setIsPositionCalculated ( true ) ;
125
- }
126
- } else {
115
+ if ( ! buttonRef ?. current ) {
116
+ // if buttonRef is not provided, or does not exists, do not calculate position
117
+ setIsPositionCalculated ( true ) ;
118
+ return ;
119
+ }
120
+ if ( ! open ) {
121
+ // reset position when dropdown is closed
127
122
setIsPositionCalculated ( false ) ;
123
+ return ;
124
+ }
125
+
126
+ const rect = buttonRef . current . getBoundingClientRect ( ) ;
127
+
128
+ let leftAnchor = rect . right ;
129
+ let topAnchor = rect . bottom ;
130
+
131
+ if ( dropdownRef . current ) {
132
+ const viewportWidth = window . innerWidth ;
133
+ const menuWidth = dropdownRef . current . offsetWidth ;
134
+ leftAnchor = Math . min ( leftAnchor , viewportWidth - menuWidth ) ;
135
+ leftAnchor = Math . max ( leftAnchor , 0 ) ;
136
+
137
+ const viewportHeight = window . innerHeight ;
138
+ const menuHeight = dropdownRef . current . offsetHeight ;
139
+ topAnchor = Math . min ( topAnchor , viewportHeight - menuHeight ) ;
140
+ topAnchor = Math . max ( topAnchor , 0 ) ;
128
141
}
129
142
143
+ setMenuPosition ( {
144
+ top : topAnchor ,
145
+ left : leftAnchor ,
146
+ } ) ;
147
+ setIsPositionCalculated ( true ) ;
130
148
} , [ open , buttonRef ] ) ;
131
149
132
150
const menuStyle = buttonRef ?. current ? { top : menuPosition . top , left : menuPosition . left } : { } ;
0 commit comments