dark mode with toggle button on navbar and sidebar menu

Tips submitted by PHPMaker users
Post Reply
yusufnalbantoglu
User
Posts: 12

dark mode with toggle button on navbar and sidebar menu

Post by yusufnalbantoglu »

Hi,

1st Step
PHPMaker -> Under the HTML -> Theme tab, search "enable-dark-mode", generate all scripts again.

2nd Step
add all codes global > Startup Script

// for add toggle on Navbar
$( "#ew-navbar-end" ).prepend( "<li class='nav-item d-none d-sm-block'><div class='nav-link form-check custom-control form-switch'><input class='form-check-input' type='checkbox' role='switch' id='flexSwitchCheckDefault'><label class='form-check-label' for='flexSwitchCheckDefault'>Dark Theme</label></div></li>" );

//for add toggle on Sidebar Menu
$( ".nav-sidebar" ).append( "<li style='padding-left: 3.5em;' class='nav-item d-block d-sm-none'><div class='nav-link form-check custom-control form-switch'><input class='form-check-input' type='checkbox' role='switch' id='flexSwitchCheckDefault'><label class='form-check-label' for='flexSwitchCheckDefault'>Dark Theme</label></div></li>" );

  //check for localStorage, add as browser preference if missing
  if (!localStorage.getItem("mode")) {
    if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
      localStorage.setItem("mode", "dark-theme");
    } else {
      localStorage.setItem("mode", "light-theme");
    }
  }

  //set interface to match localStorage
  if (localStorage.getItem("mode") == "dark-theme") {
    $("body").addClass("dark-mode");
    $("body").removeClass("light-mode");
    document.getElementById("flexSwitchCheckDefault").checked = true;
  } else {
    $("body").removeClass("dark-mode");
    $("body").addClass("light-mode");
    document.getElementById("flexSwitchCheckDefault").checked = false;
  }

  //toggle function
  $("#flexSwitchCheckDefault").click(function() {
    if ($("body").hasClass("dark-mode")) {
      $("body").removeClass("dark-mode");
      $("body").addClass("light-mode");
      localStorage.setItem("mode", "light-theme");
    } else {
      $("body").addClass("dark-mode");
      $("body").removeClass("light-mode");
      localStorage.setItem("mode", "dark-theme");
    }
  });

SilentNight
User
Posts: 171

Post by SilentNight »

This is awesome, thanks for sharing!


saleh
User
Posts: 470

Post by saleh »

Awesome thank you


maxikay
User
Posts: 6

Post by maxikay »

Super.
Thanks alot. it works


darkdragon
User
Posts: 148

Post by darkdragon »

Great add-on!


mobhar
User
Posts: 11660

Post by mobhar »

Some limitations are:

  1. If we use sidebar-light-* option of Sidebar class under HTML -> Theme -> AdminLTE, then the sidebar is not converted to dark-mode. It stays on light mode which will make the display becomes glare. This can be happened because it has not handled the color-convertion to dark-mode in Sidebar section.

  2. When we are in dark-mode, and after switching to another page, then the background will display white color for one second, after that it will turn into dark-mode. This can be happened because the code only check the logic from client-side, and not including the server side code.


yusufnalbantoglu
User
Posts: 12

Post by yusufnalbantoglu »

UPDATE:

The first version was client-side. The current version is server-side based. In this update, the theme preference is saved to the session and there are no problems with page transitions.

STEPS:

  1. Add codes > Server Events > Global > Page_Loading

        if (session_status() == PHP_SESSION_NONE) {
            session_start();
        }
        
        if (!isset($_SESSION['theme'])) {
            $_SESSION['theme'] = 'light-theme';
        }
    
        $themeClass = $_SESSION['theme'] === 'dark-theme' ? 'dark-mode' : 'light-mode';
        Config("BODY_CLASS", Config("BODY_CLASS") . " " . $themeClass);
        return true;
  2. Create a php file named update_theme.php in the application directory and add these codes.

    <?php
    if (session_status() == PHP_SESSION_NONE) {
        session_start();
    }
    
    if (isset($_POST['theme'])) {
        $_SESSION['theme'] = $_POST['theme'];
        echo 'success';
    } else {
        echo 'error';
    }
    ?>
  3. Add codes > Client Scripts > Global > Startup Script

    //Toggle add Navbar
    $( "#ew-navbar-end" ).prepend( "<li class='nav-item d-none d-sm-block'><div class='nav-link form-check custom-control form-switch'><input class='form-check-input' type='checkbox' role='switch' id='flexSwitchCheckDefault'><label class='form-check-label' for='flexSwitchCheckDefault'>Dark Theme</label></div></li>" );
    
    //Toggle add Sidebar Menu
    $( ".nav-sidebar" ).append( "<li class='nav-item d-block d-sm-none'><div class='nav-link'><label class='form-check-label' for='flexSwitchCheckDefault'>Dark Theme</label></div></li>" );
    
    
      $("#flexSwitchCheckDefault").prop("checked", $("body").hasClass("dark-mode"));
    
      $("#flexSwitchCheckDefault").click(function() {
        if ($("body").hasClass("dark-mode")) {
          $("body").removeClass("dark-mode");
          $("body").addClass("light-mode");
          updateTheme("light-theme");
        } else {
          $("body").addClass("dark-mode");
          $("body").removeClass("light-mode");
          updateTheme("dark-theme");
        }
      });
    
      function updateTheme(theme) {
        $.ajax({
          url: 'update_theme.php',
          type: 'POST',
          data: { theme: theme },
          success: function(response) {
            if (response === 'success') {
              location.reload();
            } else {
              console.error('Theme update failed');
            }
          },
          error: function() {
            console.error('Theme update failed');
          }
        });
      }

Note: These changes allow the Global Page_Loading function to add the correct theme class to BODY_CLASS after reloading the page following a theme change.

It is hoped that these changes will reduce transition time by applying the correct theme class when the page loads and help preserve user preferences during page transitions.

Thank you everyone.


mobhar
User
Posts: 11660

Post by mobhar »

No need to create "update_theme.php" file in step #2. You may simply use Api_Action server event instead:

    $app->get('/updateTheme/{theme}', function ($request, $response, $args) {
        $theme = $args["theme"] ?? null; // get theme
        if (session_status() == PHP_SESSION_NONE) {
            session_start();
        }
        if (isset($theme)) {
            $_SESSION['theme'] = $theme;
            return $response->write('success');
        } else {
            return $response->write('error');
        }
    });

After that, change this part from Global Startup Script:
updateTheme("light-theme");

to:

      $.get(ew.getApiUrl(["updateTheme", "light-theme"]), function(res) {
        if (res == "success") {
          window.location.reload();
        } else {
          console.error('Theme update failed'); 
        }
      });

and this part:
updateTheme("dark-theme");

to:

      $.get(ew.getApiUrl(["updateTheme", "dark-theme"]), function(res) {
        if (res == "success") {
          window.location.reload();
        } else {
          console.error('Theme update failed'); 
        }
      });

mobhar
User
Posts: 11660

Post by mobhar »

In addition, this code:

        if (res == "success") {
          window.location.reload();
        } else {
          console.error('Theme update failed'); 
        }

should be only just like this:

        if (res == "error")
          console.error('Theme update failed');

In other words, no need to reload the current page after switching the dark-mode, since the session has been handled by the Api_Action server event.


rembo
User
Posts: 227

Post by rembo »

perfect ....


Post Reply