Skip to content

Commit 9a8af53

Browse files
committed
refactor(CDropdown): add focus trap when used with portal
1 parent cf37758 commit 9a8af53

File tree

2 files changed

+33
-24
lines changed

2 files changed

+33
-24
lines changed

packages/coreui-react/src/components/dropdown/CDropdown.tsx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { getNextActiveElement, isRTL } from '../../utils'
2222

2323
import type { Alignments, Directions } from './types'
2424
import { getPlacement } from './utils'
25+
import { CFocusTrap } from '../focus-trap'
2526

2627
export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIElement> {
2728
/**
@@ -288,7 +289,11 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
288289
}, [dropdownToggleElement, allowPopperUse, destroyPopper, onHide])
289290

290291
const handleKeydown = useCallback((event: KeyboardEvent) => {
291-
if (dropdownMenuRef.current && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
292+
if (!dropdownMenuRef.current) {
293+
return
294+
}
295+
296+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
292297
event.preventDefault()
293298
const target = event.target as HTMLElement
294299
const items = [
@@ -404,26 +409,28 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
404409

405410
return (
406411
<CDropdownContext.Provider value={contextValues}>
407-
{variant === 'input-group' ? (
408-
<>{children}</>
409-
) : (
410-
<Component
411-
className={classNames(
412-
variant === 'nav-item' ? 'nav-item dropdown' : variant,
413-
{
414-
'dropdown-center': direction === 'center',
415-
'dropup dropup-center': direction === 'dropup-center',
416-
[`${direction}`]:
417-
direction && direction !== 'center' && direction !== 'dropup-center',
418-
},
419-
className
420-
)}
421-
{...rest}
422-
ref={forkedRef}
423-
>
424-
{children}
425-
</Component>
426-
)}
412+
<CFocusTrap active={portal && _visible} additionalContainer={dropdownMenuRef} restoreFocus>
413+
{variant === 'input-group' ? (
414+
<>{children}</>
415+
) : (
416+
<Component
417+
className={classNames(
418+
variant === 'nav-item' ? 'nav-item dropdown' : variant,
419+
{
420+
'dropdown-center': direction === 'center',
421+
'dropup dropup-center': direction === 'dropup-center',
422+
[`${direction}`]:
423+
direction && direction !== 'center' && direction !== 'dropup-center',
424+
},
425+
className
426+
)}
427+
{...rest}
428+
ref={forkedRef}
429+
>
430+
{children}
431+
</Component>
432+
)}
433+
</CFocusTrap>
427434
</CDropdownContext.Provider>
428435
)
429436
}

packages/docs/content/components/dropdown/examples/DropdownOptionsExample.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ export const DropdownOptionsExample = () => {
1212
<CDropdownItem href="#">Something else here</CDropdownItem>
1313
</CDropdownMenu>
1414
</CDropdown>
15-
<CDropdown portal>
16-
<CDropdownToggle color="secondary">Portal</CDropdownToggle>
17-
<CDropdownMenu>
15+
<CDropdown portal variant="input-group">
16+
<CDropdownToggle color="secondary" aria-controls="dropdownMenuInPortal">
17+
Portal
18+
</CDropdownToggle>
19+
<CDropdownMenu id="dropdownMenuInPortal">
1820
<CDropdownItem href="#">Action</CDropdownItem>
1921
<CDropdownItem href="#">Another action</CDropdownItem>
2022
<CDropdownItem href="#">Something else here</CDropdownItem>

0 commit comments

Comments
 (0)