ആധുനിക വെബ്‌സൈറ്റുകൾ കൂടുതൽ ആകർഷകമായ ദൃശ്യങ്ങളിലൂടെ ആളുകളുടെ ശ്രദ്ധ പിടിച്ചുപറ്റാൻ മത്സരിക്കുന്നു. പാരാലാക്സ് ഹീറോകൾ (Parallax heroes) വ്യൂപോർട്ടിലേക്ക് (viewport) ആഴത്തിൽ വ്യാപിച്ചു കിടക്കുന്നു. കറൗസലുകൾ (Carousels) അനന്തമായി സ്ക്രോൾ ചെയ്തുകൊണ്ടിരിക്കുന്നു. സൈൻഅപ്പ് ഫോമുകൾക്ക് പിന്നിൽ ബാക്ക്ഗ്രൗണ്ട് വീഡിയോകൾ ഓട്ടോപ്ലേ ആകുന്നു. ഒരു ഡിസൈൻ പോർട്ട്‌ഫോളിയോയിൽ ഇവ വളരെ മികച്ചതും ആകർഷകവുമായാണ് തോന്നുകയെങ്കിലും, നിങ്ങളുടെ പ്രേക്ഷകരിൽ ഒരു വിഭാഗത്തിന് ഇവ ശാരീരികമായ പ്രകോപനമായി മാറാം.

വെസ്റ്റിബുലാർ ഡിസോർഡറുകൾ (vestibular disorders) ഉള്ള ആളുകൾക്ക് തുടർച്ചയായ ചലനങ്ങളുള്ള വലിയ ഭാഗങ്ങൾ കാണുമ്പോൾ ഓക്കാനം, തലകറക്കം അല്ലെങ്കിൽ മൈഗ്രേൻ എന്നിവ അനുഭവപ്പെടാം. അവരെ സംരക്ഷിക്കുന്നതിനായി, എല്ലാ പ്രധാന ഓപ്പറേറ്റിംഗ് സിസ്റ്റങ്ങളിലും ഇപ്പോൾ "Reduce Motion" എന്ന ആക്സസിബിലിറ്റി സെറ്റിംഗ് ഉൾപ്പെടുത്തിയിട്ടുണ്ട്. വെബ് ബ്രൗസറുകൾ prefers-reduced-motion എന്ന മീഡിയ ക്വറിയിലൂടെ (media query) ഈ മുൻഗണന ലഭ്യമാക്കുന്നു. ഇത് കൃത്യമായി ഉപയോഗിക്കാൻ ആഗ്രഹിക്കുന്ന React ഡെവലപ്പർമാർക്ക് @reactuses/core-ൽ നിന്നുള്ള useReducedMotion ഹുക്ക് ഉപയോഗിക്കാവുന്നതാണ്. ഇത് OS മുൻഗണനയെ ഒരു ബൂളിയനായി (boolean) വായിക്കുന്നു, ഉപയോക്താവ് മാറ്റം വരുത്തിയാൽ തത്സമയം അപ്ഡേറ്റ് ചെയ്യുന്നു, കൂടാതെ സെർവർ-സൈഡ് റെൻഡറിംഗ് (server-side rendering) തകരാറിലാകാതെ കൈകാര്യം ചെയ്യുന്നു.

എന്തുകൊണ്ടാണ് സ്വയം നിർമ്മിക്കുന്ന പരിഹാരങ്ങൾ പരാജയപ്പെടുന്നത്

window.matchMedia('(prefers-reduced-motion: reduce)') ഉപയോഗിച്ച് നിങ്ങൾക്ക് ഈ മുൻഗണന സ്വയം പരിശോധിക്കാവുന്നതാണ്. പല ഡെവലപ്പർമാരും ഇത് ചെയ്യുന്നുണ്ടെങ്കിലും, പലപ്പോഴും ചെറിയ പിശകുകൾ (bugs) ഇതിലൂടെ സംഭവിക്കാറുണ്ട്.

