mirror of
https://github.com/discourse/discourse.git
synced 2025-03-08 20:49:50 +00:00
FIX: ensures d-popover closes when clicking on popper (#16675)
I think the no-invalid-interaction is fine here as on click Is not actually used for an expected interaction but as an event bubbling barrier.
This commit is contained in:
parent
4d0ac8636c
commit
131974b3a6
@ -2,6 +2,8 @@ import Component from "@ember/component";
|
|||||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||||
import tippy from "tippy.js";
|
import tippy from "tippy.js";
|
||||||
import { guidFor } from "@ember/object/internals";
|
import { guidFor } from "@ember/object/internals";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { next } from "@ember/runloop";
|
||||||
|
|
||||||
export default class DiscoursePopover extends Component {
|
export default class DiscoursePopover extends Component {
|
||||||
tagName = "";
|
tagName = "";
|
||||||
@ -15,13 +17,30 @@ export default class DiscoursePopover extends Component {
|
|||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
this._setupTippy();
|
this._tippyInstance = this._setupTippy();
|
||||||
|
}
|
||||||
|
|
||||||
|
willDestroyElement() {
|
||||||
|
this._super(...arguments);
|
||||||
|
|
||||||
|
this._tippyInstance?.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
get componentId() {
|
get componentId() {
|
||||||
return guidFor(this);
|
return guidFor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
close(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (!this.isExpanded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._tippyInstance?.hide();
|
||||||
|
}
|
||||||
|
|
||||||
_setupTippy() {
|
_setupTippy() {
|
||||||
const baseOptions = {
|
const baseOptions = {
|
||||||
trigger: "click",
|
trigger: "click",
|
||||||
@ -30,6 +49,7 @@ export default class DiscoursePopover extends Component {
|
|||||||
interactive: true,
|
interactive: true,
|
||||||
allowHTML: false,
|
allowHTML: false,
|
||||||
appendTo: "parent",
|
appendTo: "parent",
|
||||||
|
hideOnClick: true,
|
||||||
content:
|
content:
|
||||||
this.options?.content ||
|
this.options?.content ||
|
||||||
document
|
document
|
||||||
@ -38,20 +58,27 @@ export default class DiscoursePopover extends Component {
|
|||||||
":scope > .d-popover-content, :scope > div, :scope > ul"
|
":scope > .d-popover-content, :scope > div, :scope > ul"
|
||||||
),
|
),
|
||||||
onShow: () => {
|
onShow: () => {
|
||||||
if (this.isDestroyed || this.isDestroying) {
|
next(() => {
|
||||||
return;
|
if (this.isDestroyed || this.isDestroying) {
|
||||||
}
|
return;
|
||||||
this.set("isExpanded", true);
|
}
|
||||||
|
|
||||||
|
this.set("isExpanded", true);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
onHide: () => {
|
onHide: () => {
|
||||||
if (this.isDestroyed || this.isDestroying) {
|
next(() => {
|
||||||
return;
|
if (this.isDestroyed || this.isDestroying) {
|
||||||
}
|
return;
|
||||||
this.set("isExpanded", false);
|
}
|
||||||
|
this.set("isExpanded", false);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
tippy(
|
const instance = tippy(
|
||||||
document
|
document
|
||||||
.getElementById(this.componentId)
|
.getElementById(this.componentId)
|
||||||
.querySelector(
|
.querySelector(
|
||||||
@ -59,5 +86,7 @@ export default class DiscoursePopover extends Component {
|
|||||||
),
|
),
|
||||||
Object.assign({}, baseOptions, this.options || {})
|
Object.assign({}, baseOptions, this.options || {})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return instance?.id ? instance : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
<div id={{componentId}} class="d-popover {{class}} {{if isExpanded "is-expanded"}}">
|
{{!-- template-lint-disable no-invalid-interactive --}}
|
||||||
|
<div {{on "click" (action "close")}} id={{componentId}} class="d-popover {{class}} {{if isExpanded "is-expanded"}}">
|
||||||
{{yield (hash isExpanded=isExpanded)}}
|
{{yield (hash isExpanded=isExpanded)}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -39,16 +39,20 @@ discourseModule("Integration | Component | d-popover", function (hooks) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
componentTest("show/hide popover from component", {
|
componentTest("show/hide popover from component", {
|
||||||
template: hbs`{{#d-popover}}{{d-button icon="chevron-down"}}<ul><li class="test">foo</li></ul>{{/d-popover}}`,
|
template: hbs`{{#d-popover}}{{d-button class="trigger" icon="chevron-down"}}<ul><li class="test">foo</li><li>{{d-button icon="times" class="closer"}}</li></ul>{{/d-popover}}`,
|
||||||
|
|
||||||
async test(assert) {
|
async test(assert) {
|
||||||
assert.notOk(exists(".d-popover.is-expanded"));
|
assert.notOk(exists(".d-popover.is-expanded"));
|
||||||
assert.notOk(exists(".test"));
|
assert.notOk(exists(".test"));
|
||||||
|
|
||||||
await click(".btn");
|
await click(".trigger");
|
||||||
|
|
||||||
assert.ok(exists(".d-popover.is-expanded"));
|
assert.ok(exists(".d-popover.is-expanded"));
|
||||||
assert.equal(query(".test").innerText.trim(), "foo");
|
assert.equal(query(".test").innerText.trim(), "foo");
|
||||||
|
|
||||||
|
await click(".closer");
|
||||||
|
|
||||||
|
assert.notOk(exists(".d-popover.is-expanded"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user