UX: Allow opening user-menu tabs in new tab/window (#20792)

This commit turns the new user menu tabs into `<a href` elements. This means that the tab's associated URL is shown on mouseover, and also allows the browser to handle navigation when a modifier key is pressed (e.g. ctrl, shift, mod).
This commit is contained in:
David Taylor 2023-03-24 08:18:23 +00:00 committed by GitHub
parent ed6f7b1e6d
commit d2617c4904
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 12 deletions

View File

@ -1,5 +1,4 @@
<button
type="button"
<a
role="tab"
class={{this.classNames}}
id={{this.id}}
@ -8,12 +7,12 @@
aria-selected={{if this.isActive "true" "false"}}
aria-controls={{this.ariaControls}}
data-tab-number={{@tab.position}}
href={{@tab.linkWhenActive}}
{{on "click" @onTabClick}}
{{! template-lint-disable require-context-role }}
>
{{d-icon @tab.icon}}
{{#if @tab.count}}
<span aria-hidden="true" class="badge-notification">{{@tab.count}}</span>
{{/if}}
{{yield}}
</button>
</a>

View File

@ -5,7 +5,7 @@ import { NO_REMINDER_ICON } from "discourse/models/bookmark";
import UserMenuTab, { CUSTOM_TABS_CLASSES } from "discourse/lib/user-menu/tab";
import { inject as service } from "@ember/service";
import getUrl from "discourse-common/lib/get-url";
import DiscourseURL from "discourse/lib/url";
import { wantsNewWindow } from "discourse/lib/intercept-click";
const DEFAULT_TAB_ID = "all-notifications";
const DEFAULT_PANEL_COMPONENT = "user-menu/notifications-list";
@ -314,14 +314,17 @@ export default class UserMenu extends Component {
}
@action
handleTabClick(tab) {
if (this.currentTabId !== tab.id) {
this.currentTabId = tab.id;
this.currentPanelComponent = tab.panelComponent;
this.currentNotificationTypes = tab.notificationTypes;
} else if (tab.linkWhenActive) {
DiscourseURL.routeTo(tab.linkWhenActive);
handleTabClick(tab, event) {
if (wantsNewWindow(event) || this.currentTabId === tab.id) {
// Allow normal navigation to href
return;
}
event.preventDefault();
this.currentTabId = tab.id;
this.currentPanelComponent = tab.panelComponent;
this.currentNotificationTypes = tab.notificationTypes;
}
@action

View File

@ -748,6 +748,34 @@ acceptance("User menu", function (needs) {
await click("#site-logo");
}
});
test("tabs have hrefs and can be opened in new window/tab", async function (assert) {
await visit("/");
await click(".d-header-icons .current-user");
assert
.dom("#user-menu-button-replies")
.hasAttribute("href", "/u/eviltrout/notifications/responses");
// Add a top-level click listener to stub attempts to open a new window/tab
const newWindowOpenedAssertion = assert.async();
const interceptor = (event) => {
event.preventDefault();
newWindowOpenedAssertion();
const target = event.target;
assert.strictEqual(target.tagName, "A");
assert.true(target.href.endsWith("/u/eviltrout/notifications/responses"));
};
window.addEventListener("click", interceptor);
try {
await click("#user-menu-button-replies", { shiftKey: true });
} finally {
window.removeEventListener("click", interceptor);
}
});
});
acceptance("User menu - Dismiss button", function (needs) {