Skip to content

Commit 337b365

Browse files
pieeryyx990803
authored andcommitted
Add vuemastery banner (#1825)
1 parent 9028c70 commit 337b365

File tree

7 files changed

+990
-2
lines changed

7 files changed

+990
-2
lines changed
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
<template>
2+
<div id="vm-banner" class="vuemastery-banner" role="banner" v-if="isVisible">
3+
<a
4+
id="vs"
5+
href="https://www.vuemastery.com/free-weekend"
6+
target="_blank"
7+
rel="noreferrer"
8+
role="banner"
9+
>
10+
<div class="vuemastery-banner--wrapper">
11+
<img class="vuemastery-banner--logo" src="/images/vuemastery/logo-vuemastery.svg" alt="vuemastery" />
12+
<p>Access the highest quality library of Vue courses free<span>July 22-24 only</span></p>
13+
<button class="vuemastery-button">Secure a spot</button>
14+
</div>
15+
<div id="vm-close" class="vuemastery-banner--close"></div>
16+
</a>
17+
</div>
18+
</template>
19+
20+
<script setup>
21+
import { ref, onMounted } from 'vue'
22+
23+
const isVisible = ref(false)
24+
25+
onMounted(() => {
26+
const now = new Date()
27+
const end = new Date('2022-07-24T00:00:00+02:00')
28+
isVisible.value = !localStorage.getItem('VM_FW_22_OFFER') && (now < end)
29+
if (isVisible.value) document.body.classList.add('has-top-banner')
30+
})
31+
32+
function close () {
33+
isVisible.value = false
34+
document.body.classList.remove('has-top-banner')
35+
localStorage.setItem('VM_FW_22_OFFER', 1)
36+
}
37+
</script>
38+
39+
<style>
40+
.vuemastery-banner {
41+
background: url("../images/vuemastery/background-vuemastery.svg") center center no-repeat;
42+
background-size: 100% auto;
43+
overflow: hidden;
44+
position: fixed;
45+
top: 0;
46+
z-index: 2;
47+
width: 100%;
48+
transition: all 0.3s ease-out 0.1s;
49+
}
50+
.vuemastery-banner:before {
51+
content: '';
52+
background: url("../images/vuemastery/background-bubbles-vuemastery.svg") left center no-repeat;
53+
background-size: cover;
54+
position: absolute;
55+
top: 0;
56+
bottom: 0;
57+
left: 0;
58+
right: 0;
59+
transition: all 0.3s ease-out 0.1s;
60+
transform: scale(1.1);
61+
}
62+
.vuemastery-banner:after {
63+
content: '';
64+
background: url("../images/vuemastery/lock-vuemastery.svg") right center no-repeat;
65+
background-size: auto 100%;
66+
position: absolute;
67+
width: 100%;
68+
height: 100%;
69+
top: 0;
70+
left: 0;
71+
pointer-events: none;
72+
}
73+
.vuemastery-banner:hover {
74+
background-size: 150% auto;
75+
}
76+
.vuemastery-banner:hover:before {
77+
transform: scale(1);
78+
}
79+
.vuemastery-banner:hover:after {
80+
background-image: url("../images/vuemastery/unlock-vuemastery.svg");
81+
}
82+
.vuemastery-banner a {
83+
display: flex;
84+
height: 80px;
85+
justify-content: center;
86+
}
87+
.vuemastery-banner--wrapper {
88+
display: flex;
89+
height: 100%;
90+
align-items: center;
91+
width: 100%;
92+
justify-content: center;
93+
position: relative;
94+
}
95+
.vuemastery-banner--wrapper:before {
96+
content: '';
97+
pointer-events: none;
98+
position: absolute;
99+
top: 0;
100+
bottom: 0;
101+
left: 0;
102+
width: 0;
103+
transition: width 0.3s ease-out;
104+
}
105+
.vuemastery-banner--wrapper:hover + .vuemastery-banner--close:before,
106+
.vuemastery-banner--wrapper:hover + .vuemastery-banner--close:after {
107+
transform-origin: 100%;
108+
}
109+
.vuemastery-banner--wrapper p {
110+
margin: -3px 50px 0 20px;
111+
font-size: 1rem;
112+
color: #fff;
113+
position: relative;
114+
transition-delay: 0.15s;
115+
}
116+
.vuemastery-banner--wrapper span {
117+
font-weight: 600;
118+
display: block;
119+
color: #beff74;
120+
background: -webkit-linear-gradient(#41e281, #beff74);
121+
-webkit-background-clip: text;
122+
-webkit-text-fill-color: transparent;
123+
}
124+
.vuemastery-banner--logo {
125+
height: 102%;
126+
margin-top: -1px;
127+
margin-left: -200px;
128+
position: relative;
129+
z-index: 2;
130+
}
131+
.vuemastery-banner--close {
132+
position: absolute;
133+
top: 20px;
134+
right: 25px;
135+
height: 40px;
136+
width: 40px;
137+
-webkit-tap-highlight-color: transparent;
138+
border-radius: 50%;
139+
cursor: pointer;
140+
}
141+
.vuemastery-banner--close:before,
142+
.vuemastery-banner--close:after {
143+
content: '';
144+
position: absolute;
145+
top: 19px;
146+
left: 14px;
147+
width: 25px;
148+
height: 2px;
149+
background-color: #fff;
150+
transform-origin: 50%;
151+
transform: rotate(-45deg);
152+
transition: all 0.2s ease-out;
153+
}
154+
.vuemastery-banner--close:after {
155+
transform: rotate(45deg);
156+
}
157+
.vuemastery-button {
158+
display: inline-flex;
159+
background: linear-gradient(to top right, #3d2c61, #835ec2);
160+
height: 38px;
161+
margin: 0.5em 0;
162+
line-height: 38px;
163+
padding: 0 30px;
164+
color: #fff;
165+
text-decoration: none;
166+
align-items: center;
167+
justify-content: center;
168+
outline: 0;
169+
text-transform: uppercase;
170+
border: none;
171+
border-radius: 36px;
172+
font-weight: bold;
173+
font-size: 12px;
174+
cursor: pointer;
175+
position: relative;
176+
overflow: hidden;
177+
}
178+
.vuemastery-button:before,
179+
.vuemastery-button:after {
180+
background: linear-gradient(to top right, transparent, #fff);
181+
content: "";
182+
height: 150px;
183+
left: -175px;
184+
opacity: 0.1;
185+
position: absolute;
186+
top: -50px;
187+
transform: rotate(35deg);
188+
width: 100px;
189+
}
190+
.vuemastery-weekend-promo #mobile-bar,
191+
.vuemastery-weekend-promo #mobile-bar.top {
192+
position: relative;
193+
background-color: #fff;
194+
}
195+
.vuemastery-weekend-promo.docs:not(.vuemastery-menu-fixed) {
196+
padding-top: 0;
197+
}
198+
.vuemastery-weekend-promo.docs:not(.vuemastery-menu-fixed) #header {
199+
position: relative;
200+
width: auto;
201+
}
202+
.vuemastery-weekend-promo.vuemastery-menu-fixed #mobile-bar {
203+
position: fixed;
204+
}
205+
@media screen and (min-width: 901px) {
206+
.vuemastery-weekend-promo.docs:not(.vuemastery-menu-fixed) #main.fix-sidebar .sidebar {
207+
position: absolute;
208+
top: 141px;
209+
}
210+
.vuemastery-weekend-promo.docs:not(.vuemastery-menu-fixed) #sidebar-sponsors-platinum-right {
211+
position: absolute;
212+
top: 170px;
213+
}
214+
.vuemastery-weekend-promo.vuemastery-menu-fixed.docs .vuemastery-banner {
215+
margin-bottom: 0;
216+
}
217+
.vuemastery-banner--wrapper span {
218+
font-size: 1.17rem;
219+
}
220+
}
221+
@media screen and (max-width: 1200px) {
222+
.vuemastery-banner,
223+
.vuemastery-banner:hover {
224+
background-size: cover;
225+
}
226+
.vuemastery-banner:before {
227+
transform: scale(1);
228+
}
229+
.vuemastery-banner:hover:before {
230+
transform: scale(1);
231+
}
232+
}
233+
@media screen and (max-width: 1100px) {
234+
.vuemastery-button {
235+
display: none;
236+
}
237+
}
238+
@media screen and (max-width: 900px) {
239+
.vuemastery-weekend-promo.vuemastery-menu-fixed .vuemastery-banner {
240+
margin-bottom: 40px;
241+
}
242+
.vuemastery-banner:after {
243+
background-position: right -6rem center;
244+
}
245+
}
246+
@media screen and (max-width: 700px) {
247+
.vuemastery-banner a {
248+
overflow: hidden;
249+
}
250+
.vuemastery-banner .vuemastery-banner--logo {
251+
margin-left: 0;
252+
justify-content: flex-start;
253+
}
254+
.vuemastery-banner p,
255+
.vuemastery-banner span {
256+
line-height: 18px;
257+
color: #fff;
258+
}
259+
.vuemastery-banner p {
260+
max-width: 230px;
261+
}
262+
.vuemastery-banner .vuemastery-banner--close {
263+
right: 0px;
264+
}
265+
.vuemastery-banner .vuemastery-banner--close:before,
266+
.vuemastery-banner .vuemastery-banner--close:after {
267+
top: 19px;
268+
left: 14px;
269+
width: 15px;
270+
height: 2px;
271+
}
272+
.vuemastery-banner:after {
273+
display: none;
274+
}
275+
}
276+
@media screen and (max-width: 465px) {
277+
278+
.vuemastery-banner p {
279+
max-width: 185px;
280+
}
281+
.vuemastery-banner:after {
282+
background-position: right -3rem center;
283+
}
284+
}
285+
@media screen and (max-width: 400px) {
286+
.vuemastery-banner p {
287+
font-size: 0.6rem;
288+
margin: -3px 28px 0 0px;
289+
max-width: 140px;
290+
}
291+
}
292+
@media print {
293+
.vuemastery-banner {
294+
display: none;
295+
}
296+
}
297+
298+
299+
.has-top-banner {
300+
--vt-banner-height: 80px;
301+
}
302+
303+
.has-top-banner .banner {
304+
height: 24px;
305+
line-height: 24px;
306+
top: 80px;
307+
}
308+
</style>

