Hamburger menu slide direction

Hey everyone, I’m trying to configure (on mobile devices) the hamburger panel to slide out from the right-hand side of the screen, exactly the same as the profile panel is configured. I see there is a left: 0 rule that exists specifically for the hamburger panel. I’ve been tweaking the CSS but have been unable to replicate the slide-left behavior of the profile panel. There doesn’t appear to be a whole lot of CSS specific to the hamburger panel, so I’m not exactly sure what I’m missing.

I’d appreciate any tips or insights on what I may be missing here! Thanks all.

2 Likes

Hey Lukas, welcome to Meta :wave:

There’s isn’t a lot of CSS involved in this. The animation is handled with CSS, but the values for the offset are set in JavaScript to handle the case where the user scrolls/pans to the right or left to close the menus.

Most of that logic is here - that’s just one method; there’s a few others involved in that file
discourse/site-header.js at 8a250a1eac9032485e7d367f93e6ac418014e2ff · discourse/discourse · GitHub

There’s also some logic that handles the case when the user clicks on the dimmed background to close the menus.

for the user menu

discourse/user-menu.js at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub

For the hamburger menu

discourse/hamburger-menu.js at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub

Changing those to make the hamburger menu open and close on the right will involve two things.

  1. modify the site-header component with ModifyClass so that it opens all the menus from the right side. It currently checks for a class on the menu, so we simply override that like so

    api.modifyClass("component:site-header", {
      pluginId: "right-side-mobile-hamburger",
      _leftMenuClass() {
        // we don't want any left menus, so return false
        return false;
      }
    });
    
  2. when closing the menu, we also want it to close to the right side. For the scroll/pan event, this is already handled by the snippet above. Now we need to fix the case where the user clicks on the dimmed background. Discourse decides that based on whether or not the site uses an RTL language. To modify this, we need a different plugin-api method since the hamburger panel is a widget.

    The method we’re going to use is reopenWidget like so

     api.reopenWidget("hamburger-menu", {
      clickOutsideMobile() {
        // apply the code from core
        this._super(...arguments);
    
        // then make your change so that it closes to the right side
        const panel = document.querySelector(".menu-panel");
        const windowWidth = document.body.offsetWidth;
        panel.style.setProperty("--offset", `${windowWidth}px`);
      }
    });
    

Then all you need to do is add a couple of lines of CSS to override the default styles for that menu like so

.hamburger-panel,
.user-menu {
  .menu-panel.slide-in {
    left: unset;
    right: 0;
  }
}

Now let’s put all of that together. This goes in the mobile > header tab of your theme

<script type="text/discourse-plugin" version="0.8">
api.modifyClass("component:site-header", {
  pluginId: "right-side-mobile-hamburger",
  _leftMenuClass() {
    // we don't want any left menus, so return false
    return false;
  }
});

api.reopenWidget("hamburger-menu", {
  clickOutsideMobile() {
    // apply the code from core
    this._super(...arguments);

    // then make your change so that it closes to the right side
    const panel = document.querySelector(".menu-panel");
    const windowWidth = document.body.offsetWidth;
    panel.style.setProperty("--offset", `${windowWidth}px`);
  }
});
</script>

and this goes in mobile > CSS tab.

.hamburger-panel,
.user-menu {
  .menu-panel.slide-in {
    left: unset;
    right: 0;
  }
}

Once you save the theme and refresh the page, the hamburger menu will open and close on the right side on mobile - just like the user menu.

6 Likes

Now that’s how you provide a complete answer. Well done!

2 Likes

image

Amazing! Thank you so much for the detailed response Joe! A+ customer service, I am impressed and very thankful.

1 Like