5

I can't seem to find a solution to this on any of the documentation. All I want is have a button toggle to switch between a light and dark mode.

kmurp62rulz
  • 169
  • 2
  • 9
  • Maybe this tutorial is helping? https://levelup.gitconnected.com/dark-mode-in-react-533faaee3c6e – David Jul 10 '22 at 08:43

4 Answers4

22

It's not really necessary to install an additional npm package to achieve theme switching.

If all you want to achieve is having a toggle, you can list the desired themes in your tailwind.config.cjs file like so:

plugins: [require('daisyui')],
daisyui: {
  themes: ['light', 'dark'],
},

And then in your component, have a state, a toggle function and a useEffect that handles attribute injection into the HTML tag of the document (we want to have the global theme as an attribute in the html element as per the daisyUI docs: https://daisyui.com/docs/themes/)

function MyAwesomeThemeComponent() {
  const [theme, setTheme] = React.useState('light');
  const toggleTheme = () => {
    setTheme(theme === 'dark' ? 'light' : 'dark');
  };
  // initially set the theme and "listen" for changes to apply them to the HTML tag
  React.useEffect(() => {
    document.querySelector('html').setAttribute('data-theme', theme);
  }, [theme]);
  return (
    <label className="swap swap-rotate">
      <input onClick={toggleTheme} type="checkbox" />
      <div className="swap-on">DARKMODE</div>
      <div className="swap-off">LIGHTMODE</div>
    </label>
  );
}
SaHeinem
  • 358
  • 1
  • 3
  • 10
4

Install the package called theme-change https://www.npmjs.com/package/theme-change and then for react

index.tsx

import { themeChange } from 'theme-change';

/*Initialize under useEffect */

useEffect(() => {
    themeChange(false);
  }, []);

Then on navigation menu or top bar

<select className="gradientselect" data-choose-theme>
        <option disabled value="">
          Pick a theme
        </option>
        <option value="">Default</option>
        <option value="light">Light</option>
        <option value="retro">Retro</option>
        <option value="dracula">Dracula</option>
        <option value="cyberpunk">Cyberpunk</option>
 </select>

Make sure to check the docs for more info on https://github.com/saadeghi/theme-change

Nabin Thapa
  • 86
  • 1
  • 4
2

Create a state variable to store the selected theme

const [theme, setTheme] = useState(localStorage.getItem("theme") ?? "light");

create function to handle theme toggle

const handleToggle = (e: any) => {
  if (e.target.checked) {
    setTheme("winter");
  } else {
    setTheme("night");
  }
};

Save the selected theme to localStorage and update the theme attribute on the root element

useEffect(() => {
    localStorage.setItem('theme', theme!)
    const localTheme = localStorage.getItem('theme')
    document.querySelector('html')?.setAttribute('data-theme', localTheme!)
}, [theme]);

And you can use 'handleToggle' at 'Swap' from DaisyUI

<label className="swap swap-rotate">
  {/* this hidden checkbox controls the state */}
  <input type="checkbox" onChange={handleToggle} />
  {/* sun icon */}
  <svg className="swap-on fill-current w-10 h-10" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z"/></svg>
  {/* moon icon */}
  <svg className="swap-off fill-current w-10 h-10" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z"/></svg>
</label>
Fabio Nettis
  • 1,150
  • 6
  • 18
Jivelocity
  • 21
  • 2
1

I use the react-daisyui package. It abstracts all of the daisyui components as react components.

It even has a theme component

Example from official documentation:

import { Theme, Button } from 'react-daisyui'

export default (props) => {
  return (
    <>
      <Theme dataTheme="dark">
        <Button color="primary">Click me, dark!</Button>
      </Theme>

      <Theme dataTheme="light">
        <Button color="primary">Click me, light!</Button>
      </Theme>
    </>
  )
}
Ivan P.
  • 480
  • 2
  • 5
  • 10