Shadcn ui Alert dialog closes automatically when clicking the trigger from dropdown menu

4 min read 04-10-2024
Shadcn ui Alert dialog closes automatically when clicking the trigger from dropdown menu


Shadcn UI: Alert Dialogs Disappear When Clicking Dropdown Menu Trigger

Problem:

You're using Shadcn UI's Alert dialog component. You've integrated it into your application, but you've noticed a frustrating bug: when you click on the button or link that triggers the dialog, the dialog itself disappears before you can even interact with it. This often happens when the trigger is embedded within a dropdown menu.

Scenario:

Imagine you're building a user profile page. You have a dropdown menu with options like "Edit Profile," "Change Password," and "Delete Account." When the user clicks "Delete Account," you want to display an alert dialog confirming their action. But, instead of the dialog appearing, it instantly disappears.

Code Example:

<div class="dropdown">
  <button type="button" data-dropdown-toggle="my-dropdown"
    class="inline-flex items-center text-sm font-medium text-gray-500 hover:text-gray-900 focus:outline-none focus:ring-0"
    data-dropdown-placement="bottom-start">
    Actions
    <svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor"
      viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
        d="M19 9l-7 7-7-7"></path>
    </svg>
  </button>

  <div id="my-dropdown"
    class="hidden z-10 absolute top-full start-0 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none"
    data-dropdown-overlay="true">
    <ul class="py-2" aria-labelledby="dropdown-button">
      <li>
        <button data-modal-toggle="deleteAccountModal"
          class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
          Delete Account
        </button>
      </li>
    </ul>
  </div>

  <div id="deleteAccountModal" tabindex="-1"
    class="fixed top-0 left-0 right-0 z-50 hidden w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-modal md:h-full">
    <div class="relative w-full max-w-md h-full md:h-auto">
      <div class="relative bg-white rounded-lg shadow">
        <div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t">
          <h3 class="text-xl font-semibold text-gray-900">
            Delete Account
          </h3>
          <button type="button" data-modal-hide="deleteAccountModal"
            class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center"
            data-modal-toggle="deleteAccountModal">
            <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"
              xmlns="http://www.w3.org/2000/svg">
              <path d="M6 2l2 4h8L14 2H6zm2 10a2 2 0 11-4 0 2 2 0 014 0zm8-2a2 2 0 11-4 0 2 2 0 014 0z" />
            </svg>
          </button>
        </div>
        <div class="p-6 space-y-6">
          <p class="text-base leading-relaxed text-gray-500">
            Are you sure you want to delete your account? This action
            cannot be undone.
          </p>
        </div>
        <div class="flex items-center p-6 space-x-2 border-t rounded-b">
          <button data-modal-hide="deleteAccountModal"
            class="text-white bg-gray-700 hover:bg-gray-800 focus:ring-4 focus:outline-none focus:ring-gray-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center">
            Cancel
          </button>
          <button data-modal-hide="deleteAccountModal"
            class="text-white bg-red-500 hover:bg-red-600 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center">
            Delete
          </button>
        </div>
      </div>
    </div>
  </div>
</div>

Analysis and Solution:

The issue stems from the way Shadcn UI's dropdown and modal components handle events. When you click on the "Delete Account" button within the dropdown, the dropdown menu itself closes due to its default behavior. This closure triggers a re-render of the page, which effectively closes the modal before it has a chance to fully appear.

Solution:

To prevent this, you can employ a few strategies:

  1. Prevent Dropdown Closure: Modify the dropdown behavior to prevent it from closing automatically when the "Delete Account" button is clicked. This might involve adding an event listener to the dropdown button that prevents the default dropdown closure action when the button is clicked.

  2. Direct Modal Trigger: Instead of triggering the modal through the dropdown button, consider using a separate button specifically for triggering the modal. This button could be placed directly within the modal container, bypassing the dropdown's closure behavior entirely.

  3. Modal Trigger Delay: Introduce a small delay before the modal appears. This gives the dropdown time to close before the modal starts rendering, avoiding the timing conflict.

  4. Manual Modal Control: Instead of relying on the data-modal-toggle attribute, you can manually manage the modal's display using JavaScript. You can delay the modal's appearance using a setTimeout function.

Example: Manual Modal Control with Delay

document.addEventListener('DOMContentLoaded', function() {
  const deleteAccountButton = document.querySelector('#deleteAccountButton');
  const deleteAccountModal = document.getElementById('deleteAccountModal');

  deleteAccountButton.addEventListener('click', () => {
    setTimeout(() => {
      deleteAccountModal.classList.remove('hidden'); 
    }, 100); // Delay the modal appearance for 100 milliseconds
  });
});

Additional Tips:

  • Use console.log statements to pinpoint the exact point in your code where the dropdown is closing, which will help you understand the flow of events and target your solution accordingly.
  • Consider the user experience. While you can prevent the modal from closing prematurely, it might be helpful to make the modal trigger more prominent, perhaps with a separate button that is easily identifiable.

Conclusion:

Understanding the interactions between Shadcn UI's dropdown and modal components is crucial for solving this common issue. By preventing the dropdown from closing prematurely, or by triggering the modal directly, you can ensure the alert dialogs appear as intended and provide a smoother user experience.