Skip to content

Commit 98ba6c4

Browse files
author
Tenny
committed
feat: Popover 样式完成
Signed-off-by: Tenny <joel.shu@qq.com>
1 parent 2045681 commit 98ba6c4

File tree

4 files changed

+86
-15
lines changed

4 files changed

+86
-15
lines changed

docs/components/popover.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
</template>
2626
</textarea>
2727
<template #preview>
28-
<Popover>
29-
<Button @click="click1">悬浮</Button>
28+
<Popover content="Content">
29+
<template #trigger>
30+
<Button @click="click1">悬浮</Button>
31+
</template>
3032
</Popover>
3133
</template>
3234
</CodePreview>

src/components/Popover.vue

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,51 @@
11
<script lang="ts">
2-
import { defineComponent, h, VNode } from 'vue';
2+
import { defineComponent, h, VNode, Teleport, ref, Transition } from 'vue';
33
import type { PropType } from 'vue';
44
5-
function getFirstSlotVNode(vnodes?: VNode[]) {
6-
if (vnodes != null) {
7-
return vnodes[0];
5+
function getFirstTriggerVNode(slots: any): VNode | null {
6+
if (slots.trigger != null) {
7+
return slots.trigger()[0];
88
}
99
return null;
1010
}
1111
1212
export default defineComponent({
1313
props: {
14+
/** 触发方式: hover - 渲染, click - 点击 */
1415
trigger: {
1516
type: String as PropType<'hover' | 'click'>,
1617
default: 'hover',
1718
},
19+
/** 显示的内容,也可以通过写入默认 slot 修改显示内容 */
20+
content: String,
1821
},
19-
setup(props, { slots }) {
22+
setup(props, { slots, attrs }) {
23+
const show = ref(false);
24+
const posStyle = ref({});
25+
2026
function handleMouseEnter(e: Event) {
21-
console.log('mouseenter');
27+
const $target = e.target as HTMLElement;
28+
const rect = $target.getBoundingClientRect();
29+
console.log(rect);
30+
console.log($target.offsetParent.getBoundingClientRect());
31+
posStyle.value = {
32+
top: 500 + 'px',
33+
left: `${rect.left}px`,
34+
};
35+
show.value = true;
2236
}
2337
24-
function hanldeMouseLeave(e: Event) {
25-
console.log('mouseleave');
38+
/** 鼠标离开事件 */
39+
function hanldeMouseLeave() {
40+
show.value = false;
2641
}
2742
2843
function handleClick(e: Event) {
2944
console.log('click');
3045
}
3146
3247
return () => {
33-
const firstVNode = getFirstSlotVNode(
34-
slots.default != null ? slots.default() : undefined,
35-
);
48+
const firstVNode = getFirstTriggerVNode(slots);
3649
if (firstVNode == null) {
3750
return null;
3851
}
@@ -43,7 +56,38 @@ export default defineComponent({
4356
} else {
4457
prop.onClick = handleClick;
4558
}
46-
return h('div', h(firstVNode, prop));
59+
return [
60+
h(firstVNode, prop),
61+
h(
62+
Teleport,
63+
{ to: 'body' },
64+
h(
65+
Transition,
66+
{ name: 'nt-opacity' },
67+
{
68+
default: () =>
69+
show.value
70+
? h(
71+
'div',
72+
{
73+
...attrs,
74+
class: ['nt-popover', attrs.class],
75+
style: [posStyle.value],
76+
},
77+
[
78+
slots.default != null
79+
? slots.default()
80+
: props.content != null
81+
? h('span', props.content)
82+
: null,
83+
h('span', { class: 'nt-popover-arrow' }),
84+
],
85+
)
86+
: null,
87+
},
88+
),
89+
),
90+
];
4791
};
4892
},
4993
});

style/popover/index.css

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.nt-popover {
2+
--nt-popover-border-color: #e4e4e4;
3+
position: absolute;
4+
top: 264px;
5+
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.12);
6+
background: #ffffff;
7+
border: 1px solid var(--nt-popover-border-color);
8+
border-radius: 4px;
9+
padding: 10px;
10+
z-index: 30;
11+
color: #666666;
12+
box-sizing: border-box;
13+
}
14+
15+
.nt-popover-arrow {
16+
position: absolute;
17+
border-width: 6px;
18+
border-style: solid;
19+
left: 50%;
20+
margin-left: -5px;
21+
top: 100%;
22+
border-color: var(--nt-popover-border-color) transparent transparent
23+
transparent;
24+
}

style/popover/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
import "./index.css";
1+
import '../util/transition.css';
2+
import './index.css';

0 commit comments

Comments
 (0)