Skip to content

Commit

Permalink
fix(comp:drawer): content first render should be delayed till visible (
Browse files Browse the repository at this point in the history
  • Loading branch information
sallerli1 committed Aug 21, 2023
1 parent 54f2c7f commit 4e4542b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 47 deletions.
53 changes: 30 additions & 23 deletions packages/components/drawer/__tests__/drawer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@ import { DrawerButtonProps, DrawerInstance, DrawerProps } from '../src/types'

describe('Drawer', () => {
const content = [h('p', 'Some contents...')]
const DrawerMount = (options?: MountingOptions<Partial<DrawerProps>>) => {
const DrawerMount = async (options?: MountingOptions<Partial<DrawerProps>>) => {
const { props, slots, ...rest } = options || {}
const _options = {
props: { visible: true, ...props },
slots: { default: content, ...slots },
attachTo: 'body',
...rest,
} as MountingOptions<DrawerProps>
return mount(Drawer, _options) as VueWrapper<DrawerInstance>
const wrapper = mount(Drawer, _options) as VueWrapper<DrawerInstance>

await nextTick()
await flushPromises()

return wrapper
}

afterEach(() => {
Expand All @@ -36,7 +41,9 @@ describe('Drawer', () => {

test('v-model:visible work', async () => {
const onUpdateVisible = vi.fn()
const wrapper = DrawerMount({ props: { closeIcon: 'close', visible: false, 'onUpdate:visible': onUpdateVisible } })
const wrapper = await DrawerMount({
props: { closeIcon: 'close', visible: false, 'onUpdate:visible': onUpdateVisible },
})
expect(isElementVisible(document.querySelector('.ix-drawer-wrapper'))).toBe(false)

await wrapper.setProps({ visible: true })
Expand All @@ -53,7 +60,7 @@ describe('Drawer', () => {
})

test('closable work', async () => {
const wrapper = DrawerMount({ props: { closable: false, closeIcon: 'close' } })
const wrapper = await DrawerMount({ props: { closable: false, closeIcon: 'close' } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)

expect(drawerWrapper.find('.ix-icon-close').exists()).toBe(false)
Expand All @@ -65,7 +72,7 @@ describe('Drawer', () => {

test('closeIcon work', async () => {
const onClose = vi.fn()
const wrapper = DrawerMount({ props: { closeIcon: 'up', onClose } })
const wrapper = await DrawerMount({ props: { closeIcon: 'up', onClose } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)

expect(drawerWrapper.find('.ix-icon-close-filled').exists()).toBe(false)
Expand All @@ -87,7 +94,7 @@ describe('Drawer', () => {
})

test('closeIcon slot work', async () => {
const wrapper = DrawerMount({
const wrapper = await DrawerMount({
props: { closeIcon: 'up' },
slots: {
closeIcon: () => h(IxIcon, { name: 'close' }),
Expand All @@ -101,7 +108,7 @@ describe('Drawer', () => {

test('closeOnEsc work', async () => {
const onUpdateVisible = vi.fn()
const wrapper = DrawerMount({ props: { closeOnEsc: false, 'onUpdate:visible': onUpdateVisible } })
const wrapper = await DrawerMount({ props: { closeOnEsc: false, 'onUpdate:visible': onUpdateVisible } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)

await drawerWrapper.trigger('keydown', { code: 'Escape' })
Expand All @@ -116,7 +123,7 @@ describe('Drawer', () => {
})

test('destroyOnHide work', async () => {
const wrapper = DrawerMount({ props: { destroyOnHide: true } })
const wrapper = await DrawerMount({ props: { destroyOnHide: true } })
let drawerWrapper = wrapper.getComponent(DrawerWrapper)

expect(drawerWrapper.find('.ix-drawer').exists()).toBe(true)
Expand All @@ -138,7 +145,7 @@ describe('Drawer', () => {

test('footer buttons work', async () => {
let footer: DrawerButtonProps[] = [{ text: 'button1' }]
const wrapper = DrawerMount({ props: { footer } })
const wrapper = await DrawerMount({ props: { footer } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)

expect(drawerWrapper.findAll('.ix-button').length).toBe(1)
Expand All @@ -151,7 +158,7 @@ describe('Drawer', () => {

test('footer slot work', async () => {
const footer: DrawerButtonProps[] = [{ text: 'button1' }]
const wrapper = DrawerMount({
const wrapper = await DrawerMount({
props: { footer },
slots: { footer: () => h(IxButton, {}, { default: () => 'button slot' }) },
})
Expand All @@ -163,7 +170,7 @@ describe('Drawer', () => {

test('header work', async () => {
let header: string | HeaderProps = 'This is header'
const wrapper = DrawerMount({ props: { header } })
const wrapper = await DrawerMount({ props: { header } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)

expect(drawerWrapper.find('.ix-header').text()).toBe(header)
Expand All @@ -183,7 +190,7 @@ describe('Drawer', () => {

test('header slot work', async () => {
const header = 'This is header'
const wrapper = DrawerMount({
const wrapper = await DrawerMount({
props: { header },
slots: {
header: () => h(IxHeader, { title: 'this is header2' }),
Expand All @@ -195,7 +202,7 @@ describe('Drawer', () => {
})

test('height work', async () => {
const wrapper = DrawerMount({ props: { height: 400 } })
const wrapper = await DrawerMount({ props: { height: 400 } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)
const getDom = () => drawerWrapper.find('.ix-drawer').element as HTMLElement

Expand All @@ -211,7 +218,7 @@ describe('Drawer', () => {
})

test('mask work', async () => {
const wrapper = DrawerMount({ props: { mask: false } })
const wrapper = await DrawerMount({ props: { mask: false } })

expect(isElementVisible(document.querySelector('.ix-mask'))).toBe(false)

Expand All @@ -222,7 +229,7 @@ describe('Drawer', () => {

test('maskClosable work', async () => {
const onUpdateVisible = vi.fn()
const wrapper = DrawerMount({ props: { maskClosable: false, 'onUpdate:visible': onUpdateVisible } })
const wrapper = await DrawerMount({ props: { maskClosable: false, 'onUpdate:visible': onUpdateVisible } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)

await drawerWrapper.trigger('click')
Expand All @@ -236,7 +243,7 @@ describe('Drawer', () => {
})

test('offset work', async () => {
const wrapper = DrawerMount({ props: { offset: 256 } })
const wrapper = await DrawerMount({ props: { offset: 256 } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)

const getDom = () => drawerWrapper.find('.ix-drawer').element as HTMLElement
Expand All @@ -249,7 +256,7 @@ describe('Drawer', () => {
})

test('placement work', async () => {
const wrapper = DrawerMount({ props: { placement: 'start' } })
const wrapper = await DrawerMount({ props: { placement: 'start' } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)

expect(drawerWrapper.classes()).toContain('ix-drawer-start')
Expand All @@ -260,7 +267,7 @@ describe('Drawer', () => {
})

test('container work', async () => {
const wrapper = DrawerMount({ props: { container: '.ix-test-container' } })
const wrapper = await DrawerMount({ props: { container: '.ix-test-container' } })

expect(document.querySelector('.ix-test-container')!.querySelector('.ix-drawer')).not.toBeNull()

Expand All @@ -274,7 +281,7 @@ describe('Drawer', () => {
})

test('width work', async () => {
const wrapper = DrawerMount({ props: { width: 400 } })
const wrapper = await DrawerMount({ props: { width: 400 } })
const drawerWrapper = wrapper.getComponent(DrawerWrapper)
const getDom = () => drawerWrapper.find('.ix-drawer').element as HTMLElement

Expand All @@ -290,7 +297,7 @@ describe('Drawer', () => {
})

test('zIndex work', async () => {
const wrapper = DrawerMount({ props: { zIndex: 1001 } })
const wrapper = await DrawerMount({ props: { zIndex: 1001 } })
expect(document.querySelector('.ix-drawer-wrapper')!.getAttribute('style')).toContain('z-index: 1001')

await wrapper.setProps({ zIndex: 1002 })
Expand All @@ -303,7 +310,7 @@ describe('Drawer', () => {
const onClose = vi.fn()
const onBeforeClose = vi.fn()
const onUpdateVisible = vi.fn()
const wrapper = DrawerMount({ props: { onClose, onBeforeClose, 'onUpdate:visible': onUpdateVisible } })
const wrapper = await DrawerMount({ props: { onClose, onBeforeClose, 'onUpdate:visible': onUpdateVisible } })

wrapper.vm.close()
await flushPromises()
Expand All @@ -316,7 +323,7 @@ describe('Drawer', () => {
test('onBeforeClose with result work', async () => {
const onBeforeClose = vi.fn().mockImplementation((evt: unknown) => evt === 'close')
const onUpdateVisible = vi.fn()
const wrapper = DrawerMount({ props: { onBeforeClose, 'onUpdate:visible': onUpdateVisible } })
const wrapper = await DrawerMount({ props: { onBeforeClose, 'onUpdate:visible': onUpdateVisible } })

wrapper.vm.close(1)
await flushPromises()
Expand All @@ -334,7 +341,7 @@ describe('Drawer', () => {
test('onBeforeClose with promise work', async () => {
const onBeforeClose = vi.fn().mockImplementation((evt: unknown) => Promise.resolve(evt === 'close'))
const onUpdateVisible = vi.fn()
const wrapper = DrawerMount({ props: { onBeforeClose, 'onUpdate:visible': onUpdateVisible } })
const wrapper = await DrawerMount({ props: { onBeforeClose, 'onUpdate:visible': onUpdateVisible } })

wrapper.vm.close(1)
await flushPromises()
Expand Down
7 changes: 5 additions & 2 deletions packages/components/drawer/src/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default defineComponent({

const mask = computed(() => props.mask ?? config.mask)

const { loaded, visible, setVisible, animatedVisible, mergedVisible } = useVisible(props)
const { loaded, delayedLoaded, visible, setVisible, animatedVisible, mergedVisible } = useVisible(props)
const currentZIndex = useZIndex(toRef(props, 'zIndex'), toRef(common, 'overlayZIndex'), visible)

const { open, close } = useTrigger(props, setVisible)
Expand All @@ -57,6 +57,7 @@ export default defineComponent({
config,
mergedPrefixCls,
visible,
delayedLoaded,
animatedVisible,
mergedVisible,
currentZIndex,
Expand Down Expand Up @@ -97,6 +98,7 @@ function useVisible(props: DrawerProps) {
// because portal is lazy loaded, actual visible at the first time should be delayed
// or else transition animation will behave unexpectedly
const loaded = ref<boolean>(false)
const delayedLoaded = ref<boolean>(false)
const delayedVisible = ref<boolean>(false)
watch(
visible,
Expand All @@ -105,6 +107,7 @@ function useVisible(props: DrawerProps) {
loaded.value = true

nextTick(() => {
delayedLoaded.value = true
delayedVisible.value = true
})
} else {
Expand Down Expand Up @@ -133,7 +136,7 @@ function useVisible(props: DrawerProps) {
}
})

return { loaded, visible: delayedVisible, setVisible, animatedVisible, mergedVisible }
return { loaded, delayedLoaded, visible: delayedVisible, setVisible, animatedVisible, mergedVisible }
}

function useScrollStrategy(props: DrawerProps, mask: ComputedRef<boolean>, mergedVisible: ComputedRef<boolean>) {
Expand Down
47 changes: 25 additions & 22 deletions packages/components/drawer/src/DrawerWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default defineComponent({
config,
mergedPrefixCls,
visible,
delayedLoaded,
animatedVisible,
mergedVisible,
currentZIndex,
Expand Down Expand Up @@ -150,29 +151,31 @@ export default defineComponent({
onAfterEnter={onAfterEnter}
onAfterLeave={onAfterLeave}
>
<div
v-show={visible.value}
role="document"
class={prefixCls}
style={contentStyle.value}
onMousedown={onContentMousedown}
onMouseup={onContentMouseup}
{...attrs}
>
<div ref={sentinelStartRef} tabindex={0} class={`${prefixCls}-sentinel`} aria-hidden={true}></div>
<div class={`${prefixCls}-content`}>
<ɵHeader
v-slots={slots}
closable={closable.value}
closeIcon={closeIcon.value}
header={props.header}
onClose={close}
/>
<div class={`${prefixCls}-body`}>{slots.default?.()}</div>
<ɵFooter v-slots={slots} class={`${prefixCls}-footer`} footer={props.footer}></ɵFooter>
{delayedLoaded.value && (
<div
v-show={visible.value}
role="document"
class={prefixCls}
style={contentStyle.value}
onMousedown={onContentMousedown}
onMouseup={onContentMouseup}
{...attrs}
>
<div ref={sentinelStartRef} tabindex={0} class={`${prefixCls}-sentinel`} aria-hidden={true}></div>
<div class={`${prefixCls}-content`}>
<ɵHeader
v-slots={slots}
closable={closable.value}
closeIcon={closeIcon.value}
header={props.header}
onClose={close}
/>
<div class={`${prefixCls}-body`}>{slots.default?.()}</div>
<ɵFooter v-slots={slots} class={`${prefixCls}-footer`} footer={props.footer}></ɵFooter>
</div>
<div ref={sentinelEndRef} tabindex={0} class={`${prefixCls}-sentinel`} aria-hidden={true}></div>
</div>
<div ref={sentinelEndRef} tabindex={0} class={`${prefixCls}-sentinel`} aria-hidden={true}></div>
</div>
)}
</Transition>
</div>
)
Expand Down
1 change: 1 addition & 0 deletions packages/components/drawer/src/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface DrawerContext {
config: DrawerConfig
mergedPrefixCls: ComputedRef<string>
visible: Ref<boolean>
delayedLoaded: Ref<boolean>
animatedVisible: Ref<boolean | undefined>
mergedVisible: ComputedRef<boolean>
currentZIndex: ComputedRef<number>
Expand Down

0 comments on commit 4e4542b

Please sign in to comment.