Skip to content

Commit 5a5fb0b

Browse files
committed
exposed useTopLayer scope to consuming components
1 parent 0a8de01 commit 5a5fb0b

File tree

6 files changed

+50
-26
lines changed

6 files changed

+50
-26
lines changed

packages/@headlessui-react/src/components/combobox/combobox.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ export type ComboboxProps<
659659
} | null
660660

661661
onClose?(): void
662-
662+
outsideClickScope?: string
663663
__demoMode?: boolean
664664
}
665665
>
@@ -685,6 +685,7 @@ function ComboboxFn<TValue, TTag extends ElementType = typeof DEFAULT_COMBOBOX_T
685685
// Deprecated, but let's pluck it from the props such that it doesn't end up
686686
// on the `Fragment`
687687
nullable: _nullable,
688+
outsideClickScope,
688689
...theirProps
689690
} = props
690691
let defaultValue = useDefaultValue(_defaultValue)
@@ -806,7 +807,8 @@ function ComboboxFn<TValue, TTag extends ElementType = typeof DEFAULT_COMBOBOX_T
806807
useOutsideClick(
807808
outsideClickEnabled,
808809
[data.buttonElement, data.inputElement, data.optionsElement],
809-
() => actions.closeCombobox()
810+
() => actions.closeCombobox(),
811+
outsideClickScope
810812
)
811813

812814
let slot = useMemo(() => {

packages/@headlessui-react/src/components/dialog/dialog.tsx

+11-4
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ let InternalDialog = forwardRefWithAs(function InternalDialog<
126126
autoFocus = true,
127127
__demoMode = false,
128128
unmount = false,
129+
outsideClickScope,
129130
...theirProps
130131
} = props
131132

@@ -213,10 +214,15 @@ let InternalDialog = forwardRefWithAs(function InternalDialog<
213214
})
214215

215216
// Close Dialog on outside click
216-
useOutsideClick(enabled, resolveRootContainers, (event) => {
217-
event.preventDefault()
218-
close()
219-
})
217+
useOutsideClick(
218+
enabled,
219+
resolveRootContainers,
220+
(event) => {
221+
event.preventDefault()
222+
close()
223+
},
224+
outsideClickScope
225+
)
220226

221227
// Handle `Escape` to close
222228
useEscape(enabled, ownerDocument?.defaultView, (event) => {
@@ -347,6 +353,7 @@ export type DialogProps<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG> =
347353
role?: 'dialog' | 'alertdialog'
348354
autoFocus?: boolean
349355
transition?: boolean
356+
outsideClickScope?: string
350357
__demoMode?: boolean
351358
}
352359
>

packages/@headlessui-react/src/components/listbox/listbox.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ export type ListboxProps<
492492
form?: string
493493
name?: string
494494
multiple?: boolean
495-
495+
outsideClickScope?: string
496496
__demoMode?: boolean
497497
}
498498
>
@@ -515,6 +515,7 @@ function ListboxFn<
515515
horizontal = false,
516516
multiple = false,
517517
__demoMode = false,
518+
outsideClickScope,
518519
...theirProps
519520
} = props
520521

@@ -592,7 +593,8 @@ function ListboxFn<
592593
event.preventDefault()
593594
data.buttonElement?.focus()
594595
}
595-
}
596+
},
597+
outsideClickScope
596598
)
597599

