diff --git a/packages/vuetify/src/components/VApp/VApp.tsx b/packages/vuetify/src/components/VApp/VApp.tsx index f067aafe175..98f8f3760c0 100644 --- a/packages/vuetify/src/components/VApp/VApp.tsx +++ b/packages/vuetify/src/components/VApp/VApp.tsx @@ -7,6 +7,7 @@ import { makeThemeProps, provideTheme } from '@/composables/theme' import { useRtl } from '@/composables/rtl' // Utilities +import { Suspense } from 'vue' import { defineComponent, useRender } from '@/util' export const VApp = defineComponent({ @@ -34,7 +35,11 @@ export const VApp = defineComponent({ style={ layoutStyles.value } >
- { slots.default?.() } + + <> + { slots.default?.() } + +
)) diff --git a/packages/vuetify/src/components/VAppBar/VAppBar.tsx b/packages/vuetify/src/components/VAppBar/VAppBar.tsx index bb50ea00981..c6e1dbba7f0 100644 --- a/packages/vuetify/src/components/VAppBar/VAppBar.tsx +++ b/packages/vuetify/src/components/VAppBar/VAppBar.tsx @@ -53,12 +53,12 @@ export const VAppBar = defineComponent({ const vToolbarRef = ref() const isActive = useProxiedModel(props, 'modelValue') const height = computed(() => { - const height: number = vToolbarRef.value?.contentHeight ?? 0 + const height: number = vToolbarRef.value?.contentHeight ?? props.height const extensionHeight: number = vToolbarRef.value?.extensionHeight ?? 0 return (height + extensionHeight) }) - const { layoutItemStyles } = useLayoutItem({ + const { layoutItemStyles, layoutIsReady } = useLayoutItem({ id: props.name, order: computed(() => parseInt(props.order, 10)), position: toRef(props, 'location'), @@ -90,7 +90,7 @@ export const VAppBar = defineComponent({ ) }) - return {} + return layoutIsReady }, }) diff --git a/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx b/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx index 4ff052f8a44..1ecd530a988 100644 --- a/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx +++ b/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx @@ -67,7 +67,7 @@ export const VBottomNavigation = defineComponent({ (props.density === 'compact' ? 16 : 0) )) const isActive = useProxiedModel(props, 'modelValue', props.modelValue) - const { layoutItemStyles } = useLayoutItem({ + const { layoutItemStyles, layoutIsReady } = useLayoutItem({ id: props.name, order: computed(() => parseInt(props.order, 10)), position: computed(() => 'bottom'), @@ -123,7 +123,7 @@ export const VBottomNavigation = defineComponent({ ) }) - return {} + return layoutIsReady }, }) diff --git a/packages/vuetify/src/components/VBottomNavigation/__tests__/VBottomNavigation.spec.cy.tsx b/packages/vuetify/src/components/VBottomNavigation/__tests__/VBottomNavigation.spec.cy.tsx index a30ae51818d..8c1c0e662fa 100644 --- a/packages/vuetify/src/components/VBottomNavigation/__tests__/VBottomNavigation.spec.cy.tsx +++ b/packages/vuetify/src/components/VBottomNavigation/__tests__/VBottomNavigation.spec.cy.tsx @@ -31,4 +31,14 @@ describe('VBottomNavigation', () => { cy.get('.v-bottom-navigation').should('have.css', 'height', '40px') }) + + it('should not be visible if modelValue is false', () => { + cy.mount(() => ( + + + + )) + + cy.get('.v-bottom-navigation').should('not.be.visible') + }) }) diff --git a/packages/vuetify/src/components/VFooter/VFooter.tsx b/packages/vuetify/src/components/VFooter/VFooter.tsx index c09c31b23d3..1ca31d110ee 100644 --- a/packages/vuetify/src/components/VFooter/VFooter.tsx +++ b/packages/vuetify/src/components/VFooter/VFooter.tsx @@ -47,7 +47,7 @@ export const VFooter = defineComponent({ autoHeight.value = entries[0].target.clientHeight }) const height = computed(() => props.height === 'auto' ? autoHeight.value : parseInt(props.height, 10)) - const { layoutItemStyles } = useLayoutItem({ + const { layoutItemStyles, layoutIsReady } = useLayoutItem({ id: props.name, order: computed(() => parseInt(props.order, 10)), position: computed(() => 'bottom'), @@ -76,6 +76,6 @@ export const VFooter = defineComponent({ /> )) - return {} + return props.app ? layoutIsReady : {} }, }) diff --git a/packages/vuetify/src/components/VLayout/VLayout.tsx b/packages/vuetify/src/components/VLayout/VLayout.tsx index 733aa2a4283..fc5b4aba022 100644 --- a/packages/vuetify/src/components/VLayout/VLayout.tsx +++ b/packages/vuetify/src/components/VLayout/VLayout.tsx @@ -1,12 +1,13 @@ // Styles import './VLayout.sass' -// Utilities -import { defineComponent, useRender } from '@/util' - // Composables import { createLayout, makeLayoutProps } from '@/composables/layout' +// Utilities +import { Suspense } from 'vue' +import { defineComponent, useRender } from '@/util' + export const VLayout = defineComponent({ name: 'VLayout', @@ -17,7 +18,11 @@ export const VLayout = defineComponent({ useRender(() => (
- { slots.default?.() } + + <> + { slots.default?.() } + +
)) diff --git a/packages/vuetify/src/components/VMain/VMain.tsx b/packages/vuetify/src/components/VMain/VMain.tsx index ce65eb6c736..20a96d414c8 100644 --- a/packages/vuetify/src/components/VMain/VMain.tsx +++ b/packages/vuetify/src/components/VMain/VMain.tsx @@ -15,7 +15,7 @@ export const VMain = defineComponent({ props: makeTagProps({ tag: 'main' }), setup (props, { slots }) { - const { mainStyles } = useLayout() + const { mainStyles, layoutIsReady } = useLayout() const { ssrBootStyles } = useSsrBoot() useRender(() => ( @@ -32,6 +32,6 @@ export const VMain = defineComponent({ )) - return {} + return layoutIsReady }, }) diff --git a/packages/vuetify/src/components/VNavigationDrawer/VNavigationDrawer.tsx b/packages/vuetify/src/components/VNavigationDrawer/VNavigationDrawer.tsx index 668d284cf47..f901d65102e 100644 --- a/packages/vuetify/src/components/VNavigationDrawer/VNavigationDrawer.tsx +++ b/packages/vuetify/src/components/VNavigationDrawer/VNavigationDrawer.tsx @@ -16,7 +16,7 @@ import { useSsrBoot } from '@/composables/ssrBoot' import { useTouch } from './touch' // Utilities -import { computed, onBeforeMount, ref, toRef, Transition, watch } from 'vue' +import { computed, ref, toRef, Transition, watch } from 'vue' import { convertToUnit, defineComponent, useRender } from '@/util' // Types @@ -96,11 +96,9 @@ export const VNavigationDrawer = defineComponent({ if (val) isActive.value = true }) - onBeforeMount(() => { - if (props.modelValue != null || isTemporary.value) return - + if (props.modelValue == null && !isTemporary.value) { isActive.value = props.permanent || !mobile.value - }) + } const rootEl = ref() @@ -119,7 +117,7 @@ export const VNavigationDrawer = defineComponent({ return isDragging.value ? size * dragProgress.value : size }) - const { layoutItemStyles, layoutRect, layoutItemScrimStyles } = useLayoutItem({ + const { layoutItemStyles, layoutRect, layoutItemScrimStyles, layoutIsReady } = useLayoutItem({ id: props.name, order: computed(() => parseInt(props.order, 10)), position: toRef(props, 'location'), @@ -219,7 +217,7 @@ export const VNavigationDrawer = defineComponent({ ) }) - return {} + return layoutIsReady }, }) diff --git a/packages/vuetify/src/composables/layout.ts b/packages/vuetify/src/composables/layout.ts index d31671b4fba..64cc404b3a9 100644 --- a/packages/vuetify/src/composables/layout.ts +++ b/packages/vuetify/src/composables/layout.ts @@ -5,10 +5,10 @@ import { useResizeObserver } from '@/composables/resizeObserver' import { computed, inject, + nextTick, onActivated, onBeforeUnmount, onDeactivated, - onMounted, provide, reactive, ref, @@ -53,6 +53,7 @@ interface LayoutProvide { items: Ref layoutRect: Ref rootZIndex: Ref + layoutIsReady: Promise } export const VuetifyLayoutKey: InjectionKey = Symbol.for('vuetify:layout') @@ -112,6 +113,8 @@ export function useLayoutItem (options: { onDeactivated(() => isKeptAlive.value = true) onActivated(() => isKeptAlive.value = false) + const layoutIsReady = nextTick() + const { layoutItemStyles, layoutItemScrimStyles, @@ -123,7 +126,7 @@ export function useLayoutItem (options: { onBeforeUnmount(() => layout.unregister(id)) - return { layoutItemStyles, layoutRect: layout.layoutRect, layoutItemScrimStyles } + return { layoutItemStyles, layoutRect: layout.layoutRect, layoutItemScrimStyles, layoutIsReady } } const generateLayers = ( @@ -167,27 +170,6 @@ export function createLayout (props: { overlaps?: string[], fullHeight?: boolean const disabledTransitions = reactive(new Map>()) const { resizeRef, contentRect: layoutRect } = useResizeObserver() - const computedOverlaps = computed(() => { - const map = new Map() - const overlaps = props.overlaps ?? [] - for (const overlap of overlaps.filter(item => item.includes(':'))) { - const [top, bottom] = overlap.split(':') - if (!registered.value.includes(top) || !registered.value.includes(bottom)) continue - - const topPosition = positions.get(top) - const bottomPosition = positions.get(bottom) - const topAmount = layoutSizes.get(top) - const bottomAmount = layoutSizes.get(bottom) - - if (!topPosition || !bottomPosition || !topAmount || !bottomAmount) continue - - map.set(bottom, { position: topPosition.value, amount: parseInt(topAmount.value, 10) }) - map.set(top, { position: bottomPosition.value, amount: -parseInt(bottomAmount.value, 10) }) - } - - return map - }) - const layers = computed(() => { const uniquePriorities = [...new Set([...priorities.values()].map(p => p.value))].sort((a, b) => a - b) const layout = [] @@ -234,10 +216,7 @@ export function createLayout (props: { overlaps?: string[], fullHeight?: boolean const rootVm = getCurrentInstance('createLayout') - const isMounted = ref(false) - onMounted(() => { - isMounted.value = true - }) + const layoutIsReady = nextTick() provide(VuetifyLayoutKey, { register: ( @@ -281,19 +260,12 @@ export function createLayout (props: { overlaps?: string[], fullHeight?: boolean ...(transitionsEnabled.value ? undefined : { transition: 'none' }), } as const - if (!isMounted.value) return styles - if (index.value < 0) throw new Error(`Layout item "${id}" is missing`) const item = items.value[index.value] if (!item) throw new Error(`Could not find layout item "${id}`) - const overlap = computedOverlaps.value.get(id) - if (overlap) { - item[overlap.position] += overlap.amount - } - return { ...styles, height: isHorizontal ? `calc(100% - ${item.top}px - ${item.bottom}px)` : elementSize.value ? `${elementSize.value}px` : undefined, @@ -325,6 +297,7 @@ export function createLayout (props: { overlaps?: string[], fullHeight?: boolean items, layoutRect, rootZIndex, + layoutIsReady, }) const layoutClasses = computed(() => [ @@ -342,6 +315,7 @@ export function createLayout (props: { overlaps?: string[], fullHeight?: boolean getLayoutItem, items, layoutRect, + layoutIsReady, layoutRef: resizeRef, } }