lepikhinb / momentum-modal

MIT License
442 stars 26 forks source link

[Help] Can't get the modal to display #41

Closed grantholle closed 1 year ago

grantholle commented 1 year ago

I'm using vite, here is my setup:

createApp({ render: () => h(App, props) })
  .use(modal, {
    resolve: (name) => {
      console.log(name)
      return resolvePageComponent(name, import.meta.glob('./Pages/**/*.vue'))
    },
  })

I'm returning an Inertia::modal() and when inspecting the props, the modal object is correct with my props and the component, the base route is displaying correctly, but no modal is launching.

I've put a console log in the resolve function, but I never get any logs. Any idea why the modal isn't showing?

jeffreyvanhees commented 1 year ago

Did you put the<Modal />-component somewhere in your layout?

<script setup>
import { Modal } from 'momentum-modal'
</script>

<template>
    <div>
        <!-- layout -->
        <Modal />
    </div>
</template>
grantholle commented 1 year ago

Yes, this is my component I use for modals:

<template>
  <TransitionRoot appear as="template" :show="show" @afterLeave="redirect">
    <Dialog as="div" class="fixed inset-0 overflow-y-auto z-40" @close="close" :initial-focus="initialFocus">
      <div class="flex items-start justify-center min-h-screen pt-12 px-4 pb-20 text-center">
        <TransitionChild
          as="template"
          enter-active="duration-300 ease-out"
          enter-from="opacity-0"
          enter-to="opacity-100"
          leave-active="duration-200 ease-in"
          leave-from="opacity-100"
          leave-to="opacity-0"
        >
          <div @click.prevent.stop="" class="fixed inset-0 transition-opacity backdrop-blur-sm" aria-hidden="true">
            <div class="absolute inset-0 bg-gray-800 opacity-75"></div>
          </div>
        </TransitionChild>

        <TransitionChild
          as="template"
          enter-active="ease-out duration-300"
          enter-from="opacity-0 -translate-y-5"
          enter-to="opacity-100 translate-y-0"
          leave-active="ease-in duration-200"
          leave-from="opacity-100 translate-y-0"
          leave-to="opacity-0 -translate-y-5"
        >
          <DialogPanel ref="modal" :class="modalSize" class="w-full inline-block align-middle bg-white dark:bg-gray-600 rounded-2xl text-left shadow-xl transform transition-all sm:my-8">
            <div v-if="!inescapable" class="hidden sm:block absolute top-0 right-0 pt-4 pr-3">
              <button @click.prevent="close" type="button" class="bg-white dark:bg-gray-600 rounded-full text-gray-400 hover:text-gray-500 focus:bg-gray-50 focus:outline-none focus:ring focus:ring-gray-300 dark:focus:ring-gray-500 transition ease-in-out">
                <span class="sr-only">Close</span>
                <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
            </div>
            <div class="sm:flex sm:items-start px-4 pt-5 pb-4 sm:p-6">
              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
                <ModalHeadline v-if="headline">
                  {{ headline }}
                </ModalHeadline>
                <div>
                  <slot/>
                </div>
              </div>
            </div>
            <div class="bg-gray-100 dark:bg-gray-700 px-4 py-3 sm:px-6 flex flex-col space-y-2 sm:space-y-0 sm:flex-row-reverse rounded-b-2xl">
              <slot name="actions" :close="close">
                <AppButton @click.prevent="performAction" :loading="actionLoading" type="button" :color="actionColor" class="sm:ml-2 text-sm">
                  {{ computedActionText }}
                </AppButton>
                <AppButton v-if="!inescapable" @click.prevent="close" type="button" color="white" class="text-sm">
                  {{ __('Close') }}
                </AppButton>
              </slot>
            </div>
          </DialogPanel>
        </TransitionChild>
      </div>
    </Dialog>
  </TransitionRoot>
</template>

<script setup>
import { ref, computed, nextTick, onMounted, onUnmounted } from 'vue'
import { TransitionRoot, TransitionChild, Dialog, DialogPanel } from '@headlessui/vue'
import { useModal } from 'momentum-modal'
import ModalHeadline from '@/components/modals/ModalHeadline.vue'
import { clearAllBodyScrollLocks } from 'body-scroll-lock'
import AppButton from '@/components/AppButton.vue'

const props = defineProps({
  headline: String,
  actionText: String,
  actionLoading: {
    type: Boolean,
    default: false
  },
  actionColor: {
    type: String,
    default: 'primary',
  },
  autoClose: {
    type: Boolean,
    default: () => false
  },
  size: {
    type: String,
    default: 'lg'
  },
  initialFocus: Object,
  inescapable: {
    type: Boolean,
    default: () => false,
  }
})
const emit = defineEmits(['close', 'action'])
const { show, close, redirect } = useModal()

const modal = ref()
const performAction = () => {
  emit('action', close)

  if (props.autoClose) {
    close()
  }
}
const listener = (e) => {
  if (e.key === 'Escape') {
    e.stopPropagation()

    if (!props.inescapable) {
      close()
    }
  }
}
const computedActionText = computed(() => {
  return props.actionText || trans('Save')
})
const modalSize = computed(() => {
  const modalSizes = {
    xs: 'sm:max-w-xs',
    sm: 'sm:max-w-sm',
    md: 'sm:max-w-md',
    lg: 'sm:max-w-lg',
    xl: 'sm:max-w-xl',
    '2xl': 'sm:max-w-2xl',
    '3xl': 'sm:max-w-3xl',
    '4xl': 'sm:max-w-4xl',
  }

  return modalSizes[props.size]
})

onMounted(() => {
  show.value = true
  document.addEventListener('keydown', listener)

  nextTick(() => {
    // disableBodyScroll(modal.value)
  })
})

onUnmounted(() => {
  clearAllBodyScrollLocks()
})
</script>

Regardless, I should be seeing the logging when it tries to resolve the component.

grantholle commented 1 year ago

The modal props look right from the response

Screenshot 2023-01-04 at 10 04 39 PM
jeffreyvanhees commented 1 year ago

@grantholle Hmm, did you install Inertia 1.0.0-beta.2? Currently trying that beta and having the same problem.

grantholle commented 1 year ago

@jeffreyvanhees I think I'm still on 0.11.1.

nmkr commented 1 year ago

had the same until i realized there is a modal and a usemodal reference..

in your desired modal file you use "usemodal" import { useModal } from 'momentum-modal'

then in your layout file import { Modal } from 'momentum-modal' and place the <Modal /> somewhere

your modal gets then loaded into the main modal component 🪄 then visit the route and the modal will show with correct props etc..

if you use vite you might need to replace the mount function like this:

.use(modal, {
    resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue")),
})
lepikhinb commented 1 year ago

@nmkr thank you for the help

@grantholle feel free to re-open the issue if the problem persists