tailwindlabs / tailwindui-issues

Bug fixes and feature request tracking for Tailwind UI.
233 stars 4 forks source link

Catalyst Alert Modal Does Not Automatically Open on Page Load #1616

Open iamvinny opened 1 month ago

iamvinny commented 1 month ago

What component (if applicable)

Describe the bug The modal does not automatically open when the page loads, even though the useState is set to true. The modal works correctly without Catalyst styling when using Dialog from headlessui.

To Reproduce Steps to reproduce the behavior:

  1. Copy the example code for Catalyst UI Alert and create a new component
  2. Ensure the component is rendered with isOpen state set to true.
  3. Observe that the modal does not open automatically on page load.
  4. Compare with the same logic implemented using Dialog from headlessui where the modal opens as expected.

Expected behavior The modal should automatically open when the page loads if the useState is set to true.

Browser/Device (if applicable)

Additional context The issue occurs specifically when using the Catalyst Alert component. The same logic works correctly when using the Dialog component from headlessui, indicating a potential issue with how the open prop is being handled in Catalyst's Alert component.

Catalyst example

"use client";

import { Alert, AlertActions, AlertDescription, AlertTitle } from '@/app/components/catalyst/alert'
import { Button } from '@/app/components/catalyst/button'
import { useState } from 'react'

export default function Announcement() {
    let [isOpen, setIsOpen] = useState(true)

    return (
        <>
            <Alert open={isOpen} onClose={setIsOpen}>
            <AlertTitle>Are you sure you want to refund this payment?</AlertTitle>
                <AlertDescription>
                    The refund will be reflected in the customer’s bank account 2 to 3 business days after processing.
                </AlertDescription>
                <AlertActions>
                    <Button plain onClick={() => setIsOpen(false)}>
                        Cancel
                    </Button>
                    <Button onClick={() => setIsOpen(false)}>Refund</Button>
                </AlertActions>
            </Alert>
        </>
    )
}

Pure HeadlessUI Example:

"use client";

import { useState } from 'react'
import { Dialog } from '@headlessui/react'

export default function Announcement() {
  let [isOpen, setIsOpen] = useState(true)

  return (
    <Dialog open={isOpen} onClose={() => setIsOpen(false)}>
      <Dialog.Panel>
        <Dialog.Title>Deactivate account</Dialog.Title>
        <Dialog.Description>
          This will permanently deactivate your account
        </Dialog.Description>

        <p>
          Are you sure you want to deactivate your account? All of your data
          will be permanently removed. This action cannot be undone.
        </p>

        <button onClick={() => setIsOpen(false)}>Deactivate</button>
        <button onClick={() => setIsOpen(false)}>Cancel</button>
      </Dialog.Panel>
    </Dialog>
  )
}
reinink commented 1 month ago

Hey! Happy to try and help out here.

Would you be able to put together a minimal reproduction of this as a Git repo for me?

I only ask because I've been trying to reproduce this issue, but setting the open state to true on load is working for me in both the Dialog and Alert components, so I'm not sure what's up here.

iamvinny commented 1 month ago

Hey! Happy to try and help out here.

Would you be able to put together a minimal reproduction of this as a Git repo for me?

I only ask because I've been trying to reproduce this issue, but setting the open state to true on load is working for me in both the Dialog and Alert components, so I'm not sure what's up here.

Thanks for your prompt response to the issue!

After some time debugging, I managed to create a minimal Git repository that reproduces the issue. The problem appears to occur specifically when the Catalyst sidebar is present, combined with a Loading state or any condition that delays the full DOM load in the application-layout component.

In the example below, I'm returning a <Loading /> component while waiting for the session data to be fetched. oddly enough, this causes the modal to not display automatically, even though the modal works perfectly when manually triggered by clicking a button.

export function ApplicationLayout({
    events,
    children,
}: {
    events: Awaited<ReturnType<typeof getEvents>>
    children: React.ReactNode
}) {
     let pathname = usePathname()
     const { logout, user } = useAuth({ middleware: 'auth' } as any)
     if (!user) { return 'Loading...' }

     return (
        <SidebarLayout
        ...

For context, I'm using the hook available at laravel/breeze-next project for session management. However, I was able to replicate the issue simply by adding a delay in the ApplicationLayout file to simulate the session fetching process.

It seems that any session management approach that introduces a loading screen before rendering the actual content could trigger this issue. The strange part is that the modal component is present in the DOM (visible in the inspector), but it doesn’t appear on the screen until manually triggered.

Below is the Github repo I put together: https://github.com/iamvinny/catalyst-modal-bug

Let me know if you need any more details or if there's anything else I can do to assist!