@@ -23,6 +23,60 @@ const props = withDefaults(defineProps<Props>(), {
2323 placement: ' home' ,
2424})
2525
26+ const sponsorUrl
27+ = ' https://opencollective.com/masscode/contribute/silver-sponsors-43169/checkout?interval=month&amount=50&contributeAs=me'
28+
29+ const ctaSparks = [
30+ {
31+ tx: ' -22px' ,
32+ ty: ' -26px' ,
33+ rot: ' -32deg' ,
34+ delay: ' 0s' ,
35+ duration: ' 2.4s' ,
36+ size: ' 11px' ,
37+ },
38+ {
39+ tx: ' 24px' ,
40+ ty: ' -28px' ,
41+ rot: ' 34deg' ,
42+ delay: ' 0.55s' ,
43+ duration: ' 2.6s' ,
44+ size: ' 13px' ,
45+ },
46+ {
47+ tx: ' -28px' ,
48+ ty: ' -6px' ,
49+ rot: ' -52deg' ,
50+ delay: ' 1.05s' ,
51+ duration: ' 2.0s' ,
52+ size: ' 9px' ,
53+ },
54+ {
55+ tx: ' 26px' ,
56+ ty: ' -4px' ,
57+ rot: ' 46deg' ,
58+ delay: ' 0.3s' ,
59+ duration: ' 2.2s' ,
60+ size: ' 10px' ,
61+ },
62+ {
63+ tx: ' -8px' ,
64+ ty: ' -30px' ,
65+ rot: ' -10deg' ,
66+ delay: ' 0.85s' ,
67+ duration: ' 2.5s' ,
68+ size: ' 12px' ,
69+ },
70+ {
71+ tx: ' 10px' ,
72+ ty: ' -32px' ,
73+ rot: ' 14deg' ,
74+ delay: ' 1.45s' ,
75+ duration: ' 2.3s' ,
76+ size: ' 10px' ,
77+ },
78+ ] as const
79+
2680const data = ref <SponsorData >(sponsorsData )
2781const isShow = ref (false )
2882
@@ -79,6 +133,60 @@ onMounted(async () => {
79133 {{ text }}
80134 </div >
81135 </a >
136+ <a
137+ v-if =" placement === 'home'"
138+ :href =" sponsorUrl"
139+ class =" sponsors-item sponsors-item-cta"
140+ target =" _blank"
141+ rel =" noopener"
142+ >
143+ <span class =" cta-heart-wrap" >
144+ <svg
145+ class =" cta-heart"
146+ viewBox =" 0 0 24 24"
147+ stroke =" currentColor"
148+ stroke-width =" 1.6"
149+ stroke-linecap =" round"
150+ stroke-linejoin =" round"
151+ aria-hidden =" true"
152+ >
153+ <path
154+ fill =" transparent"
155+ d =" M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"
156+ />
157+ </svg >
158+ <span
159+ class =" cta-spark-layer"
160+ aria-hidden =" true"
161+ >
162+ <span
163+ v-for =" (spark, i) in ctaSparks"
164+ :key =" i"
165+ class =" cta-spark"
166+ :style =" {
167+ '--tx': spark.tx,
168+ '--ty': spark.ty,
169+ '--rot': spark.rot,
170+ '--delay': spark.delay,
171+ '--duration': spark.duration,
172+ '--size': spark.size,
173+ }"
174+ >
175+ <svg
176+ viewBox =" 0 0 24 24"
177+ aria-hidden =" true"
178+ >
179+ <path
180+ fill =" currentColor"
181+ d =" M12 21s-7-4.5-9.5-9C-0.5 6.5 5 1.5 12 6c7-4.5 12.5 0.5 9.5 6-2.5 4.5-9.5 9-9.5 9z"
182+ />
183+ </svg >
184+ </span >
185+ </span >
186+ </span >
187+ <span class =" cta-title" >Become a sponsor</span >
188+ <span class =" cta-subtitle" >Your logo here</span >
189+ </a >
82190 </div >
83191 </template >
84192 </div >
@@ -142,6 +250,187 @@ onMounted(async () => {
142250 justify-content : center ;
143251}
144252
253+ @property --sponsor-cta-angle {
254+ syntax: "<angle> ";
255+ initial-value : 0deg;
256+ inherits: false;
257+ }
258+
259+ .sponsors-item-cta {
260+ /* Multiplier for the heart spray reach. 1 = default, 1.5 = 50% wider, 0.5 = half. */
261+ --spray-scale : 2 ;
262+ position : relative ;
263+ overflow : hidden ;
264+ isolation : isolate ;
265+ gap : 6px ;
266+ text-align : center ;
267+ text-decoration : none ;
268+ border : 1px solid transparent ;
269+ background :
270+ linear-gradient (var (--vp-c-bg-soft ), var (--vp-c-bg-soft )) padding-box ,
271+ conic-gradient (
272+ from var (--sponsor-cta-angle ),
273+ color-mix(in srgb , var (--vp-c-brand-1 ) 22% , transparent ),
274+ color-mix(in srgb , var (--vp-c-brand-1 ) 22% , transparent ) 60deg ,
275+ var (--vp-c-brand-1 ) 110deg ,
276+ color-mix (in srgb , var (--vp-c-brand-1 ) 22%, transparent ) 160deg ,
277+ color-mix (in srgb , var (--vp-c-brand-1 ) 22%, transparent ) 360deg
278+ )
279+ border-box ;
280+ animation : sponsor-cta-shimmer 6s linear infinite ;
281+ transition : transform 0.35s ease ;
282+ }
283+
284+ .dark .sponsors-item-cta {
285+ background :
286+ linear-gradient (var (--vp-c-bg-soft ), var (--vp-c-bg-soft )) padding-box ,
287+ conic-gradient (
288+ from var (--sponsor-cta-angle ),
289+ color-mix(in srgb , var (--vp-c-brand-1 ) 18% , transparent ),
290+ color-mix(in srgb , var (--vp-c-brand-1 ) 18% , transparent ) 60deg ,
291+ var (--vp-c-brand-1 ) 110deg ,
292+ color-mix (in srgb , var (--vp-c-brand-1 ) 18%, transparent ) 160deg ,
293+ color-mix (in srgb , var (--vp-c-brand-1 ) 18%, transparent ) 360deg
294+ )
295+ border-box ;
296+ }
297+
298+ @keyframes sponsor-cta-shimmer {
299+ to {
300+ --sponsor-cta-angle : 360deg ;
301+ }
302+ }
303+
304+ /* .sponsors-item-cta:hover {
305+ transform: translateY(-2px);
306+ } */
307+
308+ .sponsors-item-cta :hover .cta-heart {
309+ color : var (--vp-c-brand-1 );
310+ transform : scale (1.08 );
311+ }
312+
313+ .sponsors-item-cta :hover .cta-heart path {
314+ fill : color-mix(in srgb , var (--vp-c-brand-1 ) 22% , transparent );
315+ }
316+
317+ @media (prefers-reduced-motion: reduce) {
318+ .sponsors-item-cta {
319+ animation : none ;
320+ }
321+ }
322+
323+ .cta-heart-wrap {
324+ position : relative ;
325+ display : block ;
326+ width : 26px ;
327+ height : 26px ;
328+ margin-bottom : 4px ;
329+ }
330+
331+ .cta-heart {
332+ display : block ;
333+ width : 100% ;
334+ height : 100% ;
335+ color : color-mix(in srgb , var (--vp-c-brand-1 ) 78% , transparent );
336+ transition :
337+ color 0.35s ease ,
338+ transform 0.35s ease ;
339+ }
340+
341+ .cta-heart path {
342+ transition : fill 0.35s ease ;
343+ }
344+
345+ /* Override global `.dark svg { fill: ... !important }` for the outline heart. */
346+ .dark .sponsors-item-cta .cta-heart {
347+ fill : none !important ;
348+ }
349+
350+ .cta-spark-layer {
351+ position : absolute ;
352+ inset : 0 ;
353+ pointer-events : none ;
354+ opacity : 0 ;
355+ transition : opacity 0.4s ease ;
356+ }
357+
358+ .sponsors-item-cta :hover .cta-spark-layer {
359+ opacity : 1 ;
360+ }
361+
362+ .cta-spark {
363+ position : absolute ;
364+ left : 50% ;
365+ top : 50% ;
366+ width : var (--size );
367+ height : var (--size );
368+ margin-left : calc (var (--size ) / -2 );
369+ margin-top : calc (var (--size ) / -2 );
370+ color : var (--vp-c-brand-1 );
371+ opacity : 0 ;
372+ filter : drop-shadow (
373+ 0 0 4px color-mix(in srgb , var (--vp-c-brand-1 ) 45% , transparent )
374+ );
375+ animation : cta-spark-emit var (--duration ) ease-out infinite ;
376+ animation-delay : var (--delay );
377+ animation-play-state : paused ;
378+ }
379+
380+ .sponsors-item-cta :hover .cta-spark {
381+ animation-play-state : running ;
382+ }
383+
384+ .cta-spark svg {
385+ display : block ;
386+ width : 100% ;
387+ height : 100% ;
388+ }
389+
390+ @keyframes cta-spark-emit {
391+ 0% {
392+ opacity : 0 ;
393+ transform : translate (0 , 0 ) scale (0.25 ) rotate (0deg );
394+ }
395+ 18% {
396+ opacity : 0.9 ;
397+ transform : translate (
398+ calc (var (--tx ) * 0.28 * var (--spray-scale )),
399+ calc (var (--ty ) * 0.28 * var (--spray-scale ))
400+ )
401+ scale (0.85 ) rotate (calc (var (--rot ) * 0.3 ));
402+ }
403+ 100% {
404+ opacity : 0 ;
405+ transform : translate (
406+ calc (var (--tx ) * var (--spray-scale )),
407+ calc (var (--ty ) * var (--spray-scale ))
408+ )
409+ scale (0.55 ) rotate (var (--rot ));
410+ }
411+ }
412+
413+ @media (prefers-reduced-motion: reduce) {
414+ .cta-spark-layer {
415+ display : none ;
416+ }
417+ }
418+
419+ .cta-title {
420+ font-size : 15px ;
421+ font-weight : 600 ;
422+ letter-spacing : -0.01em ;
423+ color : var (--vp-c-text-1 );
424+ }
425+
426+ .cta-subtitle {
427+ font-size : 11px ;
428+ font-weight : 500 ;
429+ letter-spacing : 0.04em ;
430+ text-transform : uppercase ;
431+ color : var (--vp-c-text-3 );
432+ }
433+
145434.dark .sponsors-item img {
146435 transition : all 0.2s ;
147436 filter : grayscale (1 ) invert (1 );
0 commit comments