use-active-overall-theme.tsx 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import { useUserSettingsContext } from '@/shared/context/user-settings-context'
  2. import { OverallTheme } from '@/shared/utils/styles'
  3. import { isIEEEBranded } from '@/utils/is-ieee-branded'
  4. import { useEffect, useMemo, useState } from 'react'
  5. import { useSplitTestContext } from '../context/split-test-context'
  6. export type ActiveOverallTheme = 'dark' | 'light'
  7. const mediaWatcher = window.matchMedia?.('(prefers-color-scheme: dark)') ?? {
  8. // If matchMedia is not supported, use the default (dark) theme
  9. matches: true,
  10. addEventListener: () => {},
  11. removeEventListener: () => {},
  12. }
  13. function getTheme(
  14. overallTheme: OverallTheme,
  15. prefersDark: boolean
  16. ): ActiveOverallTheme {
  17. if (isIEEEBranded()) {
  18. return 'dark'
  19. }
  20. if (overallTheme === 'light-') {
  21. return 'light'
  22. }
  23. if (overallTheme === 'system') {
  24. return prefersDark ? 'dark' : 'light'
  25. }
  26. return 'dark'
  27. }
  28. export const useActiveOverallTheme = (
  29. featureFlag?: string
  30. ): ActiveOverallTheme => {
  31. const { splitTestVariants } = useSplitTestContext()
  32. const [browserPrefersDarkMode, setBrowserPrefersDarkMode] = useState(
  33. mediaWatcher.matches
  34. )
  35. const {
  36. userSettings: { overallTheme },
  37. } = useUserSettingsContext()
  38. const activeOverallTheme = useMemo<ActiveOverallTheme>(() => {
  39. // Override theme if feature flag is provided and not enabled
  40. if (featureFlag && splitTestVariants[featureFlag] !== 'enabled') {
  41. return 'light'
  42. }
  43. return getTheme(overallTheme, browserPrefersDarkMode)
  44. }, [overallTheme, browserPrefersDarkMode, featureFlag, splitTestVariants])
  45. useEffect(() => {
  46. const listener = (e: MediaQueryListEvent) => {
  47. setBrowserPrefersDarkMode(e.matches)
  48. }
  49. mediaWatcher.addEventListener('change', listener)
  50. return () => {
  51. mediaWatcher.removeEventListener('change', listener)
  52. }
  53. }, [])
  54. return activeOverallTheme
  55. }