.vitepress/theme/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@ import './styles/index.css'
22
import { h, App } from 'vue'
33
import { VPTheme } from '@vue/theme'
44
import PreferenceSwitch from './components/PreferenceSwitch.vue'
5+
import VueMasteryBanner from './components/VueMasteryBanner.vue'
56
import {
67
preferComposition,
78
preferSFC,
89
filterHeadersByPreference
910
} from './components/preferences'
1011
import SponsorsAside from './components/SponsorsAside.vue'
11-
import VueSchoolLink from './components/VueSchoolLink.vue'
1212
import VueJobs from './components/VueJobs.vue'
1313

1414
export default Object.assign({}, VPTheme, {
1515
Layout: () => {
1616
// @ts-ignore
1717
return h(VPTheme.Layout, null, {
18+
banner: () => h('div', {}, [
19+
h(VueMasteryBanner)
20+
]),
1821
'sidebar-top': () => h(PreferenceSwitch),
1922
'aside-mid': () => h(SponsorsAside),
2023
'aside-bottom': () => h(VueJobs)
@@ -24,6 +27,5 @@ export default Object.assign({}, VPTheme, {
2427
app.provide('prefer-composition', preferComposition)
2528
app.provide('prefer-sfc', preferSFC)
2629
app.provide('filter-headers', filterHeadersByPreference)
27-
app.component('VueSchoolLink', VueSchoolLink)
2830
}
2931
})

0 commit comments

Comments
 (0)