11import { SearchIcon , TriangleDownIcon } from '@primer/octicons-react'
22import React , { useCallback , useMemo } from 'react'
33import type { AnchoredOverlayProps } from '../AnchoredOverlay'
4- import Overlay from '../Overlay '
4+ import { AnchoredOverlay } from '../AnchoredOverlay '
55import type { AnchoredOverlayWrapperAnchorProps } from '../AnchoredOverlay/AnchoredOverlay'
66import Box from '../Box'
77import type { FilteredActionListProps } from '../FilteredActionList'
@@ -12,12 +12,12 @@ import type {TextInputProps} from '../TextInput'
1212import type { ItemProps , ItemInput } from './types'
1313
1414import { Button } from '../Button'
15- import { useAnchoredPosition , useProvidedRefOrCreate } from '../hooks'
15+ import { useProvidedRefOrCreate } from '../hooks'
16+ import type { FocusZoneHookSettings } from '../hooks/useFocusZone'
1617import { useId } from '../hooks/useId'
1718import { useProvidedStateOrCreate } from '../hooks/useProvidedStateOrCreate'
1819import { LiveRegion , LiveRegionOutlet , Message } from '../internal/components/LiveRegion'
1920import { useFeatureFlag } from '../FeatureFlags'
20- import { useFocusTrap } from '../hooks/useFocusTrap'
2121
2222interface SelectPanelSingleSelection {
2323 selected : ItemInput | undefined
@@ -56,6 +56,11 @@ function isMultiSelectVariant(
5656 return Array . isArray ( selected )
5757}
5858
59+ const focusZoneSettings : Partial < FocusZoneHookSettings > = {
60+ // Let FilteredActionList handle focus zone
61+ disabled : true ,
62+ }
63+
5964const areItemsEqual = ( itemA : ItemInput , itemB : ItemInput ) => {
6065 // prefer checking equivality by item.id
6166 if ( typeof itemA . id !== 'undefined' ) return itemA . id === itemB . id
@@ -132,57 +137,6 @@ export function SelectPanel({
132137 }
133138 } , [ placeholder , renderAnchor , selected ] )
134139
135- /* Anchoring logic */
136- const overlayRef = React . useRef < HTMLDivElement > ( null )
137- const inputRef = React . useRef < HTMLInputElement > ( null )
138-
139- const { position} = useAnchoredPosition (
140- {
141- anchorElementRef : anchorRef ,
142- floatingElementRef : overlayRef ,
143- side : 'outside-bottom' ,
144- align : 'start' ,
145- } ,
146- [ open , anchorRef . current , overlayRef . current ] ,
147- )
148-
149- const onAnchorClick = useCallback (
150- ( event : React . MouseEvent < HTMLElement > ) => {
151- if ( event . defaultPrevented || event . button !== 0 ) {
152- return
153- }
154-
155- if ( ! open ) {
156- onOpen ( 'anchor-click' )
157- } else {
158- onClose ( 'anchor-click' )
159- }
160- } ,
161- [ open , onOpen , onClose ] ,
162- )
163-
164- const onAnchorKeyDown = useCallback (
165- ( event : React . KeyboardEvent < HTMLElement > ) => {
166- if ( ! event . defaultPrevented ) {
167- if ( ! open && [ 'ArrowDown' , 'ArrowUp' , ' ' , 'Enter' ] . includes ( event . key ) ) {
168- onOpen ( 'anchor-key-press' , event )
169- event . preventDefault ( )
170- }
171- }
172- } ,
173- [ open , onOpen ] ,
174- )
175-
176- const anchorProps = {
177- ref : anchorRef ,
178- 'aria-haspopup' : true ,
179- 'aria-expanded' : open ,
180- onClick : onAnchorClick ,
181- onKeyDown : onAnchorKeyDown ,
182- }
183- // TODO: anchor should be called button because it's not an anchor anymore
184- const anchor = renderMenuAnchor ? renderMenuAnchor ( anchorProps ) : null
185-
186140 const itemsToRender = useMemo ( ( ) => {
187141 return items . map ( item => {
188142 const isItemSelected = isMultiSelectVariant ( selected ) ? doesItemsIncludeItem ( selected , item ) : selected === item
@@ -218,13 +172,10 @@ export function SelectPanel({
218172 } )
219173 } , [ onClose , onSelectedChange , items , selected ] )
220174
221- /** Focus trap */
222- useFocusTrap ( {
223- containerRef : overlayRef ,
224- disabled : ! open || ! position ,
175+ const inputRef = React . useRef < HTMLInputElement > ( null )
176+ const focusTrapSettings = {
225177 initialFocusRef : inputRef ,
226- returnFocusRef : anchorRef ,
227- } )
178+ }
228179
229180 const extendedTextInputProps : Partial < TextInputProps > = useMemo ( ( ) => {
230181 return {
@@ -238,26 +189,22 @@ export function SelectPanel({
238189
239190 const usingModernActionList = useFeatureFlag ( 'primer_react_select_panel_with_modern_action_list' )
240191
241- if ( ! open ) return < > { anchor } </ >
242-
243192 return (
244193 < LiveRegion >
245- { anchor }
246-
247- < Overlay
248- role = "dialog"
249- aria-labelledby = { titleId }
250- aria-describedby = { subtitle ? subtitleId : undefined }
251- ref = { overlayRef }
252- returnFocusRef = { anchorRef }
253- onEscape = { ( ) => onClose ( 'escape' ) }
254- onClickOutside = { ( ) => onClose ( 'click-outside' ) }
255- ignoreClickRefs = {
256- /* this is required so that clicking the button while the panel is open does not re-open the panel */
257- [ anchorRef ]
258- }
259- { ...position }
260- { ...overlayProps }
194+ < AnchoredOverlay
195+ renderAnchor = { renderMenuAnchor }
196+ anchorRef = { anchorRef }
197+ open = { open }
198+ onOpen = { onOpen }
199+ onClose = { onClose }
200+ overlayProps = { {
201+ role : 'dialog' ,
202+ 'aria-labelledby' : titleId ,
203+ 'aria-describedby' : subtitle ? subtitleId : undefined ,
204+ ...overlayProps ,
205+ } }
206+ focusTrapSettings = { focusTrapSettings }
207+ focusZoneSettings = { focusZoneSettings }
261208 >
262209 < LiveRegionOutlet />
263210 { usingModernActionList ? null : (
@@ -313,7 +260,7 @@ export function SelectPanel({
313260 </ Box >
314261 ) }
315262 </ Box >
316- </ Overlay >
263+ </ AnchoredOverlay >
317264 </ LiveRegion >
318265 )
319266}
0 commit comments