UX: Make Sidebar more consistent with user menu on mobile (#17940)

Before this commit, we carried custom code and styles for the sidebar on
mobile. This meant the look and feel of bringing up the sidebar on
mobile was very different from the user menu resulting in a very
inconsistent experience on mobile. Also, we could not leverage on the
existing swipe to close support on mobile.

In this commit, we made it such that the sidebar dropdown is always
rendered on mobile and made the interaction with the dropdown more
consistent with the user menu. There is also more parity with the old
hamburger dropdown when the experimental sidebar is disabled.
This commit is contained in:
Alan Guo Xiang Tan 2022-08-16 13:45:32 +08:00 committed by GitHub
parent e4de738f59
commit 7a05a9d411
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 86 additions and 107 deletions

View File

@ -0,0 +1,12 @@
import Component from "@glimmer/component";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
export default class SidebarHamburgerDropdown extends Component {
@service appEvents;
@action
triggerRenderedAppEvent() {
this.appEvents.trigger("sidebar-hamburger-dropdown:rendered");
}
}

View File

@ -225,6 +225,17 @@ const SiteHeaderComponent = MountWidget.extend(
this.appEvents.on("user-menu:rendered", this, "_animateMenu"); this.appEvents.on("user-menu:rendered", this, "_animateMenu");
} }
if (
this.siteSettings.enable_experimental_sidebar_hamburger &&
!this.sidebarEnabled
) {
this.appEvents.on(
"sidebar-hamburger-dropdown:rendered",
this,
"_animateMenu"
);
}
this.dispatch("notifications:changed", "user-notifications"); this.dispatch("notifications:changed", "user-notifications");
this.dispatch("header:keyboard-trigger", "header"); this.dispatch("header:keyboard-trigger", "header");
this.dispatch("user-menu:navigation", "user-menu"); this.dispatch("user-menu:navigation", "user-menu");
@ -341,6 +352,17 @@ const SiteHeaderComponent = MountWidget.extend(
this.appEvents.off("user-menu:rendered", this, "_animateMenu"); this.appEvents.off("user-menu:rendered", this, "_animateMenu");
} }
if (
this.siteSettings.enable_experimental_sidebar_hamburger &&
!this.sidebarEnabled
) {
this.appEvents.off(
"sidebar-hamburger-dropdown:rendered",
this,
"_animateMenu"
);
}
if (this.currentUser) { if (this.currentUser) {
this.currentUser.off("status-changed", this, "queueRerender"); this.currentUser.off("status-changed", this, "queueRerender");
} }
@ -373,6 +395,7 @@ const SiteHeaderComponent = MountWidget.extend(
_animateMenu() { _animateMenu() {
const menuPanels = document.querySelectorAll(".menu-panel"); const menuPanels = document.querySelectorAll(".menu-panel");
if (menuPanels.length === 0) { if (menuPanels.length === 0) {
if (this.site.mobileView) { if (this.site.mobileView) {
this._animate = true; this._animate = true;

View File

@ -74,6 +74,11 @@ export default Controller.extend({
return false; return false;
} }
// Always return dropdown on mobile
if (this.site.mobileView) {
return false;
}
return enableSidebar; return enableSidebar;
}, },

View File

@ -1,7 +1,7 @@
<div class="hamburger-panel"> <div class="hamburger-panel">
<div class="hamburger-menu revamped menu-panel drop-down" data-max-width="320"> <div class="revamped menu-panel drop-down" data-max-width="320" {{did-insert this.triggerRenderedAppEvent}}>
<div class="panel-body"> <div class="panel-body">
<div class="panel-body-content"> <div class="panel-body-contents">
<div class="sidebar-hamburger-dropdown"> <div class="sidebar-hamburger-dropdown">
<Sidebar::Sections @collapsableSections={{false}}/> <Sidebar::Sections @collapsableSections={{false}}/>
<Sidebar::Footer @tagName="" /> <Sidebar::Footer @tagName="" />

View File

@ -589,7 +589,7 @@ export default createWidget("header", {
toggleHamburger() { toggleHamburger() {
if ( if (
this.siteSettings.enable_experimental_sidebar_hamburger && this.siteSettings.enable_experimental_sidebar_hamburger &&
(this.attrs.sidebarEnabled || this.site.mobileView) this.attrs.sidebarEnabled
) { ) {
this.sendWidgetAction("toggleSidebar"); this.sendWidgetAction("toggleSidebar");
} else { } else {

View File

@ -18,7 +18,10 @@ acceptance("Sidebar - Mobile - User with sidebar enabled", function (needs) {
test("hidden by default", async function (assert) { test("hidden by default", async function (assert) {
await visit("/"); await visit("/");
assert.ok(!exists(".sidebar-container"), "sidebar is not displayed"); assert.ok(
!exists(".sidebar-hamburger-dropdown"),
"sidebar is not displayed"
);
}); });
test("clicking outside sidebar collapses it", async function (assert) { test("clicking outside sidebar collapses it", async function (assert) {
@ -26,11 +29,11 @@ acceptance("Sidebar - Mobile - User with sidebar enabled", function (needs) {
await click(".hamburger-dropdown"); await click(".hamburger-dropdown");
assert.ok(exists(".sidebar-container"), "sidebar is displayed"); assert.ok(exists(".sidebar-hamburger-dropdown"), "sidebar is displayed");
await click("#main-outlet"); await click("#main-outlet");
assert.ok(!exists(".sidebar-container"), "sidebar is collapsed"); assert.ok(!exists(".sidebar-hamburger-dropdown"), "sidebar is collapsed");
}); });
test("clicking on a link or button in sidebar collapses it", async function (assert) { test("clicking on a link or button in sidebar collapses it", async function (assert) {
@ -40,7 +43,7 @@ acceptance("Sidebar - Mobile - User with sidebar enabled", function (needs) {
await click(".sidebar-section-link-tracked"); await click(".sidebar-section-link-tracked");
assert.ok( assert.ok(
!exists(".sidebar-container"), !exists(".sidebar-hamburger-dropdown"),
"sidebar is collapsed when a button in sidebar is clicked" "sidebar is collapsed when a button in sidebar is clicked"
); );
@ -48,28 +51,11 @@ acceptance("Sidebar - Mobile - User with sidebar enabled", function (needs) {
await click(".sidebar-section-header-link"); await click(".sidebar-section-header-link");
assert.ok( assert.ok(
!exists(".sidebar-container"), !exists(".sidebar-hamburger-dropdown"),
"sidebar is collapsed when a link in sidebar is clicked" "sidebar is collapsed when a link in sidebar is clicked"
); );
}); });
test("collapsing sidebar sections does not collapse sidebar", async function (assert) {
await visit("/");
await click(".hamburger-dropdown");
await click(".sidebar-section-header-caret");
assert.ok(
!exists(".sidebar-section-community .sidebar-section-content"),
"topics section is collapsed"
);
assert.ok(
exists(".sidebar-container"),
"sidebar is not collapsed when clicking on caret to collapse a section in sidebar"
);
});
test("button to toggle between mobile and desktop view", async function (assert) { test("button to toggle between mobile and desktop view", async function (assert) {
await visit("/"); await visit("/");
await click(".hamburger-dropdown"); await click(".hamburger-dropdown");

View File

@ -601,31 +601,3 @@ div.menu-links-header {
color: var(--primary-med-or-secondary-med); color: var(--primary-med-or-secondary-med);
} }
} }
// Sidebar-hamburger hybrid
.hamburger-menu.revamped {
--d-sidebar-highlight-color: var(--highlight-medium);
width: var(--d-sidebar-width);
.panel-body-content {
width: 100%;
min-width: 0; // prevent content blowing out width
}
.sidebar-section-wrapper {
.sidebar-section-header-button {
opacity: 1;
}
.sidebar-section-link.active {
font-weight: normal;
color: var(--primary-high);
background: var(--tertiary-low);
}
}
.sidebar-footer-wrapper {
padding: 0.5em 0 0;
}
}

View File

@ -80,7 +80,7 @@
} }
} }
.hamburger-menu.revamped { .hamburger-panel .revamped {
.sidebar-footer-wrapper { .sidebar-footer-wrapper {
background: var(--secondary); background: var(--secondary);
.sidebar-footer-container { .sidebar-footer-container {

View File

@ -1,6 +1,4 @@
.sidebar-more-section-links-details { .sidebar-more-section-links-details {
margin-left: 1.5em;
.sidebar-more-section-links-details-summary { .sidebar-more-section-links-details-summary {
padding: 0.35em 0.5em; padding: 0.35em 0.5em;
color: var(--primary-high); color: var(--primary-high);
@ -41,3 +39,9 @@
border-top: 1.5px solid var(--primary-low); border-top: 1.5px solid var(--primary-low);
} }
} }
#main-outlet-wrapper {
.sidebar-more-section-links-details {
margin-left: 1.5em;
}
}

View File

@ -7,3 +7,31 @@
max-height: calc(100vh - 100px); max-height: calc(100vh - 100px);
} }
} }
// Sidebar-hamburger hybrid
.hamburger-panel .revamped {
--d-sidebar-highlight-color: var(--highlight-medium);
width: var(--d-sidebar-width);
.panel-body-content {
width: 100%;
min-width: 0; // prevent content blowing out width
}
.sidebar-section-wrapper {
.sidebar-section-header-button {
opacity: 1;
}
.sidebar-section-link.active {
font-weight: normal;
color: var(--primary-high);
background: var(--tertiary-low);
}
}
.sidebar-footer-wrapper {
padding: 0.5em 0 0;
}
}

View File

@ -140,54 +140,3 @@ blockquote {
#simple-container { #simple-container {
width: 90%; width: 90%;
} }
// Sidebar styles
#main-outlet-wrapper {
grid-template-columns: minmax(0, 100vw);
grid-template-areas: "content";
gap: 0;
.sidebar-wrapper {
width: 0;
transition: width 0.2s ease-in-out;
z-index: z("modal", "content");
grid-area: content;
justify-self: end;
}
.sidebar-container {
padding-bottom: 6.6em; // extra space to watch out for navbar
}
}
body.has-sidebar-page {
.d-header-wrap {
// edits the z-index when the sidebar is open:
// header
// sidebar & body overlay
// composer
z-index: z("modal", "content") + 1;
}
#main-outlet-wrapper {
.sidebar-wrapper {
width: var(--d-sidebar-width);
margin-right: -10px; // compensate for main-outlet-wrapper padding
}
}
#main-outlet {
&:after {
content: "";
background: rgb(0, 0, 0); // always a black overlay
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: z("modal", "overlay");
opacity: 0.5;
}
}
}