Skip to content

Commit 02c4c41

Browse files
author
Tenny
committed
feat(Popover): 完成基础的12个弹出位置
Signed-off-by: Tenny <tenny.shu@foxmail.com>
1 parent 8ad80c8 commit 02c4c41

File tree

3 files changed

+252
-30
lines changed

3 files changed

+252
-30
lines changed

docs/components/popover.md

Lines changed: 138 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
<Button>悬浮</Button>
6060
</template>
6161
</Popover>
62-
<Popover content="点击提示" trigger='click'>
62+
<Popover content="点击提示" trigger='click' placement="bottomRight">
6363
<template #trigger>
6464
<Button>点击</Button>
6565
</template>
@@ -74,42 +74,164 @@
7474

7575
<ClientOnly>
7676
<CodePreview>
77-
<textarea lang="vue">
78-
<script setup>
79-
</script>
80-
<template>
81-
</template>
77+
<textarea lang="vue-html">
78+
<div class="popover-p-row">
79+
<nt-popover content="提示内容" placement="topLeft">
80+
<template #trigger>
81+
<nt-button>topLeft</nt-button>
82+
</template>
83+
</nt-popover>
84+
<nt-popover content="提示内容" placement="top">
85+
<template #trigger>
86+
<nt-button>top</nt-button>
87+
</template>
88+
</nt-popover>
89+
<nt-popover content="提示内容" placement="topRight">
90+
<template #trigger>
91+
<nt-button>topRight</nt-button>
92+
</template>
93+
</nt-popover>
94+
</div>
95+
<div class="popover-p-row">
96+
<nt-popover content="提示内容" placement="leftTop">
97+
<template #trigger>
98+
<nt-button>leftTop</nt-button>
99+
</template>
100+
</nt-popover>
101+
<nt-popover content="提示内容" placement="left">
102+
<template #trigger>
103+
<nt-button>left</nt-button>
104+
</template>
105+
</nt-popover>
106+
<nt-popover content="提示内容" placement="leftBottom">
107+
<template #trigger>
108+
<nt-button>leftBottom</nt-button>
109+
</template>
110+
</nt-popover>
111+
</div>
112+
<div class="popover-p-row">
113+
<nt-popover content="提示内容" placement="rightTop">
114+
<template #trigger>
115+
<nt-button>rightTop</nt-button>
116+
</template>
117+
</nt-popover>
118+
<nt-popover content="提示内容" placement="right">
119+
<template #trigger>
120+
<nt-button>right</nt-button>
121+
</template>
122+
</nt-popover>
123+
<nt-popover content="提示内容" placement="rightBottom">
124+
<template #trigger>
125+
<nt-button>rightBottom</nt-button>
126+
</template>
127+
</nt-popover>
128+
</div>
129+
<div class="popover-p-row">
130+
<nt-popover content="提示内容" placement="bottomLeft">
131+
<template #trigger>
132+
<nt-button>bottomLeft</nt-button>
133+
</template>
134+
</nt-popover>
135+
<nt-popover content="提示内容" placement="bottom">
136+
<template #trigger>
137+
<nt-button>bottom</nt-button>
138+
</template>
139+
</nt-popover>
140+
<nt-popover content="提示内容" placement="bottomRight">
141+
<template #trigger>
142+
<nt-button>bottomRight</nt-button>
143+
</template>
144+
</nt-popover>
145+
</div>
82146
</textarea>
83147
<template #preview>
84148
<div class="popover-p-row">
85-
<Button>topLeft</Button>
149+
<Popover content="提示内容" placement="topLeft">
150+
<template #trigger>
151+
<Button>topLeft</Button>
152+
</template>
153+
</Popover>
86154
<Popover content="提示内容" placement="top">
87155
<template #trigger>
88156
<Button>top</Button>
89157
</template>
90158
</Popover>
91-
<Button>topRight</Button>
159+
<Popover content="提示内容" placement="topRight">
160+
<template #trigger>
161+
<Button>topRight</Button>
162+
</template>
163+
</Popover>
92164
</div>
93165
<div class="popover-p-row">
94-
<Button>leftTop</Button>
95-
<Button>left</Button>
96-
<Button>leftBottom</Button>
166+
<Popover content="提示内容" placement="leftTop">
167+
<template #trigger>
168+
<Button>leftTop</Button>
169+
</template>
170+
</Popover>
171+
<Popover content="提示内容" placement="left">
172+
<template #trigger>
173+
<Button>left</Button>
174+
</template>
175+
</Popover>
176+
<Popover content="提示内容" placement="leftBottom">
177+
<template #trigger>
178+
<Button>leftBottom</Button>
179+
</template>
180+
</Popover>
97181
</div>
98182
<div class="popover-p-row">
99-
<Button>rightTop</Button>
100-
<Button>right</Button>
101-
<Button>rightBottom</Button>
183+
<Popover content="提示内容" placement="rightTop">
184+
<template #trigger>
185+
<Button>rightTop</Button>
186+
</template>
187+
</Popover>
188+
<Popover content="提示内容" placement="right">
189+
<template #trigger>
190+
<Button>right</Button>
191+
</template>
192+
</Popover>
193+
<Popover content="提示内容" placement="rightBottom">
194+
<template #trigger>
195+
<Button>rightBottom</Button>
196+
</template>
197+
</Popover>
102198
</div>
103199
<div class="popover-p-row">
104-
<Button>bottomLeft</Button>
200+
<Popover content="提示内容" placement="bottomLeft">
201+
<template #trigger>
202+
<Button>bottomLeft</Button>
203+
</template>
204+
</Popover>
105205
<Popover content="提示内容" placement="bottom">
106206
<template #trigger>
107207
<Button>bottom</Button>
108208
</template>
109209
</Popover>
110-
<Button>bottomRight</Button>
210+
<Popover content="提示内容" placement="bottomRight">
211+
<template #trigger>
212+
<Button>bottomRight</Button>
213+
</template>
214+
</Popover>
111215
</div>
216+
</template>
217+
</CodePreview>
218+
</ClientOnly>
219+
220+
### 受控模式
221+
222+
不需要自动弹出,需要进行手动控制是否展示;通过传递 `open` 属性设置是否展示,然后设置 `to` 属性指向弹层对标节点。
112223