598600
let slot = useMemo(() => {

packages/@headlessui-react/src/components/menu/menu.tsx

+14-8
Original file line numberDiff line numberDiff line change
@@ -382,14 +382,15 @@ export type MenuProps<TTag extends ElementType = typeof DEFAULT_MENU_TAG> = Prop
382382
MenuPropsWeControl,
383383
{
384384
__demoMode?: boolean
385+
outsideClickScope?: string
385386
}
386387
>
387388

388389
function MenuFn<TTag extends ElementType = typeof DEFAULT_MENU_TAG>(
389390
props: MenuProps<TTag>,
390391
ref: Ref<HTMLElement>
391392
) {
392-
let { __demoMode = false, ...theirProps } = props
393+
let { __demoMode = false, outsideClickScope, ...theirProps } = props
393394
let reducerBag = useReducer(stateReducer, {
394395
__demoMode,
395396
menuState: __demoMode ? MenuStates.Open : MenuStates.Closed,
@@ -405,14 +406,19 @@ function MenuFn<TTag extends ElementType = typeof DEFAULT_MENU_TAG>(
405406

406407
// Handle outside click
407408
let outsideClickEnabled = menuState === MenuStates.Open
408-
useOutsideClick(outsideClickEnabled, [buttonElement, itemsElement], (event, target) => {
409-
dispatch({ type: ActionTypes.CloseMenu })
409+
useOutsideClick(
410+
outsideClickEnabled,
411+
[buttonElement, itemsElement],
412+
(event, target) => {
413+
dispatch({ type: ActionTypes.CloseMenu })
410414

411-
if (!isFocusableElement(target, FocusableMode.Loose)) {
412-
event.preventDefault()
413-
buttonElement?.focus()
414-
}
415-
})
415+
if (!isFocusableElement(target, FocusableMode.Loose)) {
416+
event.preventDefault()
417+
buttonElement?.focus()
418+
}
419+
},
420+
outsideClickScope
421+
)
416422

417423
let close = useEvent(() => {
418424
dispatch({ type: ActionTypes.CloseMenu })

packages/@headlessui-react/src/components/popover/popover.tsx

+14-8
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,15 @@ export type PopoverProps<TTag extends ElementType = typeof DEFAULT_POPOVER_TAG>
238238
PopoverPropsWeControl,
239239
{
240240
__demoMode?: boolean
241+
outsideClickScope?: string
241242
}
242243
>
243244

244245
function PopoverFn<TTag extends ElementType = typeof DEFAULT_POPOVER_TAG>(
245246
props: PopoverProps<TTag>,
246247
ref: Ref<HTMLElement>
247248
) {
248-
let { __demoMode = false, ...theirProps } = props
249+
let { __demoMode = false, outsideClickScope, ...theirProps } = props
249250
let internalPopoverRef = useRef<HTMLElement | null>(null)
250251
let popoverRef = useSyncRefs(
251252
ref,
@@ -375,14 +376,19 @@ function PopoverFn<TTag extends ElementType = typeof DEFAULT_POPOVER_TAG>(
375376

376377
// Handle outside click
377378
let outsideClickEnabled = popoverState === PopoverStates.Open
378-
useOutsideClick(outsideClickEnabled, root.resolveContainers, (event, target) => {
379-
dispatch({ type: ActionTypes.ClosePopover })
379+
useOutsideClick(
380+
outsideClickEnabled,
381+
root.resolveContainers,
382+
(event, target) => {
383+
dispatch({ type: ActionTypes.ClosePopover })
380384

381-
if (!isFocusableElement(target, FocusableMode.Loose)) {
382-
event.preventDefault()
383-
button?.focus()
384-
}
385-
})
385+
if (!isFocusableElement(target, FocusableMode.Loose)) {
386+
event.preventDefault()
387+
button?.focus()
388+
}
389+
},
390+
outsideClickScope
391+
)
386392

387393
let close = useEvent(
388394
(

packages/@headlessui-react/src/hooks/use-outside-click.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ const MOVE_THRESHOLD_PX = 30
2121
export function useOutsideClick(
2222
enabled: boolean,
2323
containers: ContainerInput | (() => ContainerInput),
24-
cb: (event: MouseEvent | PointerEvent | FocusEvent | TouchEvent, target: HTMLElement) => void
24+
cb: (event: MouseEvent | PointerEvent | FocusEvent | TouchEvent, target: HTMLElement) => void,
25+
topLayerScope = 'outside-click'
2526
) {
26-
let isTopLayer = useIsTopLayer(enabled, 'outside-click')
27+
let isTopLayer = useIsTopLayer(enabled, topLayerScope)
2728
let cbRef = useLatestValue(cb)
2829

2930
let handleOutsideClick = useCallback(

0 commit comments

Comments
 (0)