diff --git a/app/components/Modal.client.vue b/app/components/Modal.client.vue index a8e2831b2..e34c15739 100644 --- a/app/components/Modal.client.vue +++ b/app/components/Modal.client.vue @@ -5,6 +5,10 @@ const props = defineProps<{ const dialogRef = useTemplateRef('dialogRef') +const emit = defineEmits<{ + (e: 'transitioned'): void +}>() + const modalTitleId = computed(() => { const id = getCurrentInstance()?.attrs.id return id ? `${id}-title` : undefined @@ -14,6 +18,20 @@ function handleModalClose() { dialogRef.value?.close() } +/** + * Emits `transitioned` once the dialog has finished its open opacity transition. + * This is used by consumers that need to run layout-sensitive logic (for example + * dispatching a resize) only after the modal is fully displayed. + */ +function onDialogTransitionEnd(event: TransitionEvent) { + const el = dialogRef.value + if (!el) return + if (!el.open) return + if (event.target !== el) return + if (event.propertyName !== 'opacity') return + emit('transitioned') +} + defineExpose({ showModal: () => dialogRef.value?.showModal(), close: () => dialogRef.value?.close(), @@ -28,6 +46,7 @@ defineExpose({ class="w-full bg-bg border border-border rounded-lg shadow-xl max-h-[90vh] overflow-y-auto overscroll-contain m-0 m-auto p-6 text-fg focus-visible:outline focus-visible:outline-accent/70" :aria-labelledby="modalTitleId" v-bind="$attrs" + @transitionend="onDialogTransitionEnd" >
diff --git a/app/components/Package/WeeklyDownloadStats.vue b/app/components/Package/WeeklyDownloadStats.vue index 67a797e78..451cb7797 100644 --- a/app/components/Package/WeeklyDownloadStats.vue +++ b/app/components/Package/WeeklyDownloadStats.vue @@ -9,16 +9,27 @@ const props = defineProps<{ }>() const chartModal = useModal('chart-modal') - +const hasChartModalTransitioned = shallowRef(false) const isChartModalOpen = shallowRef(false) + async function openChartModal() { isChartModalOpen.value = true + hasChartModalTransitioned.value = false // ensure the component renders before opening the dialog await nextTick() await nextTick() chartModal.open() } +function handleModalClose() { + isChartModalOpen.value = false + hasChartModalTransitioned.value = false +} + +function handleModalTransitioned() { + hasChartModalTransitioned.value = true +} + const { fetchPackageDownloadEvolution } = useCharts() const { accentColors, selectedAccentColor } = useAccentColor() @@ -249,16 +260,45 @@ const config = computed(() => {
- - + + + + + + + + +
+ +