Skip to content

Commit

Permalink
fix(comp:*): opening overlay once triggers two zIndex changes (#1355)
Browse files Browse the repository at this point in the history
  • Loading branch information
danranVm committed Dec 14, 2022
1 parent 107c03e commit 7cec4ec
Show file tree
Hide file tree
Showing 17 changed files with 46 additions and 70 deletions.
7 changes: 5 additions & 2 deletions packages/components/_private/overlay/src/Overlay.tsx
Expand Up @@ -22,6 +22,8 @@ import {
withDirectives,
} from 'vue'

import { isFunction } from 'lodash-es'

import { vClickOutside } from '@idux/cdk/click-outside'
import { type PopperElement, type PopperEvents, type PopperOptions, usePopper } from '@idux/cdk/popper'
import { CdkPortal } from '@idux/cdk/portal'
Expand Down Expand Up @@ -59,7 +61,8 @@ export default defineComponent({
const { destroy: popperDestroy } = usePopperInit(props, initialize, destroy)
const currentZIndex = useZIndex(toRef(props, 'zIndex'), toRef(common, 'overlayZIndex'), visibility)
const mergedContainer = computed(() => {
return () => props.container(convertElement(triggerRef)!)
const { container = common.overlayContainer } = props
return (isFunction(container) ? container(convertElement(triggerRef)!) : container) ?? props.containerFallback
})

watch(visibility, value => callEmit(props['onUpdate:visible'], value))
Expand Down Expand Up @@ -221,7 +224,7 @@ function renderContent(
}
const prefixCls = mergedPrefixCls.value
const { triggerId } = props
const overlayId = triggerId != null ? `overlay-${triggerId}` : undefined
const overlayId = triggerId != null ? `__IDUX_OVERLAY-${triggerId}` : undefined
const style = `z-index: ${currentZIndex.value}`
const overlay = (
<div ref={popperRef} id={overlayId} class={prefixCls} style={style} {...popperEvents.value} {...attrs}>
Expand Down
10 changes: 8 additions & 2 deletions packages/components/_private/overlay/src/types.ts
Expand Up @@ -7,6 +7,7 @@

import type { PopperOptions, PopperPlacement, PopperTrigger } from '@idux/cdk/popper'
import type { ExtractInnerPropTypes, ExtractPublicPropTypes, MaybeArray } from '@idux/cdk/utils'
import type { OverlayContainerType } from '@idux/components/utils'
import type { DefineComponent, HTMLAttributes, PropType } from 'vue'

export const overlayPlacementDef = String as PropType<PopperPlacement>
Expand All @@ -18,6 +19,8 @@ export const overlayProps = {
type: Boolean,
default: undefined,
},
placement: overlayPlacementDef,

allowEnter: {
type: Boolean,
default: undefined,
Expand All @@ -31,7 +34,11 @@ export const overlayProps = {
default: undefined,
},
container: {
type: Function as PropType<(element?: Element) => string | HTMLElement>,
type: [String, HTMLElement, Function] as PropType<OverlayContainerType>,
default: undefined,
},
containerFallback: {
type: String,
required: true,
},
delay: overlayDelayDef,
Expand All @@ -44,7 +51,6 @@ export const overlayProps = {
default: undefined,
},
offset: Array as unknown as PropType<[number, number]>,
placement: overlayPlacementDef,
showArrow: {
type: Boolean,
default: undefined,
Expand Down
6 changes: 3 additions & 3 deletions packages/components/cascader/src/Cascader.tsx
Expand Up @@ -14,7 +14,7 @@ import { ɵSelector, type ɵSelectorInstance } from '@idux/components/_private/s
import { useGlobalConfig } from '@idux/components/config'
import { useFormItemRegister, useFormSize, useFormStatus } from '@idux/components/form'
import { ɵUseOverlayState } from '@idux/components/select'
import { useGetKey, useOverlayContainer } from '@idux/components/utils'
import { useGetKey } from '@idux/components/utils'

import { useActiveState } from './composables/useActiveState'
import { useDataSource } from './composables/useDataSource'
Expand All @@ -35,7 +35,6 @@ export default defineComponent({
const common = useGlobalConfig('common')
const config = useGlobalConfig('cascader')
const mergedPrefixCls = computed(() => `${common.prefixCls}-cascader`)
const mergedOverlayContainer = useOverlayContainer(props, config, common, mergedPrefixCls)

const mergedChildrenKey = computed(() => props.childrenKey ?? config.childrenKey)
const mergedClearIcon = computed(() => props.clearIcon ?? config.clearIcon)
Expand Down Expand Up @@ -175,7 +174,8 @@ export default defineComponent({
const overlayProps = {
class: overlayClasses.value,
clickOutside: true,
container: mergedOverlayContainer.value,
container: props.overlayContainer ?? config.overlayContainer,
containerFallback: `.${mergedPrefixCls.value}-overlay-container`,
disabled: accessor.disabled || props.readonly,
offset: defaultOffset,
placement: 'bottomStart',
Expand Down
Expand Up @@ -8,18 +8,17 @@
import { type ComputedRef, computed } from 'vue'

import { type ɵOverlayProps } from '@idux/components/_private/overlay'
import { useOverlayContainer } from '@idux/components/utils'

import { type DatePickerContext, type DateRangePickerContext } from '../token'

const defaultOffset: [number, number] = [0, 4]
export function useOverlayProps(context: DatePickerContext | DateRangePickerContext): ComputedRef<ɵOverlayProps> {
const { props, common, config, accessor, mergedPrefixCls, overlayOpened, setOverlayOpened, onAfterLeave } = context
const mergedOverlayContainer = useOverlayContainer(props, config, common, mergedPrefixCls)
return computed(() => {
return {
clickOutside: true,
container: mergedOverlayContainer.value,
container: props.overlayContainer ?? config.overlayContainer,
containerFallback: `.${mergedPrefixCls.value}-overlay-container`,
disabled: accessor.disabled || props.readonly,
offset: defaultOffset,
placement: 'bottomStart',
Expand Down
5 changes: 2 additions & 3 deletions packages/components/dropdown/src/Dropdown.tsx
Expand Up @@ -10,7 +10,6 @@ import { computed, defineComponent, provide, toRef } from 'vue'
import { useControlledProp } from '@idux/cdk/utils'
import { ɵOverlay } from '@idux/components/_private/overlay'
import { type DropdownConfig, useGlobalConfig } from '@idux/components/config'
import { useOverlayContainer } from '@idux/components/utils'

import { dropdownToken } from './token'
import { type DropdownProps, dropdownProps } from './types'
Expand All @@ -24,7 +23,6 @@ export default defineComponent({
const common = useGlobalConfig('common')
const config = useGlobalConfig('dropdown')
const mergedPrefixCls = computed(() => `${common.prefixCls}-dropdown`)
const mergedOverlayContainer = useOverlayContainer(props, config, common, mergedPrefixCls)

const [visibility, setVisibility] = useControlledProp(props, 'visible', false)
const configProps = useConfigProps(props, config, setVisibility)
Expand All @@ -37,7 +35,8 @@ export default defineComponent({
visible={visibility.value}
v-slots={{ default: slots.default, content: slots.overlay }}
class={mergedPrefixCls.value}
container={mergedOverlayContainer.value}
container={props.overlayContainer ?? config.overlayContainer}
containerFallback={`.${mergedPrefixCls.value}-overlay-container`}
delay={defaultDelay}
disabled={props.disabled}
transitionName={`${common.prefixCls}-fade`}
Expand Down
7 changes: 4 additions & 3 deletions packages/components/menu/src/contents/menu-sub/MenuSub.tsx
Expand Up @@ -23,7 +23,7 @@ import { debounce } from 'lodash-es'
import { type VKey, useState } from '@idux/cdk/utils'
import { ɵOverlay } from '@idux/components/_private/overlay'
import { useGlobalConfig } from '@idux/components/config'
import { useKey, useOverlayContainer } from '@idux/components/utils'
import { useKey } from '@idux/components/utils'

import { usePaddingLeft } from '../../composables/usePaddingLeft'
import { type MenuSubContext, menuItemGroupToken, menuSubToken, menuToken } from '../../token'
Expand Down Expand Up @@ -53,7 +53,7 @@ export default defineComponent({
const menuItemGroupContext = inject(menuItemGroupToken, false)

const key = useKey()
const mergedOverlayContainer = useOverlayContainer(menuProps, config, common, mergedPrefixCls)

const mode = useMode(menuProps, menuSubContext)
const level = menuSubContext ? menuSubContext.level + 1 : 1
const paddingLeft = usePaddingLeft(menuProps, mode, indent, level, menuItemGroupContext)
Expand Down Expand Up @@ -117,7 +117,8 @@ export default defineComponent({
v-slots={{ default: trigger, content: content }}
class={overlayClasses.value}
autoAdjust
container={mergedOverlayContainer.value}
container={menuProps.overlayContainer ?? config.overlayContainer}
containerFallback={`.${mergedPrefixCls.value}-overlay-container`}
destroyOnHide={false}
delay={menuProps.overlayDelay}
disabled={disabled}
Expand Down
1 change: 0 additions & 1 deletion packages/components/popconfirm/src/Popconfirm.tsx
Expand Up @@ -27,7 +27,6 @@ export default defineComponent({
const { overlayRef, updatePopper, visible, setVisible, overlayProps } = ɵUseTooltipOverlay(
props,
config,
common,
mergedPrefixCls,
)

Expand Down
7 changes: 1 addition & 6 deletions packages/components/popover/src/Popover.tsx
Expand Up @@ -23,12 +23,7 @@ export default defineComponent({
const common = useGlobalConfig('common')
const config = useGlobalConfig('popover')
const mergedPrefixCls = computed(() => `${common.prefixCls}-popover`)
const { overlayRef, updatePopper, overlayProps, setVisible } = ɵUseTooltipOverlay(
props,
config,
common,
mergedPrefixCls,
)
const { overlayRef, updatePopper, overlayProps, setVisible } = ɵUseTooltipOverlay(props, config, mergedPrefixCls)

expose({ updatePopper })

Expand Down
5 changes: 2 additions & 3 deletions packages/components/select/src/Select.tsx
Expand Up @@ -17,7 +17,6 @@ import { ɵOverlay } from '@idux/components/_private/overlay'
import { ɵSelector, type ɵSelectorInstance } from '@idux/components/_private/selector'
import { type SelectConfig, useGlobalConfig } from '@idux/components/config'
import { useFormItemRegister, useFormSize, useFormStatus } from '@idux/components/form'
import { useOverlayContainer } from '@idux/components/utils'

import { useActiveState } from './composables/useActiveState'
import { GetKeyFn, useGetOptionKey } from './composables/useGetOptionKey'
Expand All @@ -38,7 +37,6 @@ export default defineComponent({
const common = useGlobalConfig('common')
const config = useGlobalConfig('select')
const mergedPrefixCls = computed(() => `${common.prefixCls}-select`)
const mergedOverlayContainer = useOverlayContainer(props, config, common, mergedPrefixCls)

const triggerRef = ref<ɵSelectorInstance>()
const focus = () => triggerRef.value?.focus()
Expand Down Expand Up @@ -196,7 +194,8 @@ export default defineComponent({
class: overlayClasses.value,
style: overlayStyle.value,
clickOutside: true,
container: mergedOverlayContainer.value,
container: props.overlayContainer ?? config.overlayContainer,
containerFallback: `.${mergedPrefixCls.value}-overlay-container`,
disabled: accessor.disabled || props.readonly,
offset: props.offset ?? config.offset,
placement: 'bottomStart',
Expand Down
Expand Up @@ -9,18 +9,17 @@ import type { ɵOverlayProps } from '@idux/components/_private/overlay'

import { type ComputedRef, computed } from 'vue'

import { useOverlayContainer } from '@idux/components/utils'

import { TimePickerContext, TimeRangePickerContext } from '../tokens'

const defaultOffset: [number, number] = [0, 4]
export function useOverlayProps(context: TimePickerContext | TimeRangePickerContext): ComputedRef<ɵOverlayProps> {
const { props, common, config, accessor, mergedPrefixCls, overlayOpened, setOverlayOpened } = context
const mergedOverlayContainer = useOverlayContainer(props, config, common, mergedPrefixCls)

return computed(() => {
return {
clickOutside: true,
container: mergedOverlayContainer.value,
container: props.overlayContainer ?? config.overlayContainer,
containerFallback: `.${mergedPrefixCls.value}-overlay-container`,
disabled: accessor.disabled || props.readonly,
offset: defaultOffset,
placement: 'bottomStart',
Expand Down
2 changes: 1 addition & 1 deletion packages/components/tooltip/src/Tooltip.tsx
Expand Up @@ -23,7 +23,7 @@ export default defineComponent({
const common = useGlobalConfig('common')
const config = useGlobalConfig('tooltip')
const mergedPrefixCls = computed(() => `${common.prefixCls}-tooltip`)
const { overlayRef, updatePopper, overlayProps } = useTooltipOverlay(props, config, common, mergedPrefixCls)
const { overlayRef, updatePopper, overlayProps } = useTooltipOverlay(props, config, mergedPrefixCls)
expose({ updatePopper })

return () => {
Expand Down
14 changes: 5 additions & 9 deletions packages/components/tooltip/src/useTooltipOverlay.ts
Expand Up @@ -5,12 +5,11 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import { type ComputedRef, type Ref, computed, onDeactivated, ref, toRef } from 'vue'
import { type ComputedRef, type Ref, computed, onDeactivated, ref } from 'vue'

import { useControlledProp } from '@idux/cdk/utils'
import { type ɵOverlayInstance, type ɵOverlayProps } from '@idux/components/_private/overlay'
import { type CommonConfig, type TooltipConfig } from '@idux/components/config'
import { useOverlayContainer, useZIndex } from '@idux/components/utils'
import { type TooltipConfig } from '@idux/components/config'

import { type TooltipProps } from './types'

Expand All @@ -25,16 +24,12 @@ export interface TooltipOverlayContext {
export function useTooltipOverlay(
props: TooltipProps,
config: TooltipConfig,
common: CommonConfig,
mergedPrefixCls: ComputedRef<string>,
): TooltipOverlayContext {
const overlayRef = ref<ɵOverlayInstance>()
const updatePopper = () => overlayRef.value?.updatePopper()

const mergedOverlayContainer = useOverlayContainer(props, config, common, mergedPrefixCls)

const [visible, setVisible] = useControlledProp(props, 'visible', false)
const currentZIndex = useZIndex(toRef(props, 'zIndex'), toRef(common, 'overlayZIndex'), visible)

onDeactivated(() => {
if (visible.value && props.closeOnDeactivated) {
Expand All @@ -49,15 +44,16 @@ export function useTooltipOverlay(
['onUpdate:visible']: setVisible,
autoAdjust: props.autoAdjust ?? config.autoAdjust,
clickOutside: trigger === 'click' || trigger === 'contextmenu',
container: mergedOverlayContainer.value,
container: props.overlayContainer ?? config.overlayContainer,
containerFallback: `.${mergedPrefixCls.value}-overlay-container`,
delay: props.delay ?? config.delay,
destroyOnHide: props.destroyOnHide ?? config.destroyOnHide,
disabled: props.disabled,
offset: props.offset ?? config.offset,
showArrow: true,
placement: props.placement ?? config.placement,
trigger: trigger,
zIndex: currentZIndex.value,
zIndex: props.zIndex,
}
})
return { overlayRef, updatePopper, visible, setVisible, overlayProps }
Expand Down
6 changes: 3 additions & 3 deletions packages/components/tree-select/src/TreeSelect.tsx
Expand Up @@ -16,7 +16,7 @@ import { useGlobalConfig } from '@idux/components/config'
import { useFormItemRegister, useFormSize, useFormStatus } from '@idux/components/form'
import { ɵUseOverlayState } from '@idux/components/select'
import { type TreeInstance } from '@idux/components/tree'
import { useGetKey, useOverlayContainer } from '@idux/components/utils'
import { useGetKey } from '@idux/components/utils'

import { useMergeNodes } from './composables/useDataSource'
import { useSelectedState } from './composables/useSelectedState'
Expand All @@ -33,7 +33,6 @@ export default defineComponent({
const locale = useGlobalConfig('locale')
const config = useGlobalConfig('treeSelect')
const mergedPrefixCls = computed(() => `${common.prefixCls}-tree-select`)
const mergedOverlayContainer = useOverlayContainer(props, config, common, mergedPrefixCls)
const mergedChildrenKey = computed(() => props.childrenKey ?? config.childrenKey)
const mergedGetKey = useGetKey(props, config, 'components/tree-select')
const mergedLabelKey = computed(() => props.labelKey ?? config.labelKey)
Expand Down Expand Up @@ -180,7 +179,8 @@ export default defineComponent({
class: overlayClasses.value,
style: overlayStyle.value,
clickOutside: true,
container: mergedOverlayContainer.value,
container: props.overlayContainer ?? config.overlayContainer,
containerFallback: `.${mergedPrefixCls.value}-overlay-container`,
disabled: accessor.disabled || props.readonly,
offset: props.offset ?? config.offset,
placement: 'bottomStart',
Expand Down
21 changes: 2 additions & 19 deletions packages/components/utils/src/portalTarget.ts
Expand Up @@ -27,26 +27,9 @@ export function usePortalTarget(
config: ContainerProps,
common: { overlayContainer?: OverlayContainerType },
mergedPrefix: ComputedRef<string>,
): ComputedRef<() => string | HTMLElement> {
): ComputedRef<string | HTMLElement> {
return computed(() => {
const container = props.container ?? config.container ?? common.overlayContainer
return () => (isFunction(container) ? container() : container) ?? `.${mergedPrefix.value}-container`
})
}

interface OverlayContainerProps {
overlayContainer?: OverlayContainerType
}

export function useOverlayContainer(
props: OverlayContainerProps,
config: OverlayContainerProps,
common: { overlayContainer?: OverlayContainerType },
mergedPrefix: ComputedRef<string>,
): ComputedRef<(element?: Element) => string | HTMLElement> {
return computed(() => {
const container = props.overlayContainer ?? config.overlayContainer ?? common.overlayContainer
return element =>
(isFunction(container) ? container(element) : container) ?? `.${mergedPrefix.value}-overlay-container`
return (isFunction(container) ? container() : container) ?? `.${mergedPrefix.value}-container`
})
}
4 changes: 2 additions & 2 deletions packages/components/utils/src/zIndex.ts
Expand Up @@ -7,7 +7,7 @@

import { type ComputedRef, type Ref, computed, ref, watch } from 'vue'

import { isFunction } from 'lodash-es'
import { isFunction, isNil } from 'lodash-es'

let zIndexCount = 0

Expand All @@ -31,7 +31,7 @@ export const useZIndex: UseZIndex = (controlZIndex, configZIndex, visible) => {
watch(
visible,
newVisible => {
if (newVisible) {
if (newVisible && isNil(controlZIndex.value)) {
innerZIndex.value = getZIndex()
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/pro/search/src/ProSearch.tsx
Expand Up @@ -55,7 +55,7 @@ export default defineComponent({
searchItems,
searchStateContext.tempSearchStateAvailable,
)
const commonOverlayProps = useCommonOverlayProps(props, config, componentCommon, mergedPrefixCls)
const commonOverlayProps = useCommonOverlayProps(props, config, mergedPrefixCls)
const { focused, focus, blur } = useFocusedState(
props,
elementRef,
Expand Down

0 comments on commit 7cec4ec

Please sign in to comment.