כיוון החלקה של תפריט המבורגר

סיכום מבוסס בינה מלאכותית

The discussion revolves around configuring the hamburger menu on mobile devices to slide out from the right side, similar to the profile panel. lstuartfry seeks help with CSS and JavaScript adjustments to achieve this. Johani provides a detailed solution involving modifying the site-header component and the hamburger-menu widget using Discourse’s plugin API. The approach includes overriding the _leftMenuClass method to disable left-side menus and adjusting the clickOutsideMobile method to set the panel’s offset to the right. CSS is also required to override default styles, ensuring the menu slides from the right. asirota praises the thoroughness of the response, and lstuartfry expresses gratitude, confirming the solution works.

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.

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/app/assets/javascripts/discourse/app/components/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/app/assets/javascripts/discourse/app/widgets/user-menu.js at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub

For the hamburger menu

discourse/app/assets/javascripts/discourse/app/widgets/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.

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

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