Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(groups): use suspense to delay rendering of group items #15215

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { makeTagProps } from '@/composables/tag'
import { makeThemeProps, useTheme } from '@/composables/theme'

// Utilities
import { computed, toRef } from 'vue'
import { computed, Suspense, toRef } from 'vue'
import { convertToUnit, genericComponent, propsFactory, useRender } from '@/util'

// Types
Expand Down Expand Up @@ -95,7 +95,7 @@ export const VBottomNavigation = genericComponent<new <T>(
absolute: toRef(props, 'absolute'),
})

useGroup(props, VBtnToggleSymbol)
const group = useGroup(props, VBtnToggleSymbol)

provideDefaults({
VBtn: {
Expand Down Expand Up @@ -135,11 +135,13 @@ export const VBottomNavigation = genericComponent<new <T>(
props.style,
]}
>
{ slots.default && (
<div class="v-bottom-navigation__content">
{ slots.default() }
</div>
)}
<div class="v-bottom-navigation__content">
<Suspense onResolve={ group.ready }>
<>
{ slots.default?.() }
</>
</Suspense>
</div>
</props.tag>
)
})
Expand Down
4 changes: 3 additions & 1 deletion packages/vuetify/src/components/VBtn/VBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,9 @@ export const VBtn = genericComponent<VBtnSlots>()({
)
})

return { group }
const expose = { group }

return group ? group.isReady.then(() => expose) : expose
},
})

Expand Down
21 changes: 13 additions & 8 deletions packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { makeVBtnGroupProps, VBtnGroup } from '@/components/VBtnGroup/VBtnGroup'
import { makeGroupProps, useGroup } from '@/composables/group'

// Utilities
import { Suspense } from 'vue'
import { genericComponent, propsFactory, useRender } from '@/util'

// Types
Expand Down Expand Up @@ -45,7 +46,7 @@ export const VBtnToggle = genericComponent<new <T>(
},

setup (props, { slots }) {
const { isSelected, next, prev, select, selected } = useGroup(props, VBtnToggleSymbol)
const { isSelected, next, prev, select, selected, ready } = useGroup(props, VBtnToggleSymbol)

useRender(() => {
const btnGroupProps = VBtnGroup.filterProps(props)
Expand All @@ -59,13 +60,17 @@ export const VBtnToggle = genericComponent<new <T>(
{ ...btnGroupProps }
style={ props.style }
>
{ slots.default?.({
isSelected,
next,
prev,
select,
selected,
})}
<Suspense onResolve={ ready }>
<>
{ slots.default?.({
isSelected,
next,
prev,
select,
selected,
})}
</>
</Suspense>
</VBtnGroup>
)
})
Expand Down
8 changes: 5 additions & 3 deletions packages/vuetify/src/components/VChip/VChip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { Ripple } from '@/directives/ripple'

// Utilities
import { computed } from 'vue'
import { EventProp, genericComponent, propsFactory } from '@/util'
import { EventProp, genericComponent, propsFactory, useRender } from '@/util'

// Types
import type { PropType } from 'vue'
Expand Down Expand Up @@ -166,7 +166,7 @@ export const VChip = genericComponent<VChipSlots>()({
}
}

return () => {
useRender(() => {
const Tag = (link.isLink.value) ? 'a' : props.tag
const hasAppendMedia = !!(props.appendIcon || props.appendAvatar)
const hasAppend = !!(hasAppendMedia || slots.append)
Expand Down Expand Up @@ -357,7 +357,9 @@ export const VChip = genericComponent<VChipSlots>()({
)}
</Tag>
)
}
})

return group ? group.isReady : undefined
},
})

Expand Down
22 changes: 13 additions & 9 deletions packages/vuetify/src/components/VChipGroup/VChipGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { makeThemeProps, provideTheme } from '@/composables/theme'
import { makeVariantProps } from '@/composables/variant'

