Skip to content

Commit adca152

Browse files
i5dr0idposva
andauthored
docs: Add vuemastery banner (#2088)
* feat: add vuemastery banner * Update packages/docs/.vitepress/theme/components/VueMasteryBanner.vue --------- Co-authored-by: Eduardo San Martin Morote <[email protected]>
1 parent 110c869 commit adca152

File tree

6 files changed

+946
-0
lines changed

6 files changed

+946
-0
lines changed
Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
<template>
2+
<div class="vuemastery-banner-wrapper" role="banner" v-if="isVisible">
3+
<div
4+
:class="{ 'show-flash': showFlash }"
5+
class="vuemastery-background-dim"
6+
ref="vuemastery-banner-flash"
7+
></div>
8+
<a id="vm-banner" href="https://www.vuemastery.com/holiday" target="_blank">
9+
<img
10+
id="vm-logo-full"
11+
src="/vuemastery/vuemastery-white.svg"
12+
alt="vuemastery"
13+
/>
14+
<img
15+
id="vm-logo-small"
16+
src="https://firebasestorage.googleapis.com/v0/b/vue-mastery.appspot.com/o/flamelink%2Fmedia%2Fvue-mastery-logo-small.png?alt=media&token=941fcc3a-2b6f-40e9-b4c8-56b3890da108"
17+
alt="vuemastery"
18+
/>
19+
<div class="vm-banner-wrapper">
20+
<div class="vm-banner-content">
21+
<h1 class="vm-banner-title">Learn Vue with Evan You</h1>
22+
<p class="vm-banner-sub">Get 60% off a year of Vue courses</p>
23+
</div>
24+
<button id="vm-banner-cta">Unlock your discount</button>
25+
</div>
26+
<button id="vm-banner-close" @click.prevent="closeBanner">
27+
<span class="close">&times;</span>
28+
</button>
29+
</a>
30+
</div>
31+
</template>
32+
33+
<script setup lang="ts">
34+
import { ref, onMounted } from 'vue'
35+
36+
const isVisible = ref(false)
37+
const showFlash = ref(false)
38+
const nameStorage = 'VUEMASTERY-BANNER-DECEMBER-2023'
39+
40+
const closeBanner = () => {
41+
// Hide the banner
42+
isVisible.value = false
43+
// Save action in the local storage
44+
localStorage.setItem(nameStorage, String(true))
45+
document.documentElement.classList.remove('vuemastery-menu-fixed')
46+
}
47+
48+
onMounted(() => {
49+
isVisible.value = !localStorage.getItem(nameStorage)
50+
if (isVisible.value) {
51+
document.documentElement.classList.add('vuemastery-menu-fixed')
52+
setTimeout(() => {
53+
showFlash.value = true
54+
}, 2000)
55+
}
56+
})
57+
</script>
58+
<style scoped>
59+
.vuemastery-banner-wrapper {
60+
position: fixed;
61+
top: 0;
62+
bottom: 0;
63+
left: 0;
64+
right: 0;
65+
z-index: 61;
66+
width: 100%;
67+
height: 100%;
68+
max-height: 70px;
69+
background: linear-gradient(45deg, #0a2b4e, #835ec2);
70+
background-size: 110%;
71+
background-position: 50% 50%;
72+
overflow: hidden;
73+
padding: 12px;
74+
margin: 0;
75+
transition: background-size 0.25s cubic-bezier(0.39, 0.575, 0.565, 1);
76+
}
77+
78+
.vuemastery-banner-wrapper:hover {
79+
background-size: 100%;
80+
}
81+
82+
.vuemastery-banner-wrapper:before {
83+
content: '';
84+
background: url(/vuemastery/background-bubbles-vuemastery.svg) left center
85+
no-repeat;
86+
background-size: cover;
87+
position: absolute;
88+
top: 0;
89+
bottom: 0;
90+
left: 0;
91+
right: 0;
92+
transition: all 0.3s ease-out 0.1s;
93+
transform: scale(1.1);
94+
width: 100%;
95+
height: 100%;
96+
}
97+
.vuemastery-banner-wrapper:after {
98+
content: '';
99+
background: url(/vuemastery/lock-vuemastery.svg) right center no-repeat;
100+
background-size: auto 100%;
101+
position: absolute;
102+
width: 100%;
103+
height: 100%;
104+
top: 0;
105+
left: 0;
106+
pointer-events: none;
107+
}
108+
109+
.vuemastery-banner-wrapper:hover:after {
110+
background-image: url(/vuemastery/unlock-vuemastery.svg);
111+
}
112+
113+
#vm-banner {
114+
position: relative;
115+
width: 100%;
116+
height: 100%;
117+
text-decoration: none;
118+
color: white;
119+
display: flex;
120+
justify-content: center;
121+
align-items: center;
122+
overflow: hidden;
123+
}
124+
125+
#vm-logo-full {
126+
position: absolute;
127+
left: 15px;
128+
width: 120px;
129+
}
130+
131+
#vm-logo-small {
132+
display: none;
133+
}
134+
135+
.vm-banner-wrapper {
136+
display: flex;
137+
align-items: center;
138+
}
139+
140+
.vm-banner-content {
141+
display: flex;
142+
}
143+
144+
.vm-banner-title {
145+
margin: 0;
146+
padding: 0;
147+
font-weight: bold;
148+
font-size: 24px;
149+
text-align: center;
150+
background: linear-gradient(145deg, #c3ffac, #86ec87, #38a56a);
151+
background-clip: text;
152+
-webkit-background-clip: text;
153+
-webkit-text-fill-color: transparent;
154+
}
155+
156+
.vm-banner-sub {
157+
margin: 0 2em;
158+
padding: 0;
159+
font-size: 16px;
160+
text-align: center;
161+
color: #fff;
162+
}
163+
164+
#vm-banner-cta {
165+
position: relative;
166+
margin-left: 10px;
167+
padding: 10px 24px;
168+
background: linear-gradient(to top right, #41b782, #86d169);
169+
border: none;
170+
border-radius: 30px;
171+
color: #fff;
172+
font-size: 12px;
173+
font-weight: bold;
174+
text-decoration: none;
175+
text-transform: uppercase;
176+
}
177+
178+
#vm-banner-cta:hover {
179+
background: linear-gradient(to bottom right, #41b782, #86d169);
180+
}
181+
182+
#vm-banner-close {
183+
position: absolute;
184+
right: 12px;
185+
color: #fff;
186+
font-size: 20px;
187+
font-weight: bold;
188+
display: flex;
189+
align-items: center;
190+
justify-content: center;
191+
}
192+
193+
#vm-banner-close > .close {
194+
font-size: 20px;
195+
font-weight: 600;
196+
}
197+
198+
@media (max-width: 1200px) {
199+
#vm-banner-cta {
200+
display: none;
201+
}
202+
203+
.vm-banner-content {
204+
flex-direction: column;
205+
}
206+
207+
.vm-banner-sub {
208+
margin: 0 1em;
209+
}
210+
}
211+
212+
@media (max-width: 850px) {
213+
.vuemastery-banner-wrapper:after {
214+
background: none;
215+
}
216+
}
217+
@media (max-width: 767px) {
218+
#vm-logo-full {
219+
left: 10px;
220+
width: 100px;
221+
}
222+
}
223+
@media (max-width: 767px) {
224+
#vm-logo-full {
225+
display: none;
226+
}
227+
#vm-logo-small {
228+
position: absolute;
229+
display: block;
230+
left: 10px;
231+
width: 40px;
232+
}
233+
.vm-banner-title {
234+
font-size: 14px;
235+
}
236+
.vm-banner-sub {
237+
font-size: 12px;
238+
margin: 0;
239+
}
240+
}
241+
242+
.vuemastery-background-dim {
243+
position: absolute;
244+
width: 100%;
245+
height: 100%;
246+
top: 0;
247+
left: 0;
248+
}
249+
.vuemastery-background-dim:after {
250+
content: '';
251+
position: absolute;
252+
top: 0;
253+
left: -100%;
254+
width: 100%;
255+
height: 100%;
256+
background: linear-gradient(
257+
90deg,
258+
transparent,
259+
rgba(255, 255, 255, 0.4),
260+
transparent
261+
);
262+
transition: 0.5s;
263+
transition-delay: 0.5s;
264+
}
265+
.vuemastery-background-dim.show-flash:after {
266+
left: 100%;
267+
}
268+
</style>
269+
270+
<style>
271+
html.vuemastery-menu-fixed {
272+
--vt-banner-height: 70px;
273+
}
274+
html.vuemastery-menu-fixed .VPNav,
275+
html.vuemastery-menu-fixed .VPSidebar {
276+
top: 70px;
277+
}
278+
html.vuemastery-menu-fixed {
279+
scroll-padding-top: 134px;
280+
overflow: auto;
281+
}
282+
html.vuemastery-menu-fixed {
283+
margin-top: 72px;
284+
}
285+
@media (max-width: 960px) {
286+
html.vuemastery-menu-fixed .VPNav,
287+
html.vuemastery-menu-fixed .VPSidebar {
288+
top: 0;
289+
}
290+
}
291+
</style>

packages/docs/.vitepress/theme/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import './styles/vars.css'
88
import './styles/sponsors.css'
99
import VueSchoolLink from './components/VueSchoolLink.vue'
1010
import VueMasteryLogoLink from './components/VueMasteryLogoLink.vue'
11+
import VueMasteryBanner from './components/VueMasteryBanner.vue'
1112

1213
const theme: Theme = {
1314
...DefaultTheme,
@@ -16,6 +17,7 @@ const theme: Theme = {
1617
// 'home-features-after': () => h(HomeSponsors),
1718
'aside-ads-before': () => h(AsideSponsors),
1819
'doc-before': () => h(TranslationStatus),
20+
'layout-top': () => h(VueMasteryBanner),
1921
})
2022
},
2123

0 commit comments

Comments
 (0)