Skip to content

Commit ab958c8

Browse files
i5dr0idyyx990803
andauthored
add vuemastery banner black friday 2024 (#3104)
Co-authored-by: Evan You <[email protected]>
1 parent 797839b commit ab958c8

File tree

4 files changed

+397
-0
lines changed

4 files changed

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

.vitepress/theme/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import SponsorsAside from './components/SponsorsAside.vue'
1212
import VueSchoolLink from './components/VueSchoolLink.vue'
1313
// import Banner from './components/Banner.vue'
1414
// import TextAd from './components/TextAd.vue'
15+
import VueMasteryBanner from './components/VueMasteryBanner.vue'
1516

1617
export default Object.assign({}, VPTheme, {
1718
Layout: () => {
1819
// @ts-ignore
1920
return h(VPTheme.Layout, null, {
2021
// banner: () => h(Banner),
22+
banner: () => h(VueMasteryBanner),
2123
'sidebar-top': () => h(PreferenceSwitch),
2224
'sidebar-bottom': () => h(SecurityUpdateBtn),
2325
'aside-mid': () => h(SponsorsAside)
Lines changed: 110 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)