Files
element-plus/packages/components/tooltip/src/tooltip.vue
qiang 0109ab6195 fix(components): [select] abnormal focus when click tags (#13699)
* fix(components): [select] abnormal focus when click tags

closed #13665

* fix(components): [select] clearable

* chore(components): [select] remove console

* fix: the setTimeout function may bring some side effects

* fix: remove role

* test(components): [select] add some test
2023-08-03 20:15:57 +08:00

198 lines
4.6 KiB
Vue

<template>
<el-popper ref="popperRef" :role="role">
<el-tooltip-trigger
:disabled="disabled"
:trigger="trigger"
:trigger-keys="triggerKeys"
:virtual-ref="virtualRef"
:virtual-triggering="virtualTriggering"
>
<slot v-if="$slots.default" />
</el-tooltip-trigger>
<el-tooltip-content
ref="contentRef"
:aria-label="ariaLabel"
:boundaries-padding="boundariesPadding"
:content="content"
:disabled="disabled"
:effect="effect"
:enterable="enterable"
:fallback-placements="fallbackPlacements"
:hide-after="hideAfter"
:gpu-acceleration="gpuAcceleration"
:offset="offset"
:persistent="persistent"
:popper-class="popperClass"
:popper-style="popperStyle"
:placement="placement"
:popper-options="popperOptions"
:pure="pure"
:raw-content="rawContent"
:reference-el="referenceEl"
:trigger-target-el="triggerTargetEl"
:show-after="showAfter"
:strategy="strategy"
:teleported="teleported"
:transition="transition"
:virtual-triggering="virtualTriggering"
:z-index="zIndex"
:append-to="appendTo"
>
<slot name="content">
<span v-if="rawContent" v-html="content" />
<span v-else>{{ content }}</span>
</slot>
<el-popper-arrow v-if="showArrow" :arrow-offset="arrowOffset" />
</el-tooltip-content>
</el-popper>
</template>
<script lang="ts" setup>
import {
computed,
onDeactivated,
provide,
readonly,
ref,
toRef,
unref,
watch,
} from 'vue'
import { ElPopper, ElPopperArrow } from '@element-plus/components/popper'
import { isBoolean } from '@element-plus/utils'
import {
useDelayedToggle,
useId,
usePopperContainer,
} from '@element-plus/hooks'
import { TOOLTIP_INJECTION_KEY } from './constants'
import { tooltipEmits, useTooltipModelToggle, useTooltipProps } from './tooltip'
import ElTooltipTrigger from './trigger.vue'
import ElTooltipContent from './content.vue'
import type { PopperInstance } from '@element-plus/components/popper'
defineOptions({
name: 'ElTooltip',
})
const props = defineProps(useTooltipProps)
const emit = defineEmits(tooltipEmits)
usePopperContainer()
const id = useId()
const popperRef = ref<PopperInstance>()
// TODO any is temporary, replace with `TooltipContentInstance` later
const contentRef = ref<any>()
const updatePopper = () => {
const popperComponent = unref(popperRef)
if (popperComponent) {
popperComponent.popperInstanceRef?.update()
}
}
const open = ref(false)
const toggleReason = ref<Event>()
const { show, hide, hasUpdateHandler } = useTooltipModelToggle({
indicator: open,
toggleReason,
})
const { onOpen, onClose } = useDelayedToggle({
showAfter: toRef(props, 'showAfter'),
hideAfter: toRef(props, 'hideAfter'),
autoClose: toRef(props, 'autoClose'),
open: show,
close: hide,
})
const controlled = computed(
() => isBoolean(props.visible) && !hasUpdateHandler.value
)
provide(TOOLTIP_INJECTION_KEY, {
controlled,
id,
open: readonly(open),
trigger: toRef(props, 'trigger'),
onOpen: (event?: Event) => {
onOpen(event)
},
onClose: (event?: Event) => {
onClose(event)
},
onToggle: (event?: Event) => {
if (unref(open)) {
onClose(event)
} else {
onOpen(event)
}
},
onShow: () => {
emit('show', toggleReason.value)
},
onHide: () => {
emit('hide', toggleReason.value)
},
onBeforeShow: () => {
emit('before-show', toggleReason.value)
},
onBeforeHide: () => {
emit('before-hide', toggleReason.value)
},
updatePopper,
})
watch(
() => props.disabled,
(disabled) => {
if (disabled && open.value) {
open.value = false
}
}
)
const isFocusInsideContent = (event?: FocusEvent) => {
const popperContent: HTMLElement | undefined =
contentRef.value?.contentRef?.popperContentRef
const activeElement = (event?.relatedTarget as Node) || document.activeElement
return popperContent && popperContent.contains(activeElement)
}
onDeactivated(() => open.value && hide())
defineExpose({
/**
* @description el-popper component instance
*/
popperRef,
/**
* @description el-tooltip-content component instance
*/
contentRef,
/**
* @description validate current focus event is trigger inside el-tooltip-content
*/
isFocusInsideContent,
/**
* @description update el-popper component instance
*/
updatePopper,
/**
* @description expose onOpen function to mange el-tooltip open state
*/
onOpen,
/**
* @description expose onOpen function to mange el-tooltip open state
*/
onClose,
/**
* @description expose hide function
*/
hide,
})
</script>