diff --git a/packages/popup/src/LionPopup.js b/packages/popup/src/LionPopup.js index a3745d2a0..7a84e72f6 100644 --- a/packages/popup/src/LionPopup.js +++ b/packages/popup/src/LionPopup.js @@ -4,29 +4,44 @@ import { overlays, LocalOverlayController } from '@lion/overlays'; export class LionPopup extends UpdatingElement { static get properties() { return { - position: { - type: String, + placementConfig: { + type: Object, }, }; } + get placementConfig() { + return this._placementConfig; + } + + set placementConfig(config) { + this._placementConfig = { + ...this._placementConfig, + ...config, + }; + + if (this._controller && this._controller._popper) { + this._controller.updatePlacementConfig(this._placementConfig); + } + } + connectedCallback() { super.connectedCallback(); - this.contenNode = this.querySelector('[slot="content"]'); + this.contentNode = this.querySelector('[slot="content"]'); this.invokerNode = this.querySelector('[slot="invoker"]'); - this._popup = overlays.add( + this._controller = overlays.add( new LocalOverlayController({ hidesOnEsc: true, hidesOnOutsideClick: true, - placement: this.position, - contentNode: this.contenNode, + placementConfig: this.placementConfig, + contentNode: this.contentNode, invokerNode: this.invokerNode, }), ); - this._show = () => this._popup.show(); - this._hide = () => this._popup.hide(); - this._toggle = () => this._popup.toggle(); + this._show = () => this._controller.show(); + this._hide = () => this._controller.hide(); + this._toggle = () => this._controller.toggle(); this.invokerNode.addEventListener('click', this._toggle); } diff --git a/packages/popup/stories/index.stories.js b/packages/popup/stories/index.stories.js index 314bdd804..25f2ecb19 100644 --- a/packages/popup/stories/index.stories.js +++ b/packages/popup/stories/index.stories.js @@ -1,4 +1,4 @@ -import { storiesOf, html } from '@open-wc/demoing-storybook'; +import { storiesOf, html, withKnobs, object, text } from '@open-wc/demoing-storybook'; import { css } from '@lion/core'; import '@lion/icon/lion-icon.js'; @@ -11,11 +11,11 @@ const popupDemoStyle = css` background-color: white; border-radius: 2px; border: 1px solid grey; - margin: 250px; + margin: 250px 0 0 250px; padding: 8px; } - .demo-box_positions { + .demo-box_placements { display: flex; flex-direction: column; width: 173px; @@ -40,6 +40,8 @@ const popupDemoStyle = css` background-color: black; border-radius: 4px; padding: 8px; + /* To display on top of elements with no z-index that are appear later in the DOM */ + z-index: 1; } @media (max-width: 480px) { @@ -50,6 +52,7 @@ const popupDemoStyle = css` `; storiesOf('Local Overlay System|Popup', module) + .addDecorator(withKnobs) .add( 'Button popup', () => html` @@ -57,36 +60,73 @@ storiesOf('Local Overlay System|Popup', module) ${popupDemoStyle}
- - + + Popup
`, ) .add( - 'positions', + 'placements', () => html` -
- - +
+ + Top - - + + Right - - + + Bottom - - + + Left
`, + ) + .add( + 'Override placement configuration', + () => html` + +

Use the Storybook Knobs to dynamically change the placement configuration!

+
+ + + ${text('Invoker text', 'Click me!')} + +
+ `, ); diff --git a/packages/popup/test/lion-popup.test.js b/packages/popup/test/lion-popup.test.js index 31f0d61a0..8e854d2cf 100644 --- a/packages/popup/test/lion-popup.test.js +++ b/packages/popup/test/lion-popup.test.js @@ -1,4 +1,4 @@ -import { expect, fixture, html } from '@open-wc/testing'; +import { expect, fixture, html, aTimeout } from '@open-wc/testing'; import '../lion-popup.js'; @@ -25,6 +25,7 @@ describe('lion-popup', () => { const eventOnClick = new Event('click'); invoker.dispatchEvent(eventOnClick); await el.updateComplete; + await aTimeout(); expect(el.querySelector('[slot="content"]').style.display).to.be.equal('inline-block'); invoker.dispatchEvent(eventOnClick); await el.updateComplete; @@ -44,6 +45,21 @@ describe('lion-popup', () => { await el.updateComplete; expect(el.querySelector('strong')).to.not.be.undefined; }); + + it('should respond to dynamically changing the placementConfig', async () => { + const el = await fixture(html` + + + Popup button + + `); + await el._controller.show(); + expect(el._controller._popper.options.placement).to.equal('top'); + el.placementConfig = { placement: 'left' }; + // placementConfig setter calls updateConfig method which recreates popper instance and this process is async.. + await aTimeout(); + expect(el._controller._popper.options.placement).to.equal('left'); + }); }); describe('Accessibility', () => {