ഒന്നാമതായി, 'change listener' മറന്നുപോകാൻ സാധ്യതയുണ്ട്. ഒരു കോംപോണന്റ് മൗണ്ട് (mount) ചെയ്യുമ്പോൾ ആദ്യത്തെ ക്വറി ഒരു തവണ മാത്രം പ്രവർത്തിക്കുന്നു. ഒരു കറൗസൽ (carousel) കാരണം അസ്വസ്ഥത തോന്നുന്ന ഒരു ഉപയോക്താവ് സിസ്റ്റം സെറ്റിംഗ്സിൽ പോയി 'Reduce Motion' ഓപ്ഷൻ മാറ്റിയാൽ, നിങ്ങളുടെ കോംപോണന്റിന് ആ മാറ്റം അറിയാൻ കഴിയില്ല. addEventListener ഉപയോഗിച്ച് ഇത് ശരിയായി ക്രമീകരിക്കുക, അൺമൗണ്ട് (unmount) ചെയ്യുമ്പോൾ അത് നീക്കം ചെയ്യുക, പഴയ addListener സിന്റാക്സ് പോളിഫിൽ (polyfill) ചെയ്യുക എന്നിവ സങ്കീർണ്ണമായ ജോലികളാണ്, ഇത് കോപ്പി-പേസ്റ്റ് പിശകുകൾക്ക് കാരണമാകും.

രണ്ടാമതായി, SSR സമയത്ത് window നിലവിലുണ്ടാവില്ല. നിങ്ങളുടെ ആപ്പ് സെർവറിൽ റെൻഡർ ചെയ്യുകയാണെങ്കിൽ, ഒരു സാധാരണ matchMedia കോൾ റെഫറൻസ് എറർ (reference error) ഉണ്ടാക്കുകയും റെൻഡറിംഗ് തടസ്സപ്പെടുത്തുകയും ചെയ്യും. ഇതിനെ ഒഴിവാക്കാൻ typeof window !== 'undefined' പോലുള്ള ഗാർഡുകൾ ഉപയോഗിക്കേണ്ടി വരും, കൂടാതെ ഡിഫോൾട്ട് വാല്യൂ എന്തായിരിക്കുമെന്ന് ഊഹിച്ചും ക്ലയന്റ് ഹൈഡ്രേഷൻ (client hydration) ശരിയാകുമെന്ന് പ്രതീക്ഷിച്ചും പ്രവർത്തിക്കേണ്ടി വരും.

മൂന്നാമതായി, ഓരോ അനിമേഷൻ കോംപോണന്റിലും ഈ ലോജിക് ആവർത്തിക്കുന്നത് മെയിന്റനൻസ് ഭാരം (maintenance debt) വർദ്ധിപ്പിക്കും. ഒരു ടീം അംഗം ലിസണർ ഒരു രീതിയിൽ എഴുതുന്നു, മറ്റൊരാൾ അത് പൂർണ്ണമായും ഒഴിവാക്കുന്നു, മൂന്നാമതൊരാൾ മോഷന് മുൻഗണന നൽകുന്ന രീതിയിൽ ഡിഫോൾട്ട് വാല്യൂ നൽകുന്നു. ഒരു ഹുക്ക് (hook) ഉപയോഗിക്കുന്നതിലൂടെ ഈ പ്രശ്നങ്ങൾ പരിഹരിക്കാം.

useReducedMotion ഈ മൂന്ന് പ്രശ്നങ്ങളും പരിഹരിക്കുന്നു. ഇത് ഒരു ലളിതമായ ബൂളിയൻ (boolean) നൽകുന്നു. സെർവറിൽ ഇത് സുരക്ഷിതമായി പ്രവർത്തിക്കുന്നു. ഇത് ലിസണർ സ്വയമേവ ഘടിപ്പിക്കുകയും (attach) നീക്കം ചെയ്യുകയും (clean up) ചെയ്യുന്നു.

ഇത് പ്രായോഗികമാക്കാൻ മൂന്ന് വഴികൾ

