@@ -21,7 +21,7 @@ import type { Placements } from '../../types'
2121import { getNextActiveElement , isRTL } from '../../utils'
2222
2323import type { Alignments , Directions } from './types'
24- import { getPlacement } from './utils'
24+ import { getPlacement , getReferenceElement } from './utils'
2525import { CFocusTrap } from '../focus-trap'
2626
2727export interface CDropdownProps extends HTMLAttributes < HTMLDivElement | HTMLLIElement > {
@@ -161,6 +161,27 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
161161 */
162162 portal ?: boolean
163163
164+ /**
165+ * Sets the reference element for positioning the React Dropdown Menu.
166+ * - `toggle` - The React Dropdown Toggle button (default).
167+ * - `parent` - The React Dropdown wrapper element.
168+ * - `HTMLElement` - A custom HTML element.
169+ * - `React.RefObject` - A custom reference element.
170+ *
171+ * @example
172+ * // Use the parent element as reference for positioning
173+ * <CDropdown reference="parent">
174+ * <CDropdownToggle>Toggle dropdown</CDropdownToggle>
175+ * <CDropdownMenu>
176+ * <CDropdownItem>Action</CDropdownItem>
177+ * <CDropdownItem>Another Action</CDropdownItem>
178+ * </CDropdownMenu>
179+ * </CDropdown>
180+ *
181+ * @since 5.9.0
182+ */
183+ reference ?: 'parent' | 'toggle' | HTMLElement | React . RefObject < HTMLElement | null >
184+
164185 /**
165186 * Defines the visual variant of the React Dropdown
166187 */
@@ -204,6 +225,7 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
204225 popper = true ,
205226 popperConfig,
206227 portal = false ,
228+ reference = 'toggle' ,
207229 variant = 'btn-group' ,
208230 visible = false ,
209231 ...rest
@@ -255,12 +277,12 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
255277 } , [ visible ] )
256278
257279 useEffect ( ( ) => {
258- const toggleElement = dropdownToggleElement
280+ const referenceElement = getReferenceElement ( reference , dropdownToggleElement , dropdownRef )
259281 const menuElement = dropdownMenuRef . current
260- if ( allowPopperUse && menuElement && toggleElement && _visible ) {
261- initPopper ( toggleElement , menuElement , computedPopperConfig )
282+ if ( allowPopperUse && menuElement && referenceElement && _visible ) {
283+ initPopper ( referenceElement , menuElement , computedPopperConfig )
262284 }
263- } , [ dropdownToggleElement ] )
285+ } , [ dropdownToggleElement , reference ] )
264286
265287 useEffect ( ( ) => {
266288 if ( pendingKeyDownEvent !== null ) {
@@ -272,21 +294,21 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
272294 const handleHide = useCallback ( ( ) => {
273295 setVisible ( false )
274296
275- const toggleElement = dropdownToggleElement
276297 const menuElement = dropdownMenuRef . current
298+ const toggleElement = dropdownToggleElement
277299
278300 if ( allowPopperUse ) {
279301 destroyPopper ( )
280302 }
281303
282- toggleElement ?. removeEventListener ( 'keydown' , handleKeydown )
283304 menuElement ?. removeEventListener ( 'keydown' , handleKeydown )
305+ toggleElement ?. removeEventListener ( 'keydown' , handleKeydown )
284306
285307 window . removeEventListener ( 'click' , handleClick )
286308 window . removeEventListener ( 'keyup' , handleKeyup )
287309
288310 onHide ?.( )
289- } , [ dropdownToggleElement , allowPopperUse , destroyPopper , onHide ] )
311+ } , [ allowPopperUse , dropdownToggleElement , destroyPopper , onHide ] )
290312
291313 const handleKeydown = useCallback ( ( event : KeyboardEvent ) => {
292314 if ( ! dropdownMenuRef . current ) {
@@ -316,7 +338,7 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
316338 dropdownToggleElement ?. focus ( )
317339 }
318340 } ,
319- [ autoClose , handleHide ]
341+ [ autoClose , dropdownToggleElement , handleHide ]
320342 )
321343
322344 const handleClick = useCallback (
@@ -357,14 +379,15 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
357379
358380 const handleShow = useCallback (
359381 ( event ?: KeyboardEvent ) => {
360- const toggleElement = dropdownToggleElement
361382 const menuElement = dropdownMenuRef . current
383+ const referenceElement = getReferenceElement ( reference , dropdownToggleElement , dropdownRef )
384+ const toggleElement = dropdownToggleElement
362385
363- if ( toggleElement && menuElement ) {
386+ if ( menuElement && referenceElement && toggleElement ) {
364387 setVisible ( true )
365388
366389 if ( allowPopperUse ) {
367- initPopper ( toggleElement , menuElement , computedPopperConfig )
390+ initPopper ( referenceElement , menuElement , computedPopperConfig )
368391 }
369392
370393 toggleElement . focus ( )
@@ -382,13 +405,14 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
382405 }
383406 } ,
384407 [
385- dropdownToggleElement ,
386408 allowPopperUse ,
387- initPopper ,
388409 computedPopperConfig ,
410+ dropdownToggleElement ,
411+ reference ,
389412 handleClick ,
390413 handleKeydown ,
391414 handleKeyup ,
415+ initPopper ,
392416 onShow ,
393417 ]
394418 )
0 commit comments