CaptainCodeman / svelte-headlessui

HeadlessUI components for Svelte
https://captaincodeman.github.io/svelte-headlessui/
MIT License
564 stars 26 forks source link

Multiple Disclosure elements on the page. #84

Closed sideshot closed 10 months ago

sideshot commented 10 months ago

I'm running into a problem trying to put multiple disclosures on the same page.

For instance, I have multiple filter blocks. Adding them in a loop worked, but the 'store' value was unreachable. Can you recommend a solution?

I managed to create this to make it work.

    filters = filters.map((filter) => {
        const disclosure = createDisclosure({ label: filter.name });
        let expanded = false;

        disclosure.subscribe((value) => {
            expanded = value.expanded;
        });

        return { ...filter, disclosure, expanded };
    });
        {#each filters as section}
            <div class="border-t border-gray-200 px-4 py-6">
                <h3 class="-mx-2 -my-3 flow-root">
                    <button
                        use:section.disclosure.button
                        on:click={section.disclosure.toggle}
                        class="flex w-full items-center justify-between bg-white px-2 py-3 text-gray-400 hover:text-gray-500"
                    >
                        <span class="font-medium text-gray-900">{section.name}</span>
                        <span class="ml-6 flex items-center">
                            {#if !section.expanded}
                                <Plus class="h-5 w-5" aria-hidden="true" />
                            {:else}
                                <Minus class="h-5 w-5" aria-hidden="true" />
                            {/if}
                        </span>
                    </button>
                </h3>
                {#if section.expanded}
                    <div use:section.disclosure.panel class="pt-6">
                        {#each section.options as option, optionIdx}
                            <div class="flex items-center">
                                <input
                                    id={`filter-mobile-${section.id}-${optionIdx}`}
                                    name={`${section.id}[]`}
                                    value={option.value}
                                    type="checkbox"
                                    checked={option.checked}
                                    class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
                                />
                                <label
                                    for={`filter-mobile-${section.id}-${optionIdx}`}
                                    class="ml-3 min-w-0 flex-1 text-gray-500">{option.label}</label
                                >
                            </div>
                        {/each}
                    </div>
                {/if}
            </div>
        {/each}

demo data

const filters = [
        {
            id: 'color',
            name: 'Color',
            options: [
                { value: 'white', label: 'White', checked: false },
                { value: 'beige', label: 'Beige', checked: false },
                { value: 'blue', label: 'Blue', checked: true },
                { value: 'brown', label: 'Brown', checked: false },
                { value: 'green', label: 'Green', checked: false },
                { value: 'purple', label: 'Purple', checked: false }
            ]
        },
        {
            id: 'category',
            name: 'Category',
            options: [
                { value: 'new-arrivals', label: 'New Arrivals', checked: false },
                { value: 'sale', label: 'Sale', checked: false },
                { value: 'travel', label: 'Travel', checked: true },
                { value: 'organization', label: 'Organization', checked: false },
                { value: 'accessories', label: 'Accessories', checked: false }
            ]
        },
        {
            id: 'size',
            name: 'Size',
            options: [
                { value: '2l', label: '2L', checked: false },
                { value: '6l', label: '6L', checked: false },
                { value: '12l', label: '12L', checked: false },
                { value: '18l', label: '18L', checked: false },
                { value: '20l', label: '20L', checked: false },
                { value: '40l', label: '40L', checked: true }
            ]
        }
    ];
CaptainCodeman commented 10 months ago

I always like to creating a child component for each item in any loop -in my experience it usually results in simpler code rather than trying to do too much in the containing component.

sideshot commented 10 months ago

do you happen to have an example of how you would do that in a loop to create the child components, and then use the child comp .expanded feature?

CaptainCodeman commented 10 months ago

You'll move most of the code to a child component which will create the disclosure for each item passed in then just have:

{#each filters as section}
  <Section {section} />
{/each}
sideshot commented 10 months ago

{smh}

Perfect! Thanks!