All files / src/components/ThemeSwitcher ThemeSwitcher.tsx

100% Statements 20/20
100% Branches 12/12
100% Functions 4/4
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 661x                   1x 26x 26x 26x 26x 26x   26x 13x       26x 13x 13x 6x       26x 4x 4x 4x     26x 13x                         13x                                
'use client';
 
import { ActionIcon, useMantineColorScheme } from '@mantine/core';
import { useTranslations } from 'next-intl';
import { type FC, useEffect, useState } from 'react';
import { FiMoon, FiSun } from 'react-icons/fi';
import { useAppDispatch } from '@/lib/store';
import { setDarkMode } from '@/lib/store/global';
import { useIsDarkMode } from '@/lib/store/global/selectors';
 
const ThemeSwitcher: FC = () => {
  const translate = useTranslations('common');
  const dispatch = useAppDispatch();
  const isDarkMode = useIsDarkMode();
  const { colorScheme, setColorScheme } = useMantineColorScheme();
  const [mounted, setMounted] = useState(false);
 
  useEffect(() => {
    setMounted(true);
  }, []);
 
  // Sync Mantine color scheme with Redux state on mount and when isDarkMode changes
  useEffect(() => {
    const targetScheme = isDarkMode ? 'dark' : 'light';
    if (colorScheme !== targetScheme) {
      setColorScheme(targetScheme);
    }
  }, [isDarkMode, setColorScheme, colorScheme]);
 
  const handleToggleTheme = () => {
    const newDarkMode = !isDarkMode;
    dispatch(setDarkMode(newDarkMode));
    setColorScheme(newDarkMode ? 'dark' : 'light');
  };
 
  if (!mounted) {
    return (
      <ActionIcon
        variant="subtle"
        color="gray"
        size="lg"
        aria-label={translate('toggleTheme')}
        data-testid="theme-toggle"
      >
        <div style={{ width: 20, height: 20 }} />
      </ActionIcon>
    );
  }
 
  return (
    <ActionIcon
      variant="subtle"
      color="gray"
      size="lg"
      onClick={handleToggleTheme}
      aria-label={translate('toggleTheme')}
      data-testid="theme-toggle"
      title={isDarkMode ? translate('lightMode') : translate('darkMode')}
    >
      {isDarkMode ? <FiSun size={20} /> : <FiMoon size={20} />}
    </ActionIcon>
  );
};
 
export default ThemeSwitcher;