ReactHustle

How to close DaisyUI Dropdown with one click

Jasser Mark Arioste

Jasser Mark Arioste

How to close DaisyUI Dropdown with one click

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.   

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

Credits

Image by David Mark from Pixabay

Share this post!

Related Posts