diff --git a/packages/@headlessui-react/src/hooks/use-root-containers.tsx b/packages/@headlessui-react/src/hooks/use-root-containers.tsx index c2a598ef84..34bdaa2bfb 100644 --- a/packages/@headlessui-react/src/hooks/use-root-containers.tsx +++ b/packages/@headlessui-react/src/hooks/use-root-containers.tsx @@ -43,6 +43,7 @@ export function useRootContainers({ if (!(container instanceof HTMLElement)) continue // Skip non-HTMLElements if (container.id === 'headlessui-portal-root') continue // Skip the Headless UI portal root if (container.contains(mainTreeNodeRef.current)) continue // Skip if it is the main app + if (container.contains((mainTreeNodeRef.current?.getRootNode() as ShadowRoot)?.host)) continue // Skip if it is the main app (and the component is inside a shadow root) if (containers.some((defaultContainer) => container.contains(defaultContainer))) continue // Skip if the current container is part of a container we've already seen (e.g.: default container / portal) containers.push(container) diff --git a/packages/playground-react/pages/combobox/combobox-virtual-with-empty-states.tsx b/packages/playground-react/pages/combobox/combobox-virtual-with-empty-states.tsx index e36c75d32d..baaccaedfe 100644 --- a/packages/playground-react/pages/combobox/combobox-virtual-with-empty-states.tsx +++ b/packages/playground-react/pages/combobox/combobox-virtual-with-empty-states.tsx @@ -3,7 +3,6 @@ import { useRef, useState } from 'react' import { classNames } from '../../utils/class-names' import { Button } from '../../components/button' -import { flushSync } from 'react-dom' type Option = { name: string @@ -13,32 +12,32 @@ type Option = { export default function Home() { let [list, setList] = useState(() => [ - {name: 'Alice', disabled: false}, - {name: 'Bob', disabled: false}, - {name: 'Charlie', disabled: false}, - {name: 'David', disabled: false}, - {name: 'Eve', disabled: false}, - {name: 'Fred', disabled: false}, - {name: 'George', disabled: false}, - {name: 'Helen', disabled: false}, - {name: 'Iris', disabled: false}, - {name: 'John', disabled: false}, - {name: 'Kate', disabled: false}, - {name: 'Linda', disabled: false}, - {name: 'Michael', disabled: false}, - {name: 'Nancy', disabled: false}, - {name: 'Oscar', disabled: true}, - {name: 'Peter', disabled: false}, - {name: 'Quentin', disabled: false}, - {name: 'Robert', disabled: false}, - {name: 'Sarah', disabled: false}, - {name: 'Thomas', disabled: false}, - {name: 'Ursula', disabled: false}, - {name: 'Victor', disabled: false}, - {name: 'Wendy', disabled: false}, - {name: 'Xavier', disabled: false}, - {name: 'Yvonne', disabled: false}, - {name: 'Zachary', disabled: false}, + { name: 'Alice', disabled: false }, + { name: 'Bob', disabled: false }, + { name: 'Charlie', disabled: false }, + { name: 'David', disabled: false }, + { name: 'Eve', disabled: false }, + { name: 'Fred', disabled: false }, + { name: 'George', disabled: false }, + { name: 'Helen', disabled: false }, + { name: 'Iris', disabled: false }, + { name: 'John', disabled: false }, + { name: 'Kate', disabled: false }, + { name: 'Linda', disabled: false }, + { name: 'Michael', disabled: false }, + { name: 'Nancy', disabled: false }, + { name: 'Oscar', disabled: true }, + { name: 'Peter', disabled: false }, + { name: 'Quentin', disabled: false }, + { name: 'Robert', disabled: false }, + { name: 'Sarah', disabled: false }, + { name: 'Thomas', disabled: false }, + { name: 'Ursula', disabled: false }, + { name: 'Victor', disabled: false }, + { name: 'Wendy', disabled: false }, + { name: 'Xavier', disabled: false }, + { name: 'Yvonne', disabled: false }, + { name: 'Zachary', disabled: false }, ]) let emptyOption = useRef({ name: 'No results', disabled: true, empty: true }) @@ -52,10 +51,9 @@ export default function Home() { ? list : list.filter((item) => item.name.toLowerCase().includes(query.toLowerCase())) - return (
-
Selected person: {selectedPerson?.name ?? "N/A"}
+
Selected person: {selectedPerson?.name ?? 'N/A'}
0 ? filtered : [emptyOption.current], @@ -68,12 +66,11 @@ export default function Home() { setQuery('') }} as="div" - // Don't do this lol — it's not supported // It's just so we can tab to the "Add" button for the demo // The combobox doesn't actually support this behavior onKeyDownCapture={(event: KeyboardEvent) => { - let addButton = document.querySelector('#add_person') + let addButton = document.querySelector('#add_person') as HTMLElement | null if (event.key === 'Tab' && addButton && filtered.length === 0) { event.preventDefault() setTimeout(() => addButton.focus(), 0) @@ -116,69 +113,76 @@ export default function Home() { // It comes with some caveats: // like the option callback being called with a null option (which is probably a bug) static={filtered.length === 0} - ref={optionsRef} className={classNames( - "shadow-xs max-h-60 rounded-md py-1 text-base leading-6 focus:outline-none sm:text-sm sm:leading-5", + 'shadow-xs max-h-60 rounded-md py-1 text-base leading-6 focus:outline-none sm:text-sm sm:leading-5', filtered.length === 0 ? 'overflow-hidden' : 'overflow-auto' )} > - { - ({ option }: { option: Option }) => { - if (!option || option.empty) { - return ( - -
-
- - - -
-
-

No people found

- -
-
-
- ) - } - + {({ option }: { option: Option }) => { + if (!option || option.empty) { return ( { - return classNames( - 'relative w-full cursor-default select-none py-2 pl-3 pr-9 focus:outline-none', - active ? 'bg-indigo-600 text-white' : 'text-gray-900' - ) - }} + disabled + // Note: Do NOT use `null` for the `value` + value={option ?? emptyOption.current} + className="relative w-full cursor-default select-none px-3 py-2 text-center focus:outline-none" > - - {option.name} - +
+
+ + + +
+
+

+ No people found +

+ +
+
) } - } + + return ( + { + return classNames( + 'relative w-full cursor-default select-none py-2 pl-3 pr-9 focus:outline-none', + active ? 'bg-indigo-600 text-white' : 'text-gray-900' + ) + }} + > + {option.name} + + ) + }}
diff --git a/packages/playground-vue/src/components/combobox/combobox-virtual-with-empty-states.vue b/packages/playground-vue/src/components/combobox/combobox-virtual-with-empty-states.vue index bc032da5af..67cc85b81a 100644 --- a/packages/playground-vue/src/components/combobox/combobox-virtual-with-empty-states.vue +++ b/packages/playground-vue/src/components/combobox/combobox-virtual-with-empty-states.vue @@ -1,6 +1,13 @@