tailwindlabs / headlessui

Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
https://headlessui.com
MIT License
25.81k stars 1.07k forks source link

2.1.3 breaks listbox when ListboxOptions is used without anchor #3464

Closed razzeee closed 3 weeks ago

razzeee commented 3 weeks ago

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

v2.1.3

What browser are you using?

Firefox

Reproduction URL

import { Dispatch, SetStateAction } from 'react'

import {
  Listbox,
  ListboxButton,
  ListboxOption,
  ListboxOptions,
  Field,
} from '@headlessui/react'
import clsx from 'clsx'

const ListBox = <
  T extends {
    id: number
    name?: string
  }
>({
  items,
  selectedItem,
  setSelectedItem,
  onChange,
}: {
  items: T[]
  selectedItem: T
  setSelectedItem: Dispatch<SetStateAction<T>>
  onChange?: (selectedItem: T) => void
}): JSX.Element => {
  function updateSelection(newSelectedItem: T) {
    setSelectedItem(newSelectedItem)
    onChange?.(newSelectedItem)
  }

  return (
    <Field>
      <Listbox value={selectedItem} by="name" onChange={updateSelection}>
        <ListboxButton>{selectedItem.name}</ListboxButton>
        <ListboxOptions className="dark:bg-grayscale-muted dark:text-grayscale-light absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-xl bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
          {items.map((item) => (
            <ListboxOption
              key={item.id}
              className={({ focus }) =>
                clsx(
                  focus ? 'bg-primary-grapefruit-200 text-white' : '',
                  'relative cursor-default select-none py-2 pl-3 pr-9'
                )
              }
              value={item}
            >
              {({ focus, selected }) => (
                <>
                  <span
                    className={clsx(
                      selected ? 'font-semibold' : 'font-normal',
                      'block truncate'
                    )}
                  >
                    {item.name}
                  </span>

                  {selected ? (
                    <span
                      className={clsx(
                        focus ? 'text-white' : 'text-primary-grapefruit-200',
                        'absolute inset-y-0 right-0 flex items-center pr-4'
                      )}
                    ></span>
                  ) : null}
                </>
              )}
            </ListboxOption>
          ))}
        </ListboxOptions>
      </Listbox>
    </Field>
  )
}

export default ListBox

If I add an anchor to ListboxOptions it seems to start to work again, pretty unexpected for a bugfix release?

Describe your issue

I still get a listbox and can seemingly click items, but they never get selected. I would guess I end up clicking stuff above it.

Trinidus commented 3 weeks ago

Same problem here. Tried to fix it with anchors but unfortunately I am not able to fix design issues in some cases because of the auto-portal of ListboxOptions with anchor set...

RobinMalfait commented 3 weeks ago

Hey! Thanks for the bug report.

This should be fixed by #3466, and has been released in the latest release (2.1.6).

You can try it using: