@@ -20,8 +20,51 @@ const ETVRWordmark = () =>
2020 ' Docs'
2121 ] )
2222
23+ /**
24+ * Pointer highlight for the "frosted" controls, ported from the landing page's
25+ * script.js: a small radial gradient follows the cursor inside the surface via
26+ * --pointer-x / --pointer-y. Delegated from the document so it keeps working
27+ * after client-side navigation, and skipped for touch and reduced motion.
28+ */
29+ function setupFrostedGlow ( ) {
30+ const FROSTED = '.VPButton.alt, .VPSocialLink'
31+ const reducedMotion = window . matchMedia ( '(prefers-reduced-motion: reduce)' )
32+ let frame = 0
33+
34+ const surfaceOf = ( target : EventTarget | null ) =>
35+ target instanceof Element ? target . closest < HTMLElement > ( FROSTED ) : null
36+
37+ document . addEventListener ( 'pointermove' , ( event ) => {
38+ const surface = surfaceOf ( event . target )
39+ if ( ! surface || event . pointerType === 'touch' || reducedMotion . matches ) {
40+ return
41+ }
42+ const bounds = surface . getBoundingClientRect ( )
43+ cancelAnimationFrame ( frame )
44+ frame = requestAnimationFrame ( ( ) => {
45+ surface . style . setProperty ( '--pointer-x' , `${ event . clientX - bounds . left } px` )
46+ surface . style . setProperty ( '--pointer-y' , `${ event . clientY - bounds . top } px` )
47+ } )
48+ } )
49+
50+ document . addEventListener ( 'pointerout' , ( event ) => {
51+ const surface = surfaceOf ( event . target )
52+ if ( ! surface || surface . contains ( event . relatedTarget as Node ) ) {
53+ return
54+ }
55+ surface . style . removeProperty ( '--pointer-x' )
56+ surface . style . removeProperty ( '--pointer-y' )
57+ } )
58+ }
59+
2360const CustomTheme = {
2461 ...DefaultTheme ,
62+ enhanceApp ( ctx ) {
63+ DefaultTheme . enhanceApp ?.( ctx )
64+ if ( inBrowser ) {
65+ setupFrostedGlow ( )
66+ }
67+ } ,
2568 setup ( ) {
2669 const { lang } = useData ( )
2770 watchEffect ( ( ) => {
0 commit comments