224+
<ClientOnly>
225+
<CodePreview>
226+
<textarea lang="vue-html">
227+
<script setup>
228+
</script>
229+
<template>
230+
<hr />
231+
</template>
232+
</textarea>
233+
<template #preview>
234+
console.log()
113235
</template>
114236
</CodePreview>
115237
</ClientOnly>

src/components/Popover.vue

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,18 @@ export default defineComponent({
4343
/** 弹出位置 */
4444
placement: {
4545
type: String as PropType<
46-
'topStart' | 'top' | 'topEnd' | 'bottomStart' | 'bottom' | 'bottomEnd'
46+
| 'topLeft'
47+
| 'top'
48+
| 'topRight'
49+
| 'bottomLeft'
50+
| 'bottom'
51+
| 'bottomRight'
52+
| 'left'
53+
| 'leftTop'
54+
| 'leftBottom'
55+
| 'right'
56+
| 'rightTop'
57+
| 'rightBottom'
4758
>,
4859
default: 'top',
4960
},
@@ -70,12 +81,37 @@ export default defineComponent({
7081
if ($popover.value != null) {
7182
const popoverRect = $popover.value.getBoundingClientRect();
7283
const targetRect = $target.getBoundingClientRect();
73-
if (props.placement === 'top') {
84+
if (props.placement.startsWith('top')) {
7485
offsetTop = popoverRect.height + 10;
75-
} else if (props.placement === 'bottom') {
86+
} else if (props.placement.startsWith('bottom')) {
7687
offsetTop = -(targetRect.height + 10);
88+
} else if (
89+
props.placement === 'left' ||
90+
props.placement === 'right'
91+
) {
92+
offsetTop = popoverRect.height / 2 - targetRect.height / 2;
93+
} else if (
94+
props.placement === 'leftBottom' ||
95+
props.placement === 'rightBottom'
96+
) {
97+
offsetTop = popoverRect.height - targetRect.height;
98+
}
99+
100+
if (props.placement.startsWith('left')) {
101+
offsetLeft = popoverRect.width + 10;
102+
} else if (props.placement.startsWith('right')) {
103+
offsetLeft = -(targetRect.width + 10);
104+
} else if (
105+
props.placement === 'top' ||
106+
props.placement === 'bottom'
107+
) {
108+
offsetLeft = popoverRect.width / 2 - targetRect.width / 2;
109+
} else if (
110+
props.placement === 'bottomRight' ||
111+
props.placement === 'topRight'
112+
) {
113+
offsetLeft = popoverRect.width - targetRect.width;
77114
}
78-
offsetLeft = popoverRect.width / 2 - targetRect.width / 2;
79115
}
80116
posStyle.value = {
81117
top: `${top - offsetTop}px`,

style/popover/index.css

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
width: 8px;
1717
height: 8px;
1818
z-index: -1;
19-
left: 50%;
20-
margin-left: -4px;
2119
}
2220

2321
.nt-popover-arrow::before {
@@ -31,20 +29,86 @@
3129
border-style: solid;
3230
}
3331

34-
/* top */
35-
.nt-popover-top .nt-popover-arrow {
36-
bottom: -4px;
32+
.nt-popover-top .nt-popover-arrow,
33+
.nt-popover-bottom .nt-popover-arrow {
34+
left: 50%;
35+
margin-left: -4px;
3736
}
38-
.nt-popover-top .nt-popover-arrow::before {
37+
38+
.nt-popover-top .nt-popover-arrow::before,
39+
.nt-popover-topLeft .nt-popover-arrow::before,
40+
.nt-popover-topRight .nt-popover-arrow::before {
3941
border-color: transparent var(--nt-popover-border-color)
4042
var(--nt-popover-border-color) transparent;
4143
}
44+
.nt-popover-bottom .nt-popover-arrow::before,
45+
.nt-popover-bottomLeft .nt-popover-arrow::before,
46+
.nt-popover-bottomRight .nt-popover-arrow::before {
47+
border-color: var(--nt-popover-border-color) transparent transparent
48+
var(--nt-popover-border-color);
49+
}
4250

43-
/* bottom */
44-
.nt-popover-bottom .nt-popover-arrow {
51+
.nt-popover-top .nt-popover-arrow,
52+
.nt-popover-topLeft .nt-popover-arrow,
53+
.nt-popover-topRight .nt-popover-arrow {
54+
bottom: -4px;
55+
}
56+
57+
.nt-popover-topLeft .nt-popover-arrow,
58+
.nt-popover-bottomLeft .nt-popover-arrow {
59+
left: 10px;
60+
}
61+
.nt-popover-topRight .nt-popover-arrow,
62+
.nt-popover-bottomRight .nt-popover-arrow {
63+
right: 7px;
64+
}
65+
66+
.nt-popover-bottom .nt-popover-arrow,
67+
.nt-popover-bottomLeft .nt-popover-arrow,
68+
.nt-popover-bottomRight .nt-popover-arrow {
4569
top: -4px;
4670
}
47-
.nt-popover-bottom .nt-popover-arrow::before {
48-
border-color: var(--nt-popover-border-color) transparent transparent
71+
72+
/* left-right */
73+
74+
.nt-popover-left .nt-popover-arrow,
75+
.nt-popover-leftTop .nt-popover-arrow,
76+
.nt-popover-leftBottom .nt-popover-arrow {
77+
margin-top: -4px;
78+
right: -4px;
79+
}
80+
81+
.nt-popover-leftTop .nt-popover-arrow::before,
82+
.nt-popover-left .nt-popover-arrow::before,
83+
.nt-popover-leftBottom .nt-popover-arrow::before {
84+
border-color: var(--nt-popover-border-color) var(--nt-popover-border-color)
85+
transparent transparent;
86+
}
87+
88+
.nt-popover-right .nt-popover-arrow,
89+
.nt-popover-rightTop .nt-popover-arrow,
90+
.nt-popover-rightBottom .nt-popover-arrow {
91+
margin-top: -4px;
92+
left: -4px;
93+
}
94+
.nt-popover-rightTop .nt-popover-arrow::before,
95+
.nt-popover-right .nt-popover-arrow::before,
96+
.nt-popover-rightBottom .nt-popover-arrow::before {
97+
border-color: transparent transparent var(--nt-popover-border-color)
4998
var(--nt-popover-border-color);
5099
}
100+
101+
.nt-popover-left .nt-popover-arrow,
102+
.nt-popover-right .nt-popover-arrow {
103+
top: 50%;
104+
}
105+
106+
.nt-popover-leftTop .nt-popover-arrow,
107+
.nt-popover-rightTop .nt-popover-arrow {
108+
top: 10px;
109+
}
110+
111+
.nt-popover-leftBottom .nt-popover-arrow,
112+
.nt-popover-rightBottom .nt-popover-arrow {
113+
bottom: 10px;
114+
}

0 commit comments

Comments
 (0)