mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Update headerIcons
API (#26090)
- Remove panelPortal usage, which allowed for content to be added as a dropdown - Instead rely on float-kit's DMenu to render a dropdown
This commit is contained in:
parent
8509fc2ebc
commit
f8dd468caa
@ -2,7 +2,6 @@ import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { getOwner } from "@ember/application";
|
||||
import { action } from "@ember/object";
|
||||
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||
import { service } from "@ember/service";
|
||||
import { modifier } from "ember-modifier";
|
||||
import { and, eq, not, or } from "truth-helpers";
|
||||
@ -44,7 +43,6 @@ export default class GlimmerHeader extends Component {
|
||||
@service header;
|
||||
|
||||
@tracked skipSearchContext = this.site.mobileView;
|
||||
@tracked panelElement;
|
||||
|
||||
appEventsListeners = modifier(() => {
|
||||
this.appEvents.on(
|
||||
@ -166,11 +164,6 @@ export default class GlimmerHeader extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
setPanelElement(element) {
|
||||
this.panelElement = element;
|
||||
}
|
||||
|
||||
<template>
|
||||
<header class="d-header" {{this.appEventsListeners}}>
|
||||
<div class="wrap">
|
||||
@ -202,7 +195,6 @@ export default class GlimmerHeader extends Component {
|
||||
@toggleHamburger={{this.toggleHamburger}}
|
||||
@toggleUserMenu={{this.toggleUserMenu}}
|
||||
@searchButtonId={{SEARCH_BUTTON_ID}}
|
||||
@panelElement={{this.panelElement}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
@ -216,9 +208,6 @@ export default class GlimmerHeader extends Component {
|
||||
<UserMenuWrapper @toggleUserMenu={{this.toggleUserMenu}} />
|
||||
{{/if}}
|
||||
|
||||
<div id="additional-panel-wrapper" {{didInsert this.setPanelElement}}>
|
||||
</div>
|
||||
|
||||
{{#if
|
||||
(and
|
||||
(or this.site.mobileView this.site.narrowDesktopView)
|
||||
|
@ -4,7 +4,6 @@ import { eq, not, or } from "truth-helpers";
|
||||
import DAG from "discourse/lib/dag";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import Dropdown from "./dropdown";
|
||||
import PanelPortal from "./panel-portal";
|
||||
import UserDropdown from "./user-dropdown";
|
||||
|
||||
let headerIcons;
|
||||
@ -64,9 +63,7 @@ export default class Icons extends Component {
|
||||
/>
|
||||
{{/if}}
|
||||
{{else if entry.value}}
|
||||
<entry.value
|
||||
@panelPortal={{component PanelPortal panelElement=@panelElement}}
|
||||
/>
|
||||
<entry.value />
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
@ -1,9 +0,0 @@
|
||||
import ConditionalInElement from "../conditional-in-element";
|
||||
|
||||
const PanelPortal = <template>
|
||||
<ConditionalInElement @element={{@panelElement}}>
|
||||
{{yield}}
|
||||
</ConditionalInElement>
|
||||
</template>;
|
||||
|
||||
export default PanelPortal;
|
@ -1,25 +0,0 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { schedule } from "@ember/runloop";
|
||||
import { PANEL_WRAPPER_ID } from "discourse/widgets/header";
|
||||
import PanelPortal from "./header/panel-portal";
|
||||
|
||||
export default class LegacyHeaderIconShim extends Component {
|
||||
@tracked panelElement;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
schedule("afterRender", () => {
|
||||
this.panelElement = document.querySelector(`#${PANEL_WRAPPER_ID}`);
|
||||
});
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#let
|
||||
(component PanelPortal panelElement=this.panelElement)
|
||||
as |panelPortal|
|
||||
}}
|
||||
<@component @panelPortal={{panelPortal}} />
|
||||
{{/let}}
|
||||
</template>
|
||||
}
|
@ -1850,17 +1850,17 @@ class PluginApi {
|
||||
* api.headerIcons.has("chat")
|
||||
* ```
|
||||
*
|
||||
* Additionally, you can utilize the `@panelPortal` argument to create a dropdown panel. This can be useful when
|
||||
* If you are looking to add a button with a dropdown, you can implement a `DMenu` which has a `content` block
|
||||
* you want create a button in the header that opens a dropdown panel with additional content.
|
||||
*
|
||||
* ```
|
||||
* const IconWithDropdown = <template>
|
||||
* <DButton @icon="icon" @onClick={{this.toggleVisible}} />
|
||||
* {{#if this.visible}}
|
||||
* <@panelPortal>
|
||||
* <div>Panel</div>
|
||||
* </@panelPortal>
|
||||
* {{/if}}
|
||||
* <DMenu @icon="foo" title={{i18n "title"}}>
|
||||
* <:content as |args|>
|
||||
* dropdown content here
|
||||
* <DButton @action={{args.close}} @icon="bar" />
|
||||
* </:content>
|
||||
* </DMenu>
|
||||
* </template>;
|
||||
*
|
||||
* api.headerIcons.add("icon-name", IconWithDropdown, { before: "search" })
|
||||
|
@ -22,7 +22,6 @@ import discourseLater from "discourse-common/lib/later";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
const SEARCH_BUTTON_ID = "search-button";
|
||||
export const PANEL_WRAPPER_ID = "additional-panel-wrapper";
|
||||
|
||||
let _extraHeaderIcons;
|
||||
clearExtraHeaderIcons();
|
||||
@ -237,11 +236,7 @@ createWidget("header-icons", {
|
||||
tagName: "ul.icons.d-header-icons",
|
||||
|
||||
init() {
|
||||
registerWidgetShim(
|
||||
"extra-icon",
|
||||
"span.wrapper",
|
||||
hbs`<LegacyHeaderIconShim @component={{@data.component}} />`
|
||||
);
|
||||
registerWidgetShim("extra-icon", "span.wrapper", hbs`<@data.component />`);
|
||||
},
|
||||
|
||||
html(attrs) {
|
||||
@ -568,8 +563,6 @@ export default createWidget("header", {
|
||||
}
|
||||
});
|
||||
|
||||
panels.push(h(`div#${PANEL_WRAPPER_ID}`));
|
||||
|
||||
if (this.site.mobileView || this.site.narrowDesktopView) {
|
||||
panels.push(this.attach("header-cloak"));
|
||||
}
|
||||
|
@ -19,6 +19,17 @@ acceptance("Header API - authenticated", function (needs) {
|
||||
await visit("/");
|
||||
assert.dom("button.test-button").exists("button is displayed");
|
||||
});
|
||||
|
||||
test("can add icons to the header", async function (assert) {
|
||||
withPluginApi("1.29.0", (api) => {
|
||||
api.headerIcons.add("test", <template>
|
||||
<span class="test-icon">Test</span>
|
||||
</template>);
|
||||
});
|
||||
|
||||
await visit("/");
|
||||
assert.dom(".test-icon").exists("icon is displayed");
|
||||
});
|
||||
});
|
||||
|
||||
acceptance("Header API - anonymous", function () {
|
||||
@ -49,6 +60,34 @@ acceptance("Header API - anonymous", function () {
|
||||
"Test button is positioned before auth-buttons"
|
||||
);
|
||||
});
|
||||
|
||||
test("can add icons to the header", async function (assert) {
|
||||
withPluginApi("1.29.0", (api) => {
|
||||
api.headerIcons.add("test", <template>
|
||||
<span class="test-icon">Test</span>
|
||||
</template>);
|
||||
});
|
||||
|
||||
await visit("/");
|
||||
assert.dom(".test-icon").exists("icon is displayed");
|
||||
});
|
||||
|
||||
test("icons are positioned to the left of search icon by default", async function (assert) {
|
||||
withPluginApi("1.29.0", (api) => {
|
||||
api.headerIcons.add("test", <template>
|
||||
<span class="test-icon">Test</span>
|
||||
</template>);
|
||||
});
|
||||
|
||||
await visit("/");
|
||||
const testIcon = document.querySelector(".test-icon");
|
||||
const search = document.querySelector(".search-dropdown");
|
||||
assert.equal(
|
||||
testIcon.compareDocumentPosition(search),
|
||||
Node.DOCUMENT_POSITION_FOLLOWING,
|
||||
"Test icon is positioned before search icon"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
acceptance("Glimmer Header API - authenticated", function (needs) {
|
||||
@ -90,4 +129,38 @@ acceptance("Glimmer Header API - authenticated", function (needs) {
|
||||
"Test2 button is positioned before Test1 button"
|
||||
);
|
||||
});
|
||||
|
||||
test("can add icons to the header", async function (assert) {
|
||||
withPluginApi("1.29.0", (api) => {
|
||||
api.headerIcons.add("test", <template>
|
||||
<span class="test-icon">Test</span>
|
||||
</template>);
|
||||
});
|
||||
|
||||
await visit("/");
|
||||
assert.dom(".test-icon").exists("icon is displayed");
|
||||
});
|
||||
|
||||
test("icons can be repositioned", async function (assert) {
|
||||
withPluginApi("1.29.0", (api) => {
|
||||
api.headerIcons.add("test1", <template>
|
||||
<span class="test1-icon">Test1</span>
|
||||
</template>);
|
||||
|
||||
api.headerIcons.add(
|
||||
"test2",
|
||||
<template><span class="test2-icon">Test2</span></template>,
|
||||
{ before: "test1" }
|
||||
);
|
||||
});
|
||||
|
||||
await visit("/");
|
||||
const test1 = document.querySelector(".test1-icon");
|
||||
const test2 = document.querySelector(".test2-icon");
|
||||
assert.equal(
|
||||
test2.compareDocumentPosition(test1),
|
||||
Node.DOCUMENT_POSITION_FOLLOWING,
|
||||
"Test2 icon is positioned before Test1 icon"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user