Merge pull request #98 from hashicorp/fix-dropdown-click-inside
Fix dropdown click inside
This commit is contained in:
6 files changed
+77
-4
No files matched your search
@@ -12,13 +12,15 @@ export default Component.extend({
|
||||
|
||||
/**
|
||||
* Closes the details element by setting its `open` attribute to `false`.
|
||||
* While the details element handles open/close functionality without
|
||||
* JavaScript, we include this helper action to ensure that when the user
|
||||
* clicks _outside_ of the element, it still closes.
|
||||
* While the details element handles open/close functionality when clicking
|
||||
* directly on the summar elemenet without JavaScript, we include this helper
|
||||
* action to ensure that when the user clicks _outside_ of the element,
|
||||
* or _inside_ the content, it still closes.
|
||||
* @param {HTMLElement} element
|
||||
*/
|
||||
@action
|
||||
close(element) {
|
||||
if (element.open) element.open = false;
|
||||
if (element.parentElement.open) element.parentElement.open = false;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import { modifier } from 'ember-modifier';
|
||||
|
||||
/**
|
||||
* Used to detect clicks occuring _inside_ the modified element.
|
||||
* This is useful especially for dropdowns to toggle content visibility
|
||||
* when the user clicks an item.
|
||||
*/
|
||||
export default modifier((element, [callback]) => {
|
||||
function handleClick(event) {
|
||||
if (element.contains(event.target)) {
|
||||
callback(element, event);
|
||||
}
|
||||
}
|
||||
|
||||
element.addEventListener('click', handleClick, false);
|
||||
|
||||
return () => {
|
||||
element.removeEventListener('click', handleClick, false);
|
||||
};
|
||||
});
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
</summary>
|
||||
|
||||
<div class="rose-dropdown-content">
|
||||
<div class="rose-dropdown-content" {{on-click-inside this.close}}>
|
||||
{{yield (hash
|
||||
link=(component "link-to" class="rose-dropdown-link")
|
||||
button=(component "rose/button" style="dropdown")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'rose/modifiers/on-click-inside';
|
||||
@@ -67,4 +67,17 @@ module('Integration | Component | rose/dropdown', function (hooks) {
|
||||
await click('#wrapper');
|
||||
assert.notOk(find('#dropdown').open);
|
||||
});
|
||||
|
||||
test('it is closed when inside content is clicked', async function (assert) {
|
||||
await render(hbs`
|
||||
<Rose::Dropdown as |dropdown|>
|
||||
<dropdown.button>Button</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
`);
|
||||
|
||||
await click('summary');
|
||||
assert.ok(find('.rose-dropdown').open);
|
||||
await click('button');
|
||||
assert.notOk(find('.rose-dropdown').open);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, click } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
module('Integration | Modifier | on-click-inside', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it fires event when inside is clicked', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.set('clickedInside', (element) => {
|
||||
assert.ok(element);
|
||||
assert.equal(element.id, 'inside');
|
||||
});
|
||||
await render(hbs`
|
||||
<div id="outside"></div>
|
||||
<div id="inside" {{on-click-inside this.clickedInside}}>
|
||||
<div id="item" />
|
||||
</div>
|
||||
`);
|
||||
await click('#item');
|
||||
});
|
||||
|
||||
test('it does not fire event when outside is clicked', async function (assert) {
|
||||
assert.expect(0);
|
||||
this.set('clickedInside', () => {
|
||||
assert.ok(true);
|
||||
});
|
||||
await render(hbs`
|
||||
<div id="outside"></div>
|
||||
<div id="inside" {{on-click-inside this.clickedInside}}>
|
||||
<div id="item" />
|
||||
</div>
|
||||
`);
|
||||
await click('#outside');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user