ബൂളിയൻ ലഭിച്ചു കഴിഞ്ഞാൽ, അത് എങ്ങനെ ഉപയോഗിക്കണം എന്നതിനെക്കുറിച്ച് ഒരു തന്ത്രം ആവശ്യമാണ്. ഒരു കോംപോണന്റ് മുതൽ ഒരു മുഴുവൻ ആപ്ലിക്കേഷൻ വരെ ഉപയോഗിക്കാൻ കഴിയുന്ന മൂന്ന് രീതികൾ താഴെ പറയുന്നവയാണ്.

1. അനാവശ്യ ജോലികൾ ഒഴിവാക്കാൻ CSS ക്ലാസുകൾ നിയന്ത്രിക്കുക

ഏറ്റവും നേരിട്ടുള്ള മാർഗ്ഗം, കനത്ത ജാവാസ്ക്രിപ്റ്റ് അനിമേഷൻ ലൂപ്പുകൾ (JavaScript animation loops) തുടങ്ങുന്നത് തന്നെ തടയുക എന്നതാണ്. സ്ക്രോൾ ഇവന്റുകൾ (scroll events) ശ്രദ്ധിക്കുകയും requestAnimationFrame ലൂപ്പിനുള്ളിൽ ലെയറുകൾ മാറ്റുകയും ചെയ്യുന്ന ഒരു പാരാലാക്സ് ഇമേജ് കോംപോണന്റ് ഉണ്ടെന്ന് കരുതുക. ആ ലോജിക് പ്രവർത്തിപ്പിച്ച ശേഷം അതിന്റെ ദൃശ്യഫലം തടയുന്നതിന് പകരം, ആദ്യം useReducedMotion പരിശോധിക്കുക.

ഹുക്ക് true എന്ന് നൽകുകയാണെങ്കിൽ, ഒരു സ്റ്റാറ്റിക് വേരിയന്റ് ക്ലാസ് ഉപയോഗിച്ച് കോംപോണന്റ് റെൻഡർ ചെയ്യുക, സ്ക്രോൾ ലിസണറുകൾ ബന്ധിപ്പിക്കുന്ന useEffect ഒഴിവാക്കുക. ഇത് ബ്രൗസറിന്റെ ജോലി കുറയ്ക്കുന്നു. ചലനങ്ങളോട് സെൻസിറ്റിവിറ്റിയുള്ള ഉപയോക്താക്കൾക്ക് ഒരു നിശ്ചിത ചിത്രം (fixed image) കാണാൻ സാധിക്കും. മറ്റുള്ളവർക്ക് ചലിക്കുന്ന ലെയറുകൾ കാണാം. അനിമേഷൻ കോഡ് ഒരിക്കലും പ്രവർത്തിക്കാത്തതിനാൽ, സിപിയു (CPU), ബാറ്ററി എന്നിവ ലാഭിക്കാനും ഇത് സഹായിക്കുന്നു.

2. അനിമേഷൻ ലൈബ്രറികളിലേക്ക് നേരിട്ട് നൽകുക

നിങ്ങൾ Framer Motion പോലുള്ള ഒരു ലൈബ്രറി ഉപയോഗിക്കുന്നുണ്ടെങ്കിൽ, ഈ ഹുക്ക് നിങ്ങളുടെ പ്രോപ്പ് ഡെഫനിഷനുകളിലേക്ക് (prop definitions) നേരിട്ട് ഉപയോഗിക്കാം. വേരിയന്റുകൾ (variants), ട്രാൻസിഷനുകൾ (transitions), ജെസ്റ്ററുകൾ (gestures) എന്നിവയ്ക്കായി മോഷൻ കോംപോണന്റുകൾ കോൺഫിഗറേഷൻ ഒബ്‌ജക്റ്റുകൾ സ്വീകരിക്കുന്നു. useReducedMotion-ൽ നിന്നുള്ള ബൂളിയൻ ഉപയോഗിച്ച് ട്രാൻസിഷനുകളിൽ duration: 0 എന്ന് കണ്ടിഷണലായി സെറ്റ് ചെയ്യാവുന്നതാണ്, അല്ലെങ്കിൽ