Fix hanging tests when using anchor prop (#3357)
* add test that verifies unit test hang * bail when parsing the `maxHeight` results in `NaN` * playground cleanup Testing using this playground example, so cleaned it up to be more modern using newer components, transition prop and so on. * use CSS instead of JS Let's make it a CSS problem instead of a JS problem. The `round(up, <valueToRound>, <roundingInterval>)` will behave similar to a `Math.ceil()` that we had in the JS implementation. See: https://developer.mozilla.org/en-US/docs/Web/CSS/round * Remove CSS solution for now I want to re-enable this in the future, but unfortunately for now we can't use it because Chrome only introduced support for this in the last 2 months. This reverts commit daac60d45ec3f02b324d0d8b18078a995e885733. * update changelog
This commit is contained in:
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Fix prematurely added anchoring styles on `ListboxOptions` ([#3337](https://github.com/tailwindlabs/headlessui/pull/3337))
|
||||
- Ensure `unmount` on `Dialog` works in combination with the `transition` prop on `DialogBackdrop` and `DialogPanel` components ([#3352](https://github.com/tailwindlabs/headlessui/pull/3352))
|
||||
- Fix crash in `Combobox` component when in `virtual` mode when options are empty ([#3356](https://github.com/tailwindlabs/headlessui/pull/3356))
|
||||
- Fix hanging tests when using `anchor` prop ([#3357](https://github.com/tailwindlabs/headlessui/pull/3357))
|
||||
|
||||
## [2.1.1] - 2024-06-26
|
||||
|
||||
|
||||
@@ -804,6 +804,26 @@ describe('Rendering', () => {
|
||||
assertActiveElement(getByText('restorable'))
|
||||
})
|
||||
)
|
||||
|
||||
it(
|
||||
'should be possible to use the `anchor` prop on the `PopoverPanel`',
|
||||
suppressConsoleLogs(async () => {
|
||||
render(
|
||||
<Popover>
|
||||
<PopoverButton>Trigger</PopoverButton>
|
||||
<PopoverPanel anchor="bottom">Panel open</PopoverPanel>
|
||||
</Popover>
|
||||
)
|
||||
|
||||
assertPopoverButton({ state: PopoverState.InvisibleUnmounted })
|
||||
assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
|
||||
|
||||
await click(getPopoverButton())
|
||||
|
||||
assertPopoverButton({ state: PopoverState.Visible })
|
||||
assertPopoverPanel({ state: PopoverState.Visible })
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
describe('Multiple `Popover.Button` warnings', () => {
|
||||
|
||||
@@ -375,9 +375,16 @@ function useFixScrollingPixel(element: HTMLElement | null) {
|
||||
if (!element) return
|
||||
|
||||
let observer = new MutationObserver(() => {
|
||||
let maxHeight = element.style.maxHeight
|
||||
if (parseFloat(maxHeight) !== parseInt(maxHeight)) {
|
||||
element.style.maxHeight = `${Math.ceil(parseFloat(maxHeight))}px`
|
||||
let maxHeight = window.getComputedStyle(element).maxHeight
|
||||
|
||||
let maxHeightFloat = parseFloat(maxHeight)
|
||||
if (isNaN(maxHeightFloat)) return
|
||||
|
||||
let maxHeightInt = parseInt(maxHeight)
|
||||
if (isNaN(maxHeightInt)) return
|
||||
|
||||
if (maxHeightFloat !== maxHeightInt) {
|
||||
element.style.maxHeight = `${Math.ceil(maxHeightFloat)}px`
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Listbox, Transition } from '@headlessui/react'
|
||||
import { Label, Listbox, ListboxButton, ListboxOption, ListboxOptions } from '@headlessui/react'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
let people = [
|
||||
@@ -26,20 +26,12 @@ export default function Home() {
|
||||
<div className="flex h-full w-screen justify-center bg-gray-50 p-12">
|
||||
<div className="mx-auto w-full max-w-xs">
|
||||
<div className="space-y-1">
|
||||
<Listbox
|
||||
value={active}
|
||||
onChange={(value) => {
|
||||
console.log('value:', value)
|
||||
setActivePerson(value)
|
||||
}}
|
||||
>
|
||||
<Listbox.Label className="block text-sm font-medium leading-5 text-gray-700">
|
||||
Assigned to
|
||||
</Listbox.Label>
|
||||
<Listbox value={active} onChange={setActivePerson}>
|
||||
<Label className="block text-sm font-medium leading-5 text-gray-700">Assigned to</Label>
|
||||
|
||||
<div className="relative">
|
||||
<span className="inline-block w-full rounded-md shadow-sm">
|
||||
<Listbox.Button className="focus:shadow-outline-blue relative w-full cursor-default rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 text-left transition duration-150 ease-in-out focus:border-blue-300 focus:outline-none sm:text-sm sm:leading-5">
|
||||
<ListboxButton className="relative w-full cursor-default rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 text-left transition duration-150 ease-in-out sm:text-sm sm:leading-5">
|
||||
<span className="block truncate">{active}</span>
|
||||
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
||||
<svg
|
||||
@@ -56,42 +48,35 @@ export default function Home() {
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</Listbox.Button>
|
||||
</ListboxButton>
|
||||
</span>
|
||||
|
||||
<Transition
|
||||
enter="transition duration-500 ease-out"
|
||||
enterFrom="transform scale-95 opacity-0"
|
||||
enterTo="transform scale-100 opacity-100"
|
||||
leave="transition duration-500 ease-out"
|
||||
leaveFrom="transform scale-100 opacity-100"
|
||||
leaveTo="transform scale-95 opacity-0"
|
||||
<ListboxOptions
|
||||
anchor="bottom"
|
||||
transition
|
||||
className="w-[var(--button-width)] overflow-auto rounded-md border border-gray-300 bg-white py-1 text-base leading-6 shadow-lg transition duration-200 ease-out [--anchor-gap:theme(spacing.1)] [--anchor-max-height:theme(spacing.60)] focus:outline-none data-[closed]:scale-95 data-[closed]:opacity-0 sm:text-sm sm:leading-5"
|
||||
>
|
||||
<div className="absolute mt-1 w-full rounded-md bg-white shadow-lg">
|
||||
<Listbox.Options className="shadow-xs max-h-60 overflow-auto rounded-md py-1 text-base leading-6 focus:outline-none sm:text-sm sm:leading-5">
|
||||
{people.map((name) => (
|
||||
<Listbox.Option
|
||||
key={name}
|
||||
value={name}
|
||||
className="group relative cursor-default select-none py-2 pl-3 pr-9 text-gray-900 focus:outline-none data-[active]:bg-indigo-600 data-[active]:text-white"
|
||||
>
|
||||
<span className="block truncate font-normal group-data-[selected]:font-semibold">
|
||||
{name}
|
||||
</span>
|
||||
<span className="absolute inset-y-0 right-0 hidden items-center pr-4 text-indigo-600 group-data-[selected]:flex group-data-[active]:text-white">
|
||||
<svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</Listbox.Option>
|
||||
))}
|
||||
</Listbox.Options>
|
||||
</div>
|
||||
</Transition>
|
||||
{people.map((name) => (
|
||||
<ListboxOption
|
||||
key={name}
|
||||
value={name}
|
||||
className="group relative cursor-default select-none py-2 pl-3 pr-9 text-gray-900 focus:outline-none data-[active]:bg-indigo-600 data-[active]:text-white"
|
||||
>
|
||||
<span className="block truncate font-normal group-data-[selected]:font-semibold">
|
||||
{name}
|
||||
</span>
|
||||
<span className="absolute inset-y-0 right-0 hidden items-center pr-4 text-indigo-600 group-data-[selected]:flex group-data-[active]:text-white">
|
||||
<svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</ListboxOption>
|
||||
))}
|
||||
</ListboxOptions>
|
||||
</div>
|
||||
</Listbox>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user