// Utilities
import { toRef } from 'vue'
import { Suspense, toRef } from 'vue'
import { deepEqual, genericComponent, propsFactory, useRender } from '@/util'

// Types
Expand Down Expand Up @@ -65,7 +65,7 @@ export const VChipGroup = genericComponent<new <T>(

setup (props, { slots }) {
const { themeClasses } = provideTheme(props)
const { isSelected, select, next, prev, selected } = useGroup(props, VChipGroupSymbol)
const { isSelected, select, next, prev, selected, ready } = useGroup(props, VChipGroupSymbol)

provideDefaults({
VChip: {
Expand All @@ -92,13 +92,17 @@ export const VChipGroup = genericComponent<new <T>(
]}
style={ props.style }
>
{ slots.default?.({
isSelected,
select,
next,
prev,
selected: selected.value,
})}
<Suspense onResolve={ ready }>
<>
{ slots.default?.({
isSelected,
select,
next,
prev,
selected: selected.value,
})}
</>
</Suspense>
</VSlideGroup>
)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export const VExpansionPanel = genericComponent<VExpansionPanelSlots>()({
)
})

return {}
return groupItem.isReady
},
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { makeGroupProps, useGroup } from '@/composables/group'
import { makeThemeProps, provideTheme } from '@/composables/theme'

// Utilities
import { computed, toRef } from 'vue'
import { computed, Suspense, toRef } from 'vue'
import { genericComponent, propsFactory, useRender } from '@/util'

// Types
Expand Down Expand Up @@ -47,7 +47,7 @@ export const VExpansionPanels = genericComponent()({
},

setup (props, { slots }) {
useGroup(props, VExpansionPanelSymbol)
const group = useGroup(props, VExpansionPanelSymbol)

const { themeClasses } = provideTheme(props)

Expand Down Expand Up @@ -83,8 +83,13 @@ export const VExpansionPanels = genericComponent()({
props.class,
]}
style={ props.style }
v-slots={ slots }
/>
>
<Suspense onResolve={ group.ready }>
<>
{ slots.default?.() }
</>
</Suspense>
</props.tag>
))

return {}
Expand Down
11 changes: 7 additions & 4 deletions packages/vuetify/src/components/VItemGroup/VItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { VItemGroupSymbol } from './VItemGroup'
import { makeGroupItemProps, useGroupItem } from '@/composables/group'

// Utilities
import { genericComponent } from '@/util'
import { genericComponent, useRender } from '@/util'

type VItemSlots = {
default: {
Expand All @@ -26,15 +26,18 @@ export const VItem = genericComponent<VItemSlots>()({
},

setup (props, { slots }) {
const { isSelected, select, toggle, selectedClass, value, disabled } = useGroupItem(props, VItemGroupSymbol)
return () => slots.default?.({
const { isSelected, isReady, select, toggle, selectedClass, value, disabled } = useGroupItem(props, VItemGroupSymbol)

useRender(() => slots.default?.({
isSelected: isSelected.value,
selectedClass: selectedClass.value,
select,
toggle,
value: value.value,
disabled: disabled.value,
})
}))

return isReady
},
})

Expand Down
21 changes: 13 additions & 8 deletions packages/vuetify/src/components/VItemGroup/VItemGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { makeTagProps } from '@/composables/tag'
import { makeThemeProps, provideTheme } from '@/composables/theme'

// Utilities
import { Suspense } from 'vue'
import { genericComponent, propsFactory } from '@/util'

// Types
Expand Down Expand Up @@ -51,7 +52,7 @@ export const VItemGroup = genericComponent<new <T>(

setup (props, { slots }) {
const { themeClasses } = provideTheme(props)
const { isSelected, select, next, prev, selected } = useGroup(props, VItemGroupSymbol)
const { isSelected, select, next, prev, selected, ready } = useGroup(props, VItemGroupSymbol)

return () => (
<props.tag
Expand All @@ -62,13 +63,17 @@ export const VItemGroup = genericComponent<new <T>(
]}
style={ props.style }
>
{ slots.default?.({
isSelected,
select,
next,
prev,
selected: selected.value,
})}
<Suspense onResolve={ ready }>
<>
{ slots.default?.({
isSelected,
select,
next,
prev,
selected: selected.value,
})}
</>
</Suspense>
</props.tag>
)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { VItemGroup } from '../VItemGroup'
// Utilities
import { describe, expect, it } from '@jest/globals'
import { mount } from '@vue/test-utils'
import { h } from 'vue'
import { h, nextTick } from 'vue'
import { createVuetify } from '@/framework'

describe('VItemGroup', () => {
Expand Down Expand Up @@ -35,6 +35,8 @@ describe('VItemGroup', () => {
},
})

await nextTick()

const items = wrapper.findAll('#item')

await items[0].trigger('click')
Expand All @@ -56,6 +58,9 @@ describe('VItemGroup', () => {
},
})

await nextTick()
await nextTick()

const items = wrapper.findAll('#item')

await items[0].trigger('click')
Expand All @@ -76,6 +81,9 @@ describe('VItemGroup', () => {
},
})

await nextTick()
await nextTick()

const items = wrapper.findAll('#item')

await items[0].trigger('click')
Expand Down Expand Up @@ -106,6 +114,8 @@ describe('VItemGroup', () => {
},
})

await nextTick()

const items = wrapper.findAll('#item')

await items[0].trigger('click')
Expand Down
8 changes: 6 additions & 2 deletions packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useResizeObserver } from '@/composables/resizeObserver'
import { makeTagProps } from '@/composables/tag'

