saadeghi / daisyui

๐ŸŒผ ๐ŸŒผ ๐ŸŒผ ๐ŸŒผ ๐ŸŒผ โ€ƒThe most popular, free and open-source Tailwind CSS component library
https://daisyui.com
MIT License
34.2k stars 1.31k forks source link

bug: Navbar dropdown doesn't close on the option click #2880

Closed Aravin closed 8 months ago

Aravin commented 9 months ago

What version of daisyUI are you using?

4.7.0

Which browsers are you seeing the problem on?

All browsers

Reproduction URL

https://www.exaful.com/

Describe your issue

image

The dropdown is getting closed after choosing the option.

github-actions[bot] commented 9 months ago

Thank you @Aravin for reporting issues. It helps daisyUI a lot ๐Ÿ’š
I'll be working on issues one by one. I will help with this one as soon as a I find a solution.
In the meantime providing more details and reproduction links would be helpful.

saadeghi commented 8 months ago

When the site is an SPA, clicking on links doesn't actually change the page. Instead your JS framework replaces the content with the new content. So It is expected for the dropdown to stay open because it is still focused.

To close it, you can remove the focus from it using JS after the link is clicked.
Let me know if you have any questions

i0FFLINE commented 8 months ago

To close it, you can remove the focus from it using JS after the link is clicked. Let me know if you have any questions

any idea how to?

Aravin commented 8 months ago

I haven't done it yet. We have to use router/navigation and see the change in pathname accordingly modify the state of the navbar

i0FFLINE commented 8 months ago

I am stuck on the following:

Aravin commented 8 months ago

share the actual code or code sample.

i0FFLINE commented 8 months ago
<template>
    <div class="navbar py-1 px-2 bg-gradient-to-r from-slate-900 to-slate-600 text-light shadow-lg dark:shadow-none">
        <div class="flex-1">
            <a href="#" class="btn pl-1.5 btn-ghost text-xl">
                <Logo class="h-9 mr-3" /* SVG inside */ />
                {{ APP_NAME }}
            </a>
        </div>
        <div class="flex-none">
            <ThemeToggle class="h-full" /* SWAP inside */ />
            <!-- Mobile version navbar-hamberger -->
            <ul class="menu menu-horizontal pl-1 pr-0.5 gap-5 md:hidden">
                <li>
                    <div class="dropdown dropdown-bottom dropdown-end focus:outline-none active:outline-none p-0">
                        <div role="button" tabindex="0">
                            <svg>
                                <!-- cut -->
                            </svg>
                        </div>
                        <ul class="dropdown-content z-[1] menu bg-slate-700">
                            <li>
                                <details>
                                    <summary>{{ SELECTED_LOCALE }}</summary>
                                    <ul class="dropdown-content z-[1] menu bg-slate-700">
                                        <li v-for="(sli, slk) in SUPPORT_LOCALE_NAMES" :key="slk">
                                            <a href="#" onclick="document.activeElement.blur()">{{ sli }}</a>
                                        </li>
                                    </ul>
                                </details>
                            </li>
                            <li><a href="#" onclick="document.activeElement.blur()">Link1</a></li>
                            <li><a href="#" onclick="document.activeElement.blur()">Link2</a></li>
                            <li><a href="#" onclick="document.activeElement.blur()">Settings</a></li>
                            <li><a href="#" onclick="document.activeElement.blur()">Logout</a></li>
                        </ul>
                    </div>
                </li>
            </ul>
        </div>
    </div>
</template>

...something lke that

xl0 commented 3 months ago

@saadeghi Any chance you could document the best way to do this? My solution (Svelte), but it took a bit of time to figure it out:

<script lang="ts">
    import { cn } from '$lib/utils';
    import { Trash2 } from 'lucide-svelte';

    export let deleteAction: () => Promise<void> | void;
    export let size = 15;
    export let btnClass = '';
    let className = '';
    export { className as class };

    export let disabled = false;
    let deleting = false;
    let button: HTMLButtonElement;
</script>

<div class={cn('dropdown', className)}>
    <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
    <div tabindex={0} class={cn(disabled ? 'btn-disabled' : '', btnClass)}>
        {#if deleting}
            <div class="loading loading-sm" />
        {:else}
            <Trash2 {size} />
        {/if}
    </div>

    <ul class="dropdown-content w-fit p-2">
        <li>
            <button
                bind:this={button}
                class="btn btn-sm text-nowrap rounded-md"
                on:click={async () => {
                    disabled = true;
                    deleting = true;
                    button.blur();
                    await deleteAction();
                    disabled = false;
                    deleting = false;
                }}>Yes, delete!</button>
        </li>
    </ul>
</div>
saadeghi commented 3 months ago

@xl0

Any chance you could document the best way to do this?

I wish, but there's no best way. It's different for each framework.

There's a newly available HTML popover API which will fix this issue hopefully. We're expecting it to be the standard way to handle dropdowns in the next version of daisyUI.