rgossiaux / svelte-headlessui

Unofficial Svelte port of the Headless UI component library
https://svelte-headlessui.goss.io
MIT License
1.79k stars 97 forks source link

RadioGroup and Listbox do not work properly when used together #157

Open takapi327 opened 1 year ago

takapi327 commented 1 year ago

Hi! πŸ‘‹

Firstly, thanks for your work on this project! πŸ™‚

Describe the bug RadioGroup does not work properly when using four or more Listboxes.

The problem does not occur unless three Listboxes or RadioGroups are used together.

To Reproduce

<script lang="ts">
  import { createForm } from 'felte'

  import {
    RadioGroup,
    RadioGroupOption,
    Listbox,
    ListboxButton,
    ListboxOptions,
    ListboxOption,
  } from '@rgossiaux/svelte-headlessui'

  export type Form = {
    radio: string
    select1: number
    select2: number
    select3: number
    select4: number
  }

  const radioItems = [
    { label: 'Pickup', value: 'pickup' },
    { label: 'Home delivery', value: 'home-delivery' },
    { label: 'Dine in', value: 'dine-in' },
  ]

  const select1 = [
    { id: 1, name: 'Durward Reynolds', unavailable: false },
    { id: 2, name: 'Kenton Towne', unavailable: false },
    { id: 3, name: 'Therese Wunsch', unavailable: false },
    { id: 4, name: 'Benedict Kessler', unavailable: true },
    { id: 5, name: 'Katelyn Rohan', unavailable: false },
  ]

  const select2 = [
    { id: 1, name: 'Andorra' }
  ]

  const select3 = [
    { id: 1, name: 'Singaporean' }
  ]

  const select4 = [
    { id: 1, name: 'Singaporean' }
  ]

  const { form, data, errors } = createForm<Form>({
    onSubmit: (values) => {
      console.log(values)
    }
  })
</script>

<form use:form>
  <RadioGroup bind:value={$data.radio}>
    {#each radioItems as item}
      <RadioGroupOption value={item.value} let:checked>
        <span class="
          radio-label
          before:rounded-full
          before:content-['']
          before:inline-block
          before:w-[1em]
          before:h-[1em]
          before:mr-[4px]
          before:border-4
          before:border-solid
          { checked ? 'before:border-[#c2a26b]' : 'before:border-[#d8d8d8]' }
          before:bg-white
          box-border
          align-text-top"
        >{item.label}</span>
      </RadioGroupOption>
    {/each}
  </RadioGroup>

  <Listbox bind:value={$data.select1} class="select-box">
    <ListboxButton class="select-button">{select1.find(v => v.id === $data.select1)?.name ?? 'Select'}</ListboxButton>
    <ListboxOptions class="select-options">
      {#each select1 as select (select.id)}
        <ListboxOption value={select.id} disabled={select.unavailable} class="select-option">{select.name}</ListboxOption>
      {/each}
    </ListboxOptions>
  </Listbox>

  <Listbox bind:value={$data.select2} class="select-box">
    <ListboxButton class="select-button">{select2.find(v => v.id === $data.select2)?.name ?? 'Select'}</ListboxButton>
    <ListboxOptions class="select-options">
      {#each select2 as select (select.id)}
        <ListboxOption value={select.id} disabled={select.unavailable} class="select-option">{select.name}</ListboxOption>
      {/each}
    </ListboxOptions>
  </Listbox>

  <Listbox bind:value={$data.select3} class="select-box">
    <ListboxButton class="select-button">{select3.find(v => v.id === $data.select3)?.name ?? 'Select'}</ListboxButton>
    <ListboxOptions class="select-options">
      {#each select3 as select (select.id)}
        <ListboxOption value={select.id} disabled={select.unavailable} class="select-option">{select.name}</ListboxOption>
      {/each}
    </ListboxOptions>
  </Listbox>

  <Listbox bind:value={$data.select4} class="select-box">
    <ListboxButton class="select-button">{select4.find(v => v.id === $data.select4)?.name ?? 'Select'}</ListboxButton>
    <ListboxOptions class="select-options">
      {#each select4 as select (select.id)}
        <ListboxOption value={select.id} disabled={select.unavailable} class="select-option">{select.name}</ListboxOption>
      {/each}
    </ListboxOptions>
  </Listbox>
  <button type="submit">Submit</button>
</form>

<style global lang="scss">
  @tailwind base;
  @tailwind components;
  @tailwind utilities;

  .select-box {
    position: relative;
  }

  .select-button {
    position: relative;
    border-radius: 8px;
    border: 1px solid #d8d8d8;
    padding: 4px 8px;
    width: 480px;
    height: 48px;
    text-align: left;
    cursor: pointer;
  }

  .select-button::after {
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 4.5px solid #3e3e3e;
    content: "";
    position: absolute;
    right: 9px;
    top: 21px;
    width: 0;
  }

  .select-options {
    position: absolute;
    background-color: white;
    border-radius: 4px;
    box-shadow: 0 2px 4px rgba(0,0,0,.2);
    margin-top: 4px;
    width: 480px;
    z-index: 10;
  }

  .select-option {
    padding: 16px;
    cursor:  pointer;
  }

  .select-option:hover {
    background-color: #f8f8f8;
  }
</style>

If there is a problem

https://github.com/rgossiaux/svelte-headlessui/assets/57429437/de110f42-525e-4fc3-9d4e-0cfb22c527d7

If it works correctly

https://github.com/rgossiaux/svelte-headlessui/assets/57429437/6cf37ae8-e51f-4c90-b52a-15b3779cc63a

Library version

Other version used