mirror of
https://github.com/discourse/discourse.git
synced 2025-06-08 11:07:17 +08:00
UX: replaces custom more menu by d-menu (#29090)
One of the big advantages is a nicer menu on mobile. This commit also fixes a bug where the close modal action was called for any destroyed d-menu trigger, even if this specific menu was not expanding, which means it was closing a different modal than its own modal, given we can only have one modal at a time.
This commit is contained in:
@ -158,6 +158,12 @@ export default class DModal extends Component {
|
|||||||
this.closeModal(CLOSE_INITIATED_BY_SWIPE_DOWN);
|
this.closeModal(CLOSE_INITIATED_BY_SWIPE_DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
handleWrapperPointerDown(e) {
|
||||||
|
// prevents hamburger menu to close on modal backdrop click
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
handleWrapperClick(e) {
|
handleWrapperClick(e) {
|
||||||
if (e.button !== 0) {
|
if (e.button !== 0) {
|
||||||
@ -396,6 +402,8 @@ export default class DModal extends Component {
|
|||||||
enabled=this.dismissable
|
enabled=this.dismissable
|
||||||
}}
|
}}
|
||||||
{{on "click" this.handleWrapperClick}}
|
{{on "click" this.handleWrapperClick}}
|
||||||
|
{{! template-lint-disable no-pointer-down-event-binding }}
|
||||||
|
{{on "pointerdown" this.handleWrapperPointerDown}}
|
||||||
></div>
|
></div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
</ConditionalInElement>
|
</ConditionalInElement>
|
||||||
|
@ -12,7 +12,7 @@ import closeOnClickOutside from "../../modifiers/close-on-click-outside";
|
|||||||
import SidebarHamburgerDropdown from "../sidebar/hamburger-dropdown";
|
import SidebarHamburgerDropdown from "../sidebar/hamburger-dropdown";
|
||||||
|
|
||||||
const CLOSE_ON_CLICK_SELECTORS =
|
const CLOSE_ON_CLICK_SELECTORS =
|
||||||
"a[href], .sidebar-section-header-button, .sidebar-section-link-button, .sidebar-section-link";
|
"a[href], .sidebar-section-header-button, .sidebar-section-link:not(.--link-button)";
|
||||||
|
|
||||||
export default class HamburgerDropdownWrapper extends Component {
|
export default class HamburgerDropdownWrapper extends Component {
|
||||||
@service currentUser;
|
@service currentUser;
|
||||||
@ -37,6 +37,10 @@ export default class HamburgerDropdownWrapper extends Component {
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
clickOutside(e) {
|
clickOutside(e) {
|
||||||
|
if (e.target.closest(".sidebar-more-section-content")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
e.target.classList.contains("header-cloak") &&
|
e.target.classList.contains("header-cloak") &&
|
||||||
!prefersReducedMotion()
|
!prefersReducedMotion()
|
||||||
@ -101,6 +105,7 @@ export default class HamburgerDropdownWrapper extends Component {
|
|||||||
>
|
>
|
||||||
<SidebarHamburgerDropdown
|
<SidebarHamburgerDropdown
|
||||||
@forceMainSidebarPanel={{this.forceMainSidebarPanel}}
|
@forceMainSidebarPanel={{this.forceMainSidebarPanel}}
|
||||||
|
@toggleNavigationMenu={{this.toggleNavigation}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -9,7 +9,10 @@ export default class SidebarAnonymousSections extends Component {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="sidebar-sections sidebar-sections-anonymous">
|
<div class="sidebar-sections sidebar-sections-anonymous">
|
||||||
<CustomSections @collapsable={{@collapsableSections}} />
|
<CustomSections
|
||||||
|
@collapsable={{@collapsableSections}}
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
|
/>
|
||||||
<CategoriesSection @collapsable={{@collapsableSections}} />
|
<CategoriesSection @collapsable={{@collapsableSections}} />
|
||||||
|
|
||||||
{{#if this.siteSettings.tagging_enabled}}
|
{{#if this.siteSettings.tagging_enabled}}
|
||||||
|
@ -93,6 +93,7 @@ export default class SidebarCustomSection extends Component {
|
|||||||
@moreButtonAction={{this.section.moreSectionButtonAction}}
|
@moreButtonAction={{this.section.moreSectionButtonAction}}
|
||||||
@moreButtonText={{this.section.moreSectionButtonText}}
|
@moreButtonText={{this.section.moreSectionButtonText}}
|
||||||
@moreButtonIcon={{this.section.moreSectionButtonIcon}}
|
@moreButtonIcon={{this.section.moreSectionButtonIcon}}
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else if this.section.moreSectionButtonAction}}
|
{{else if this.section.moreSectionButtonAction}}
|
||||||
|
@ -24,7 +24,11 @@ export default class SidebarCustomSections extends Component {
|
|||||||
<template>
|
<template>
|
||||||
<div class="sidebar-custom-sections">
|
<div class="sidebar-custom-sections">
|
||||||
{{#each this.sections as |section|}}
|
{{#each this.sections as |section|}}
|
||||||
<CustomSection @sectionData={{section}} @collapsable={{@collapsable}} />
|
<CustomSection
|
||||||
|
@sectionData={{section}}
|
||||||
|
@collapsable={{@collapsable}}
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
|
/>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -66,6 +66,7 @@ export default class SidebarHamburgerDropdown extends Component {
|
|||||||
@collapsableSections={{this.collapsableSections}}
|
@collapsableSections={{this.collapsableSections}}
|
||||||
@panel={{this.sidebarState.currentPanel}}
|
@panel={{this.sidebarState.currentPanel}}
|
||||||
@hideApiSections={{@forceMainSidebarPanel}}
|
@hideApiSections={{@forceMainSidebarPanel}}
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
/>
|
/>
|
||||||
{{else}}
|
{{else}}
|
||||||
<ApiPanels
|
<ApiPanels
|
||||||
|
@ -20,6 +20,8 @@ const SidebarMoreSectionLink = <template>
|
|||||||
@suffixType={{@sectionLink.suffixType}}
|
@suffixType={{@sectionLink.suffixType}}
|
||||||
@suffixValue={{@sectionLink.suffixValue}}
|
@suffixValue={{@sectionLink.suffixValue}}
|
||||||
@title={{@sectionLink.title}}
|
@title={{@sectionLink.title}}
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
|
...attributes
|
||||||
/>
|
/>
|
||||||
</template>;
|
</template>;
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { fn } from "@ember/helper";
|
||||||
import { on } from "@ember/modifier";
|
import { on } from "@ember/modifier";
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
|
||||||
import willDestroy from "@ember/render-modifiers/modifiers/will-destroy";
|
|
||||||
import { service } from "@ember/service";
|
import { service } from "@ember/service";
|
||||||
import { isEmpty } from "@ember/utils";
|
import { isEmpty } from "@ember/utils";
|
||||||
|
import DropdownMenu from "discourse/components/dropdown-menu";
|
||||||
import icon from "discourse/helpers/d-icon";
|
import icon from "discourse/helpers/d-icon";
|
||||||
import { bind } from "discourse/lib/decorators";
|
|
||||||
import { i18n } from "discourse-i18n";
|
import { i18n } from "discourse-i18n";
|
||||||
|
import DMenu from "float-kit/components/d-menu";
|
||||||
import MoreSectionLink from "./more-section-link";
|
import MoreSectionLink from "./more-section-link";
|
||||||
import SectionLinkButton from "./section-link-button";
|
import SectionLinkButton from "./section-link-button";
|
||||||
|
|
||||||
@ -16,7 +16,6 @@ export default class SidebarMoreSectionLinks extends Component {
|
|||||||
@service router;
|
@service router;
|
||||||
|
|
||||||
@tracked activeSectionLink;
|
@tracked activeSectionLink;
|
||||||
@tracked open = false;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
@ -26,7 +25,6 @@ export default class SidebarMoreSectionLinks extends Component {
|
|||||||
|
|
||||||
willDestroy() {
|
willDestroy() {
|
||||||
super.willDestroy(...arguments);
|
super.willDestroy(...arguments);
|
||||||
this.#removeClickEventListener();
|
|
||||||
this.router.off("routeDidChange", this, this.#setActiveSectionLink);
|
this.router.off("routeDidChange", this, this.#setActiveSectionLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,53 +50,6 @@ export default class SidebarMoreSectionLinks extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@bind
|
|
||||||
closeDetails(event) {
|
|
||||||
if (event.target.closest(".sidebar-more-section-links-details-summary")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.open) {
|
|
||||||
const isLinkClick =
|
|
||||||
event.target.className.includes("sidebar-section-link") ||
|
|
||||||
event.target.className.includes("--link-button");
|
|
||||||
|
|
||||||
if (isLinkClick || this.#isOutsideDetailsClick(event)) {
|
|
||||||
this.open = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
registerClickListener() {
|
|
||||||
this.#addClickEventListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
unregisterClickListener() {
|
|
||||||
this.#removeClickEventListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
toggleSectionLinks(event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
this.open = !this.open;
|
|
||||||
}
|
|
||||||
|
|
||||||
#removeClickEventListener() {
|
|
||||||
document.removeEventListener("click", this.closeDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
#addClickEventListener() {
|
|
||||||
document.addEventListener("click", this.closeDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
#isOutsideDetailsClick(event) {
|
|
||||||
return !event.composedPath().some((element) => {
|
|
||||||
return element.className === "sidebar-more-section-links-details";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#setActiveSectionLink() {
|
#setActiveSectionLink() {
|
||||||
this.activeSectionLink = this.args.sectionLinks.find((sectionLink) => {
|
this.activeSectionLink = this.args.sectionLinks.find((sectionLink) => {
|
||||||
const args = [sectionLink.route];
|
const args = [sectionLink.route];
|
||||||
@ -117,54 +68,64 @@ export default class SidebarMoreSectionLinks extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
closeMenu(menu) {
|
||||||
|
menu.close();
|
||||||
|
|
||||||
|
if (this.args.toggleNavigationMenu) {
|
||||||
|
this.args.toggleNavigationMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
{{#if this.activeSectionLink}}
|
{{#if this.activeSectionLink}}
|
||||||
<MoreSectionLink @sectionLink={{this.activeSectionLink}} />
|
<MoreSectionLink @sectionLink={{this.activeSectionLink}} />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<li class="sidebar-section-link-wrapper">
|
<li class="sidebar-section-link-wrapper">
|
||||||
<button
|
<DMenu
|
||||||
{{on "click" this.toggleSectionLinks}}
|
@triggerClass="sidebar-section-link sidebar-more-section-links-details-summary sidebar-row --link-button"
|
||||||
aria-expanded={{if this.open "true" "false"}}
|
@modalForMobile={{true}}
|
||||||
class="sidebar-section-link sidebar-row sidebar-more-section-links-details-summary --link-button"
|
@autofocus={{true}}
|
||||||
|
@placement="bottom"
|
||||||
|
@inline={{true}}
|
||||||
|
@identifier="sidebar-more-section"
|
||||||
>
|
>
|
||||||
|
<:trigger>
|
||||||
<span class="sidebar-section-link-prefix icon">
|
<span class="sidebar-section-link-prefix icon">
|
||||||
{{icon "ellipsis-vertical"}}
|
{{icon "ellipsis-vertical"}}
|
||||||
</span>
|
</span>
|
||||||
<span class="sidebar-section-link-content-text">
|
<span class="sidebar-section-link-content-text">
|
||||||
{{i18n "sidebar.more"}}
|
{{i18n "sidebar.more"}}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</:trigger>
|
||||||
</li>
|
|
||||||
|
|
||||||
{{#if this.open}}
|
<:content as |menu|>
|
||||||
<div class="sidebar-more-section-links-details">
|
<DropdownMenu as |dropdown|>
|
||||||
<div
|
|
||||||
{{didInsert this.registerClickListener}}
|
|
||||||
{{willDestroy this.unregisterClickListener}}
|
|
||||||
class="sidebar-more-section-links-details-content-wrapper"
|
|
||||||
>
|
|
||||||
|
|
||||||
<div class="sidebar-more-section-links-details-content">
|
|
||||||
<ul class="sidebar-more-section-links-details-content-main">
|
|
||||||
{{#each this.sectionLinks as |sectionLink|}}
|
{{#each this.sectionLinks as |sectionLink|}}
|
||||||
<MoreSectionLink @sectionLink={{sectionLink}} />
|
<MoreSectionLink
|
||||||
|
@sectionLink={{sectionLink}}
|
||||||
|
class="dropdown-menu__item"
|
||||||
|
{{on "click" (fn this.closeMenu menu)}}
|
||||||
|
/>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
|
||||||
|
|
||||||
{{#if @moreButtonAction}}
|
{{#if @moreButtonAction}}
|
||||||
<div class="sidebar-more-section-links-details-content-footer">
|
<dropdown.divider />
|
||||||
|
|
||||||
|
<dropdown.item>
|
||||||
<SectionLinkButton
|
<SectionLinkButton
|
||||||
@action={{@moreButtonAction}}
|
@action={{@moreButtonAction}}
|
||||||
@icon={{@moreButtonIcon}}
|
@icon={{@moreButtonIcon}}
|
||||||
@text={{@moreButtonText}}
|
@text={{@moreButtonText}}
|
||||||
@name="customize"
|
@name="customize"
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</dropdown.item>
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
</DropdownMenu>
|
||||||
|
</:content>
|
||||||
|
</DMenu>
|
||||||
|
</li>
|
||||||
</template>
|
</template>
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,37 @@
|
|||||||
|
import Component from "@glimmer/component";
|
||||||
import { on } from "@ember/modifier";
|
import { on } from "@ember/modifier";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { service } from "@ember/service";
|
||||||
import icon from "discourse/helpers/d-icon";
|
import icon from "discourse/helpers/d-icon";
|
||||||
|
|
||||||
const SidebarSectionLinkButton = <template>
|
const MORE_MENU = "sidebar-more-section";
|
||||||
|
|
||||||
|
export default class SidebarSectionLinkButton extends Component {
|
||||||
|
@service menu;
|
||||||
|
@service header;
|
||||||
|
@service siteSettings;
|
||||||
|
|
||||||
|
@action
|
||||||
|
handleClick() {
|
||||||
|
const menuInstance = this.menu.getByIdentifier(MORE_MENU);
|
||||||
|
|
||||||
|
this.args.action();
|
||||||
|
|
||||||
|
this.menu.close(menuInstance);
|
||||||
|
|
||||||
|
if (this.args.toggleNavigationMenu) {
|
||||||
|
this.args.toggleNavigationMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.siteSettings.navigation_menu === "header dropdown") {
|
||||||
|
this.header.hamburgerVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
<div class="sidebar-section-link-wrapper">
|
<div class="sidebar-section-link-wrapper">
|
||||||
<button
|
<button
|
||||||
{{on "click" @action}}
|
{{on "click" this.handleClick}}
|
||||||
type="button"
|
type="button"
|
||||||
class="sidebar-section-link sidebar-row --link-button"
|
class="sidebar-section-link sidebar-row --link-button"
|
||||||
data-list-item-name={{@text}}
|
data-list-item-name={{@text}}
|
||||||
@ -18,6 +45,5 @@ const SidebarSectionLinkButton = <template>
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>;
|
</template>
|
||||||
|
}
|
||||||
export default SidebarSectionLinkButton;
|
|
||||||
|
@ -7,9 +7,13 @@ const SidebarSections = <template>
|
|||||||
@collapsableSections={{@collapsableSections}}
|
@collapsableSections={{@collapsableSections}}
|
||||||
@panel={{@panel}}
|
@panel={{@panel}}
|
||||||
@hideApiSections={{@hideApiSections}}
|
@hideApiSections={{@hideApiSections}}
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
/>
|
/>
|
||||||
{{else}}
|
{{else}}
|
||||||
<AnonymousSections @collapsableSections={{@collapsableSections}} />
|
<AnonymousSections
|
||||||
|
@collapsableSections={{@collapsableSections}}
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</template>;
|
</template>;
|
||||||
|
|
||||||
|
@ -11,7 +11,11 @@ export default class SidebarUserSections extends Component {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="sidebar-sections">
|
<div class="sidebar-sections">
|
||||||
<CustomSections @collapsable={{@collapsableSections}} />
|
<CustomSections
|
||||||
|
@collapsable={{@collapsableSections}}
|
||||||
|
@toggleNavigationMenu={{@toggleNavigationMenu}}
|
||||||
|
/>
|
||||||
|
|
||||||
<CategoriesSection @collapsable={{@collapsableSections}} />
|
<CategoriesSection @collapsable={{@collapsableSections}} />
|
||||||
|
|
||||||
{{#if this.currentUser.display_sidebar_tags}}
|
{{#if this.currentUser.display_sidebar_tags}}
|
||||||
|
@ -232,16 +232,16 @@ acceptance("Admin Sidebar - Sections - Plugin API", function (needs) {
|
|||||||
)
|
)
|
||||||
.doesNotExist();
|
.doesNotExist();
|
||||||
|
|
||||||
await click(".sidebar-more-section-links-details-summary");
|
await click(".sidebar-more-section-trigger");
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-more-section-links-details-content .sidebar-section-link[data-link-name='primary']"
|
"sidebar-more-section-content .sidebar-section-link[data-link-name='primary']"
|
||||||
)
|
)
|
||||||
.doesNotExist();
|
.doesNotExist();
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-more-section-links-details-content .sidebar-section-link[data-link-name='secondary']"
|
".sidebar-more-section-content .sidebar-section-link[data-link-name='secondary']"
|
||||||
)
|
)
|
||||||
.exists();
|
.exists();
|
||||||
});
|
});
|
||||||
|
@ -66,7 +66,7 @@ acceptance("Enforce Second Factor for unconfirmed session", function (needs) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
|
@ -10,7 +10,7 @@ acceptance("Meta Tag Updater", function (needs) {
|
|||||||
test("updates OG title and URL", async function (assert) {
|
test("updates OG title and URL", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
await click("a[href='/about']");
|
await click("a[href='/about']");
|
||||||
|
|
||||||
|
@ -40,11 +40,11 @@ acceptance("Sidebar - Anonymous user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
const sectionLinks = queryAll(
|
const sectionLinks = queryAll(
|
||||||
".sidebar-more-section-links-details-content-main .sidebar-section-link"
|
".sidebar-more-section-content .sidebar-section-link"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
|
@ -47,54 +47,32 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-content"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-content"
|
||||||
)
|
)
|
||||||
.exists("additional section links are displayed");
|
.exists("additional section links are displayed");
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary[aria-expanded='true']"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger[aria-expanded='true']"
|
||||||
)
|
)
|
||||||
.exists(
|
.exists(
|
||||||
"aria-expanded toggles to true when additional links are displayed"
|
"aria-expanded toggles to true when additional links are displayed"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-content"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-content"
|
||||||
)
|
)
|
||||||
.doesNotExist("additional section links are hidden");
|
.doesNotExist("additional section links are hidden");
|
||||||
|
|
||||||
await click(
|
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
|
||||||
);
|
|
||||||
|
|
||||||
await click("#main-outlet");
|
|
||||||
|
|
||||||
assert
|
|
||||||
.dom(
|
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-content"
|
|
||||||
)
|
|
||||||
.doesNotExist(
|
|
||||||
"additional section links are hidden when clicking outside"
|
|
||||||
);
|
|
||||||
|
|
||||||
assert
|
|
||||||
.dom(
|
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary[aria-expanded='false']"
|
|
||||||
)
|
|
||||||
.exists(
|
|
||||||
"aria-expanded toggles to false when additional links are hidden"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("clicking on everything link", async function (assert) {
|
test("clicking on everything link", async function (assert) {
|
||||||
@ -252,7 +230,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
@ -279,7 +257,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary .sidebar-section-link-content-text"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger .sidebar-section-link-content-text"
|
||||||
)
|
)
|
||||||
.hasText(
|
.hasText(
|
||||||
i18n("sidebar.more"),
|
i18n("sidebar.more"),
|
||||||
@ -301,7 +279,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
@ -315,7 +293,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
@ -335,7 +313,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
@ -357,7 +335,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
@ -384,7 +362,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary .sidebar-section-link-content-text"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger .sidebar-section-link-content-text"
|
||||||
)
|
)
|
||||||
.hasText(
|
.hasText(
|
||||||
i18n("sidebar.more"),
|
i18n("sidebar.more"),
|
||||||
@ -408,7 +386,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
@ -422,7 +400,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
@ -448,7 +426,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
@ -468,7 +446,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
@ -860,7 +838,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
.doesNotExist("review link is not shown");
|
.doesNotExist("review link is not shown");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
@ -897,12 +875,12 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-content .sidebar-section-link[data-link-name='review']"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-content .sidebar-section-link[data-link-name='review']"
|
||||||
)
|
)
|
||||||
.exists("review link is displayed in the more drawer");
|
.exists("review link is displayed in the more drawer");
|
||||||
|
|
||||||
@ -923,12 +901,12 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
.hasText("34 pending", "displays the pending reviewable count");
|
.hasText("34 pending", "displays the pending reviewable count");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(
|
.dom(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-content .sidebar-section-link[data-link-name='review']"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-content .sidebar-section-link[data-link-name='review']"
|
||||||
)
|
)
|
||||||
.doesNotExist("review link is not displayed in the more drawer");
|
.doesNotExist("review link is not displayed in the more drawer");
|
||||||
});
|
});
|
||||||
@ -947,7 +925,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
@ -1009,7 +987,7 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
|
|||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
await click(
|
await click(
|
||||||
".sidebar-section[data-section-name='community'] .sidebar-more-section-links-details-summary"
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(".sidebar-section-link[data-link-name='user-summary']");
|
await click(".sidebar-section-link[data-link-name='user-summary']");
|
||||||
|
@ -68,9 +68,8 @@ acceptance(
|
|||||||
assert
|
assert
|
||||||
.dom("[data-link-name='admin']")
|
.dom("[data-link-name='admin']")
|
||||||
.exists("the admin link is not within the 'more' dropdown");
|
.exists("the admin link is not within the 'more' dropdown");
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(".sidebar-more-section-links-details-summary")
|
.dom(".sidebar-more-section-trigger")
|
||||||
.doesNotExist(
|
.doesNotExist(
|
||||||
"the 'more' dropdown should not be present in header dropdown mode"
|
"the 'more' dropdown should not be present in header dropdown mode"
|
||||||
);
|
);
|
||||||
|
@ -61,7 +61,7 @@ export default class DMenuInstance extends FloatKitInstance {
|
|||||||
|
|
||||||
await super.close(...arguments);
|
await super.close(...arguments);
|
||||||
|
|
||||||
if (this.site.mobileView && this.options.modalForMobile) {
|
if (this.site.mobileView && this.options.modalForMobile && this.expanded) {
|
||||||
await this.modal.close();
|
await this.modal.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,43 +1,11 @@
|
|||||||
.sidebar-more-section-links-details-content {
|
.sidebar-more-section-content {
|
||||||
background-color: var(--d-sidebar-background);
|
z-index: z("modal", "dropdown");
|
||||||
transition: background-color 0.25s;
|
|
||||||
box-shadow: var(--shadow-card);
|
|
||||||
border: 1px solid var(--d-sidebar-border-color);
|
|
||||||
margin: 0 calc(var(--d-sidebar-row-horizontal-padding) * 2 / 3);
|
|
||||||
|
|
||||||
.sidebar-row {
|
.sidebar-row {
|
||||||
padding: 0.33rem calc(var(--d-sidebar-row-horizontal-padding) / 3);
|
padding: 0.33rem calc(var(--d-sidebar-row-horizontal-padding) / 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-more-section-links-details-content-main {
|
.sidebar-more-section-trigger {
|
||||||
position: sticky;
|
justify-content: flex-start;
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-more-section-links-details-content-footer {
|
|
||||||
border-top: 2px solid var(--d-sidebar-border-color);
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.sidebar-section-link-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-more-section-links-details-content-wrapper {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
z-index: z("modal", "content") + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-more-section-links-details {
|
|
||||||
position: relative;
|
|
||||||
@include breakpoint(tablet) {
|
|
||||||
grid-column-start: 1;
|
|
||||||
grid-column-end: 3;
|
|
||||||
.sidebar-more-section-links-details-content-main {
|
|
||||||
gap: 0 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
.sidebar-section-header-button {
|
.sidebar-section-header-button {
|
||||||
font-size: var(--font-down-1);
|
font-size: var(--font-down-1);
|
||||||
|
|
||||||
|
> * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn.dropdown-select-box-header,
|
.btn.dropdown-select-box-header,
|
||||||
@ -142,9 +146,6 @@
|
|||||||
|
|
||||||
.sidebar-section-content {
|
.sidebar-section-content {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
hr {
|
|
||||||
margin: 0em 1.5em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,5 +14,6 @@
|
|||||||
|
|
||||||
&__divider {
|
&__divider {
|
||||||
margin: 0rem;
|
margin: 0rem;
|
||||||
|
height: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
color: var(--primary-medium);
|
color: var(--primary-medium);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ul {
|
.sidebar-section-content {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
li {
|
li {
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.d-modal__body {
|
||||||
|
padding: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
padding-top: 0.25em;
|
padding-top: 0.25em;
|
||||||
}
|
}
|
||||||
|
@ -34,14 +34,14 @@ module PageObjects
|
|||||||
I18n.t("js.sidebar.sections.community.edit_section.sidebar"),
|
I18n.t("js.sidebar.sections.community.edit_section.sidebar"),
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(community_section).to have_no_css(".sidebar-more-section-links-details")
|
expect(community_section).to have_no_css(".sidebar-more-section-content")
|
||||||
|
|
||||||
PageObjects::Modals::SidebarSectionForm.new
|
PageObjects::Modals::SidebarSectionForm.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def click_community_section_more_button
|
def click_community_section_more_button
|
||||||
community_section.click_button(class: "sidebar-more-section-links-details-summary")
|
community_section.click_button(class: "sidebar-more-section-trigger")
|
||||||
expect(community_section).to have_css(".sidebar-more-section-links-details")
|
expect(community_section).to have_css(".sidebar-more-section-content")
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -61,6 +61,37 @@ describe "Viewing sidebar as logged in user", type: :system do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "when viewing the 'more' content in the Community sidebar section" do
|
||||||
|
let(:more_trigger_selector) do
|
||||||
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-trigger"
|
||||||
|
end
|
||||||
|
let(:more_links_selector) do
|
||||||
|
".sidebar-section[data-section-name='community'] .sidebar-more-section-content"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "toggles the more menu and handles click outside to close it" do
|
||||||
|
visit("/latest")
|
||||||
|
|
||||||
|
find(more_trigger_selector).click
|
||||||
|
|
||||||
|
expect(page).to have_selector(more_links_selector, visible: true)
|
||||||
|
|
||||||
|
expect(page).to have_selector("#{more_trigger_selector}[aria-expanded='true']")
|
||||||
|
|
||||||
|
find(more_trigger_selector).click
|
||||||
|
|
||||||
|
expect(page).not_to have_selector(more_links_selector)
|
||||||
|
|
||||||
|
expect(page).to have_selector("#{more_trigger_selector}[aria-expanded='false']")
|
||||||
|
|
||||||
|
find(more_trigger_selector).click
|
||||||
|
|
||||||
|
find(".d-header-wrap").click
|
||||||
|
|
||||||
|
expect(page).not_to have_selector(more_links_selector)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "when viewing the tags section" do
|
describe "when viewing the tags section" do
|
||||||
fab!(:tag1) do
|
fab!(:tag1) do
|
||||||
Fabricate(:tag, name: "tag 1", description: "tag 1 description <script>").tap do |tag|
|
Fabricate(:tag, name: "tag 1", description: "tag 1 description <script>").tap do |tag|
|
||||||
|
Reference in New Issue
Block a user