// Utilities
import { computed, shallowRef, watch } from 'vue'
import { computed, shallowRef, Suspense, watch } from 'vue'
import { bias, calculateCenteredOffset, calculateUpdatedOffset } from './helpers'
import { clamp, focusableChildren, genericComponent, IN_BROWSER, propsFactory, useRender } from '@/util'

Expand Down Expand Up @@ -398,7 +398,11 @@ export const VSlideGroup = genericComponent<new <T>(
onFocusout={ onFocusout }
onKeydown={ onKeydown }
>
{ slots.default?.(slotProps.value) }
<Suspense onResolve={ group.ready }>
<>
{ slots.default?.(slotProps.value) }
</>
</Suspense>
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { makeGroupItemProps, useGroupItem } from '@/composables/group'

// Utilities
import { VSlideGroupSymbol } from './VSlideGroup'
import { genericComponent } from '@/util'
import { genericComponent, useRender } from '@/util'

// Types
import type { UnwrapRef } from 'vue'
Expand All @@ -30,12 +30,14 @@ export const VSlideGroupItem = genericComponent<VSlideGroupItemSlots>()({
setup (props, { slots }) {
const slideGroupItem = useGroupItem(props, VSlideGroupSymbol)

return () => slots.default?.({
useRender(() => slots.default?.({
isSelected: slideGroupItem.isSelected.value,
select: slideGroupItem.select,
toggle: slideGroupItem.toggle,
selectedClass: slideGroupItem.selectedClass.value,
})
}))

return slideGroupItem.isReady
},
})

Expand Down
8 changes: 6 additions & 2 deletions packages/vuetify/src/components/VWindow/VWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { makeThemeProps, provideTheme } from '@/composables/theme'
import { Touch } from '@/directives/touch'

// Utilities
import { computed, provide, ref, shallowRef, watch } from 'vue'
import { computed, provide, ref, shallowRef, Suspense, watch } from 'vue'
import { genericComponent, propsFactory, useRender } from '@/util'

// Types
Expand Down Expand Up @@ -243,7 +243,11 @@ export const VWindow = genericComponent<new <T>(
height: transitionHeight.value,
}}
>
{ slots.default?.({ group }) }
<Suspense onResolve={ group.ready }>
<>
{ slots.default?.({ group }) }
</>
</Suspense>

{ props.showArrows !== false && (
<div class="v-window__controls">
Expand Down