@@ -9,16 +9,27 @@ const props = defineProps<{
99}>()
1010
1111const chartModal = useModal (' chart-modal' )
12-
12+ const hasChartModalTransitioned = shallowRef ( false )
1313const isChartModalOpen = shallowRef (false )
14+
1415async function openChartModal() {
1516 isChartModalOpen .value = true
17+ hasChartModalTransitioned .value = false
1618 // ensure the component renders before opening the dialog
1719 await nextTick ()
1820 await nextTick ()
1921 chartModal .open ()
2022}
2123
24+ function handleModalClose() {
25+ isChartModalOpen .value = false
26+ hasChartModalTransitioned .value = false
27+ }
28+
29+ function handleModalTransitioned() {
30+ hasChartModalTransitioned .value = true
31+ }
32+
2233const { fetchPackageDownloadEvolution } = useCharts ()
2334
2435const { accentColors, selectedAccentColor } = useAccentColor ()
@@ -249,16 +260,45 @@ const config = computed(() => {
249260 </CollapsibleSection >
250261 </div >
251262
252- <PackageChartModal v-if =" isChartModalOpen" @close =" isChartModalOpen = false" >
253- <PackageDownloadAnalytics
254- :weeklyDownloads =" weeklyDownloads"
255- :inModal =" true"
256- :packageName =" props.packageName"
257- :createdIso =" createdIso"
263+ <PackageChartModal @close =" handleModalClose" @transitioned =" handleModalTransitioned" >
264+ <!-- The Chart is mounted after the dialog has transitioned -->
265+ <!-- This avoids flaky behavior that hides the chart's minimap half of the time -->
266+ <Transition name =" opacity" mode =" out-in" >
267+ <PackageDownloadAnalytics
268+ v-if =" hasChartModalTransitioned"
269+ :weeklyDownloads =" weeklyDownloads"
270+ :inModal =" true"
271+ :packageName =" props.packageName"
272+ :createdIso =" createdIso"
273+ />
274+ </Transition >
275+
276+ <!-- This placeholder bears the same dimensions as the PackageDownloadAnalytics component -->
277+ <!-- Avoids CLS when the dialog has transitioned -->
278+ <div
279+ v-if =" !hasChartModalTransitioned"
280+ class =" w-full aspect-[390/634.5] sm:aspect-[718/622.797]"
258281 />
259282 </PackageChartModal >
260283</template >
261284
285+ <style scoped>
286+ .opacity-enter-active ,
287+ .opacity-leave-active {
288+ transition : opacity 200ms ease ;
289+ }
290+
291+ .opacity-enter-from ,
292+ .opacity-leave-to {
293+ opacity : 0 ;
294+ }
295+
296+ .opacity-enter-to ,
297+ .opacity-leave-from {
298+ opacity : 1 ;
299+ }
300+ </style >
301+
262302<style >
263303/* * Overrides */
264304.vue-ui-sparkline-title span {
0 commit comments