How to close DaisyUI Dropdown with one click
Jasser Mark Arioste
Daisy UI has a great dropdown component but for some reason it doesn't close when we click a menu item inside the dropdown. Although this is by design, it could be frustrating if not handled properly.
Today I will share with you 2 ways on how to close DaisyUI dropdown with one click. First with javascript using DOM api and next is using React.
In this guide, I assume you've already set up your project with daisy UI so we'll skip that part.
Why does DaisyUI not close the dropdown when clicked? #
The reason for this is because the elements inside the dropdown content are focused and DaisyUI shows the dropdown content when there's focus inside it. Below is the CSS code causing the problem.
.dropdown.dropdown-open .dropdown-content, .dropdown.dropdown-hover:hover .dropdown-content, .dropdown:not(.dropdown-hover):focus .dropdown-content, .dropdown:not(.dropdown-hover):focus-within .dropdown-content { visibility: visible; opacity: 1; }
12345678
Closing DaisyUI dropdown using .blur()
method
#
Now that we know the problem it's we can easily fix this by not focusing the dropdown
component. First let's create a dropdown component with a few menu items.
//Dropdown.js import React from 'react'; const Dropdown = () => { const handleClick = () => { const elem = document.activeElement; if(elem){ elem?.blur(); } }; return ( <> <div className="dropdown"> <label tabIndex={0} className="btn m-1"> Click </label> <ul tabIndex={0} className="dropdown-content menu p-2 shadow bg-base-200 rounded-box w-52" > <li onClick={handleClick}> <a>Item 1</a> </li> <li onClick={handleClick}> <a>Item 2</a> </li> </ul> </div> </> ); }; export default Dropdown;
1234567891011121314151617181920212223242526272829303132333435
In the above code, Whenever a menu item is clicked we get the document.activeElement
and use its blur
method to remove focus from the dropdown-content
.
Here's a link to the demo: https://stackblitz.com/edit/nextjs-daisy-ui-v3pfmf?file=components/Dropdown.js
That's one way to do it, and I also think it's the best and simplest way. Now if you want to completely control the state using react, I will also show you in the second example below
Closing DaisyUI Dropdown by toggling classes using state in React #
In short, we'll be adding the hidden class from tailwind if the dropdown is in a closed state and removing it on open state. The downside with this approach is there is a bit more code to implement it since we also need to take into consideration when clicking outside the component.
First we install two dependencies to help us out.
yarn add use-hooks classnames
1
use-hooks
is used for handling when clicking outside the dropdown and classnames
is just an awesome tool for toggling utility classes in tailwind.
Below is the code for the react component with comments:
import React, { useState, useRef } from 'react'; // import classnames and useOnClickOutside import { useOnClickOutside } from 'use-hooks'; import cn from 'classnames'; const DropdownReact = () => { // add a state to toggle the dropdown const [open, setOpen] = useState(); //close the dropdown when clicking outside the referenced element const ref = useRef(); useOnClickOutside(ref, () => setOpen(false)); //onclick handler when clicking a menu item const handleClick = () => { setOpen(false); }; return ( <> <div // add toggle dropdown-open className={cn({ dropdown: true, 'dropdown-open': open, })} // add reference to the dropdown element ref={ref} > <label tabIndex={0} className="btn m-1" // toggle open when the button is clicked. onClick={() => setOpen((prev) => !prev)} > Click </label> <ul tabIndex={0} // add hidden class when the dropdown is not open className={cn({ 'dropdown-content menu p-2 shadow bg-base-200 rounded-box w-52': true, hidden: !open, })} > <li onClick={handleClick}> <a>Item 1</a> </li> <li onClick={handleClick}> <a>Item 2</a> </li> </ul> </div> </> ); }; export default DropdownReact;
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
Here's a link to the demo: https://stackblitz.com/edit/nextjs-daisy-ui-v3pfmf?file=components/DropdownReact.js
Credits
Image by David Mark from Pixabay