Skip to content

Commit 165a4b2

Browse files
posvaIsraelOrtuno
andauthored
docs: mad vue (vuejs#2468)
* feat: add madvue banner * chore: action text * docs: fix banner * docs: fix * chore: order --------- Co-authored-by: Israel Ortuño <[email protected]>
1 parent 3753ede commit 165a4b2

File tree

3 files changed

+320
-25
lines changed

3 files changed

+320
-25
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
<script setup lang="ts">
2+
import { ref, onMounted } from 'vue'
3+
4+
const isVisible = ref(false)
5+
const nameStorage = 'MADVUE-BANNER-MARCH-2025'
6+
const target = 'https://madvue.es/?utm_source=vue-router&utm_content=top_banner'
7+
8+
function closeBanner() {
9+
// Hide the banner
10+
isVisible.value = false
11+
// Save action in the local storage
12+
localStorage.setItem(nameStorage, String(true))
13+
document.documentElement.classList.remove('has-banner')
14+
}
15+
16+
onMounted(() => {
17+
if (localStorage.getItem(nameStorage) != null) {
18+
return
19+
}
20+
21+
const keys = Object.keys(localStorage).filter(
22+
key => key.includes('FREEWEEKEND25') && key.endsWith('_CLOSED')
23+
)
24+
25+
if (keys.length > 0 && keys.every(key => localStorage.getItem(key) != null)) {
26+
isVisible.value = true
27+
document.documentElement.classList.add('has-banner')
28+
}
29+
})
30+
</script>
31+
32+
<template>
33+
<div class="banner" v-if="isVisible">
34+
<a target="_blank" :href="target">
35+
<svg
36+
class="logo"
37+
viewBox="0 0 2688 734"
38+
version="1.1"
39+
style="
40+
fill-rule: evenodd;
41+
clip-rule: evenodd;
42+
stroke-linejoin: round;
43+
stroke-miterlimit: 2;
44+
"
45+
>
46+
<g>
47+
<g>
48+
<g>
49+
<path
50+
d="M537.782,722.201l-115.56,-0l0,-367.774l-100,367.774l-115.56,-0l-91.102,-375.543l-0,375.543l-115.56,-0l-0,-721.094l123.329,-0l147.786,512.218l139.996,-512.218l126.671,-0l0,721.094Z"
51+
style="fill: #f97844; fill-rule: nonzero"
52+
></path>
53+
</g>
54+
</g>
55+
</g>
56+
<g>
57+
<g>
58+
<g>
59+
<path
60+
d="M985.548,722.201l-111.111,-0l-0,-37.783c-1.498,32.596 -33.334,48.894 -95.552,48.894c-42.968,-0 -82.226,-14.085 -117.773,-42.231c-37.782,-30.361 -56.684,-66.276 -56.684,-107.769c-0,-26.671 7.422,-53.516 22.222,-80.556c14.822,-27.04 32.965,-48.698 54.449,-64.996c25.933,-19.249 60.373,-28.884 103.342,-28.884c37.022,-0 67.035,5.186 89.996,15.56l-0,-30.013c-0,-62.218 -24.089,-93.316 -72.223,-93.316c-20.746,-0 -36.306,5.555 -46.679,16.666c-7.401,8.138 -14.801,23.698 -22.223,46.658l-109.982,0c-0,-45.92 16.298,-85.178 48.871,-117.773c32.596,-32.596 71.854,-48.893 117.795,-48.893l28.885,-0c45.92,-0 85.178,16.297 117.773,48.893c32.596,32.595 48.894,71.853 48.894,117.773l-0,357.77Zm-111.111,-154.449c-0,-19.987 -7.965,-37.023 -23.894,-51.107c-15.928,-14.063 -33.897,-21.115 -53.884,-21.115c-20.009,-0 -39.453,7.964 -58.334,23.893c-18.901,15.929 -28.342,33.528 -28.342,52.778c0,19.27 10.005,35.177 30.013,47.786c17.774,11.849 36.654,17.773 56.663,17.773c19.987,0 37.956,-6.857 53.884,-20.551c15.929,-13.715 23.894,-30.186 23.894,-49.457Z"
61+
style="fill: #f97844; fill-rule: nonzero"
62+
></path>
63+
</g>
64+
</g>
65+
</g>
66+
<g>
67+
<g>
68+
<g>
69+
<path
70+
d="M1417.74,-0l-1.107,722.201l-106.662,-0l-0,-32.227c-14.822,28.885 -45.183,43.338 -91.103,43.338c-45.92,-0 -85.178,-16.298 -117.773,-48.894c-32.596,-32.595 -48.893,-71.853 -48.893,-117.773l-0,-202.214c-0,-45.92 16.297,-85.178 48.893,-117.773c32.595,-32.596 71.853,-48.893 117.773,-48.893l28.885,-0c20.746,-0 39.258,10.373 55.555,31.12l-1.106,-227.778l115.538,-1.107Zm-115.538,359.983c-0,-42.21 -22.223,-63.325 -66.667,-63.325c-48.156,-0 -72.222,31.098 -72.222,93.338l-0,146.658c-0,62.218 22.591,93.337 67.773,93.337c18.511,0 34.809,-6.315 48.893,-18.902c14.063,-12.586 21.094,-28.146 21.094,-46.658l1.129,-204.448Z"
71+
style="fill: #f97844; fill-rule: nonzero"
72+
></path>
73+
</g>
74+
</g>
75+
</g>
76+
<g>
77+
<g>
78+
<g>
79+
<path
80+
d="M1845.57,1.107l-127.778,722.2l-118.88,-1.106l-123.329,-721.094l115.538,-0l67.795,488.867l71.094,-488.867l115.56,-0Z"
81+
style="fill: #c4d141; fill-rule: nonzero"
82+
></path>
83+
</g>
84+
</g>
85+
</g>
86+
<g>
87+
<g>
88+
<g>
89+
<path
90+
d="M2262.22,723.307l-115.56,-1.106l1.129,-27.778c-17.036,20.746 -48.893,31.12 -95.551,31.12c-45.942,-0 -83.334,-16.125 -112.218,-48.351c-28.906,-32.205 -43.338,-71.658 -43.338,-118.316l1.107,-368.88l108.876,-0l1.128,343.316c0,62.218 24.067,93.337 72.222,93.337c43.685,0 65.539,-21.115 65.539,-63.324l-1.107,-373.329l116.667,-0l1.106,533.311Z"
91+
style="fill: #c4d141; fill-rule: nonzero"
92+
></path>
93+
</g>
94+
</g>
95+
</g>
96+
<g>
97+
<g>
98+
<g>
99+
<path
100+
d="M2687.76,566.645c-0,45.92 -16.298,85.178 -48.872,117.773c-32.595,32.596 -71.853,48.894 -117.773,48.894l-28.906,-0c-45.921,-0 -85.178,-16.298 -117.774,-48.894c-32.595,-32.595 -48.871,-71.853 -48.871,-117.773l-0,-202.214c-0,-45.92 16.276,-85.178 48.871,-117.773c32.596,-32.596 71.853,-48.893 117.774,-48.893l28.906,-0c45.92,-0 85.178,16.297 117.773,48.893c32.574,32.595 48.872,71.853 48.872,117.773l-0,153.321l-251.107,-0l0,18.902c0,34.809 7.791,59.244 23.351,73.329c15.538,14.062 41.102,21.115 76.649,21.115c20.009,0 33.702,-21.484 41.124,-64.453l109.983,-0Zm-111.111,-141.102l-0,-35.547c-0,-62.24 -24.067,-93.338 -72.201,-93.338c-45.204,-0 -67.795,31.098 -67.795,93.338l0,34.44l139.996,1.107Z"
101+
style="fill: #c4d141; fill-rule: nonzero"
102+
></path>
103+
</g>
104+
</g>
105+
</g>
106+
</svg>
107+
</a>
108+
109+
<div>
110+
<div class="headline">
111+
<a target="_blank" :href="target" class="vt-tagline"
112+
>The Vue.js Event in Madrid</a
113+
>
114+
<span class="place"> · Spain</span>
115+
<span class="vt-date"> · 29 May 2025</span>
116+
</div>
117+
118+
<div class="claim">
119+
<span class="mv-text-primary">Early bird</span> tickets available
120+
<span class="mv-text-primary">Get 30% off</span>
121+
</div>
122+
</div>
123+
<a target="_blank" class="action" :href="target">
124+
More Info
125+
<svg
126+
xmlns="http://www.w3.org/2000/svg"
127+
width="15"
128+
height="15"
129+
style="margin-left: 10px"
130+
viewBox="0 0 15 15"
131+
>
132+
<path
133+
fill="currentColor"
134+
d="M8.293 2.293a1 1 0 0 1 1.414 0l4.5 4.5a1 1 0 0 1 0 1.414l-4.5 4.5a1 1 0 0 1-1.414-1.414L11 8.5H1.5a1 1 0 0 1 0-2H11L8.293 3.707a1 1 0 0 1 0-1.414"
135+
/>
136+
</svg>
137+
</a>
138+
<div class="close-btn" @click.stop.prevent="closeBanner">
139+
<span class="close">&times;</span>
140+
</div>
141+
</div>
142+
</template>
143+
144+
<style>
145+
html.has-banner {
146+
--vp-layout-top-height: 72px;
147+
}
148+
</style>
149+
150+
<style scoped>
151+
.banner {
152+
position: fixed;
153+
box-sizing: border-box;
154+
top: 0;
155+
left: 0;
156+
right: 0;
157+
z-index: 50;
158+
height: var(--vp-layout-top-height);
159+
font-weight: 600;
160+
color: #fff;
161+
background: #0f172a;
162+
display: flex;
163+
flex-direction: column;
164+
justify-content: center;
165+
align-items: center;
166+
gap: 5px;
167+
}
168+
169+
.banner .logo {
170+
height: 16px;
171+
}
172+
173+
.banner .headline {
174+
font-size: 14px;
175+
}
176+
177+
.banner .claim {
178+
display: none;
179+
}
180+
181+
.banner-dismissed .banner {
182+
display: none;
183+
}
184+
185+
.mv-text-primary {
186+
color: #c4d141;
187+
}
188+
189+
.banner .action {
190+
display: none;
191+
background: #f97844;
192+
color: #fff;
193+
padding: 3px 8px;
194+
font-size: 13px;
195+
align-items: center;
196+
border-radius: 8px;
197+
text-decoration: none;
198+
}
199+
200+
.banner .action svg {
201+
display: none;
202+
}
203+
204+
.action:hover {
205+
text-decoration: none;
206+
background: #c4d141;
207+
}
208+
209+
.close {
210+
font-size: 24px;
211+
line-height: 24px;
212+
height: 24px;
213+
}
214+
215+
.banner .close-btn {
216+
top: 50%;
217+
transform: translateY(-50%);
218+
height: 24px;
219+
left: 16px;
220+
z-index: 99;
221+
position: absolute;
222+
cursor: pointer;
223+
}
224+
225+
.banner .place {
226+
display: none;
227+
}
228+
229+
@media (min-width: 768px) {
230+
.banner {
231+
gap: 20px;
232+
text-align: center;
233+
flex-direction: row;
234+
}
235+
236+
.banner .place {
237+
display: inline;
238+
}
239+
240+
.banner .action {
241+
display: flex;
242+
}
243+
244+
.banner .action svg {
245+
display: block;
246+
}
247+
248+
.banner .logo {
249+
height: 20px;
250+
}
251+
252+
.banner .headline {
253+
font-size: 15px;
254+
}
255+
256+
.banner .claim {
257+
font-size: 13px;
258+
display: block;
259+
}
260+
261+
.banner .action {
262+
padding: 0 10px;
263+
height: 32px;
264+
font-size: 13px;
265+
}
266+
}
267+
268+
@media (min-width: 960px) {
269+
.banner {
270+
gap: 40px;
271+
}
272+
273+
.banner .logo {
274+
height: 32px;
275+
}
276+
277+
.banner .headline {
278+
font-size: 20px;
279+
}
280+
281+
.banner .claim {
282+
font-size: 18px;
283+
margin-top: 4px;
284+
}
285+
286+
.banner .action {
287+
padding: 0 14px;
288+
height: 40px;
289+
font-size: 16px;
290+
}
291+
}
292+
</style>

packages/docs/.vitepress/theme/components/VueMasteryBanner.vue

+26-25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
<script setup lang="ts">
2+
import { ref, onMounted } from 'vue'
3+
4+
const isVisible = ref(false)
5+
const showFlash = ref(false)
6+
const nameStorage = 'VUEMASTERY-BANNER-DECEMBER-2023'
7+
8+
function closeBanner() {
9+
// Hide the banner
10+
isVisible.value = false
11+
// Save action in the local storage
12+
localStorage.setItem(nameStorage, String(true))
13+
document.documentElement.classList.remove('vuemastery-menu-fixed')
14+
}
15+
16+
onMounted(() => {
17+
isVisible.value = !localStorage.getItem(nameStorage)
18+
if (isVisible.value) {
19+
document.documentElement.classList.add('vuemastery-menu-fixed')
20+
setTimeout(() => {
21+
showFlash.value = true
22+
}, 2000)
23+
}
24+
})
25+
</script>
26+
127
<template>
228
<div class="vuemastery-banner-wrapper" role="banner" v-if="isVisible">
329
<div
@@ -30,31 +56,6 @@
3056
</div>
3157
</template>
3258

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>
5859
<style scoped>
5960
.vuemastery-banner-wrapper {
6061
position: fixed;

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

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import './styles/vars.css'
88
import VueSchoolLink from './components/VueSchoolLink.vue'
99
import VueMasteryLogoLink from './components/VueMasteryLogoLink.vue'
1010
import status from '../translation-status.json'
11+
import MadVueBanner from './components/MadVueBanner.vue'
1112

1213
const i18nLabels = {
1314
zh: '该翻译已同步到了 ${date} 的版本,其对应的 commit hash 是 <code>${hash}</code>。',
@@ -20,6 +21,7 @@ const theme: Theme = {
2021
// 'home-features-after': () => h(HomeSponsors),
2122
'aside-ads-before': () => h(AsideSponsors),
2223
'doc-before': () => h(TranslationStatus, { status, i18nLabels }),
24+
'layout-top': () => h(MadVueBanner)
2325
})
2426
},
2527

0 commit comments

Comments
 (0)