import { css, LitElement, render } from '@lion/core';
import { html, storiesOf, withKnobs } from '@open-wc/demoing-storybook';
import {
OverlayMixin,
withBottomSheetConfig,
withDropdownConfig,
withModalDialogConfig,
} from '../index.js';
function renderOffline(litHtmlTemplate) {
const offlineRenderContainer = document.createElement('div');
render(litHtmlTemplate, offlineRenderContainer);
return offlineRenderContainer.firstElementChild;
}
// Currently toggling while opened doesn't work (see OverlayController)
/*
let toggledPlacement = 'top';
const togglePlacement = popupController => {
const placements = [
'top-end',
'top',
'top-start',
'right-end',
'right',
'right-start',
'bottom-start',
'bottom',
'bottom-end',
'left-start',
'left',
'left-end',
];
toggledPlacement = placements[(placements.indexOf(toggledPlacement) + 1) % placements.length];
popupController.updateConfig({ togglePlacement });
};
*/
const overlayDemoStyle = css`
.demo-box {
width: 200px;
background-color: white;
border-radius: 2px;
border: 1px solid grey;
padding: 8px;
}
.demo-box_placements {
display: flex;
flex-direction: column;
width: 173px;
margin: 0 auto;
margin-top: 68px;
}
lion-demo-overlay {
padding: 10px;
}
.close-button {
color: black;
font-size: 28px;
line-height: 28px;
}
.demo-box__column {
display: flex;
flex-direction: column;
}
.demo-overlay {
display: block;
position: absolute;
font-size: 16px;
color: white;
background-color: black;
border-radius: 4px;
padding: 8px;
}
.demo-overlay button {
color: black;
}
.demo-popup {
padding: 10px;
border: 1px solid black;
}
`;
customElements.define(
'lion-demo-overlay',
class extends OverlayMixin(LitElement) {
// eslint-disable-next-line class-methods-use-this
_defineOverlayConfig() {
return {
placementMode: 'global', // have to set a default
};
}
_setupOpenCloseListeners() {
super._setupOpenCloseListeners();
this.__toggle = () => {
this.opened = !this.opened;
};
this._overlayInvokerNode.addEventListener('click', this.__toggle);
}
_teardownOpenCloseListeners() {
super._teardownOpenCloseListeners();
this._overlayInvokerNode.removeEventListener('click', this.__toggle);
}
render() {
return html`
`;
}
},
);
storiesOf('Overlay System | Overlay as a WC', module)
.addDecorator(withKnobs)
.add(
'Default',
() => html`
Important note: For placementMode: 'global', your
slot="content" gets moved to global overlay container. After initialization it
is no longer a child of lion-demo-overlay
To close your overlay from some action performed inside the content slot, fire a
hide event.
For the overlay to close, it will need to bubble to the content slot (use
bubbles: true. If absolutely needed composed: true can be used to
traverse shadow boundaries)
The demo below demonstrates this
Overlay
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
⨯
`,
)
.add('Global placement configuration', () => {
const overlay = placement => html`
Overlay ${placement}
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
⨯
`;
return html`
${overlay('center')} ${overlay('top-left')} ${overlay('top-right')}
${overlay('bottom-left')} ${overlay('bottom-right')}
`;
})
.add(
'Nested overlays',
() => html`
Overlay
Hello! This is a notification.
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
Close
Open child
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
⨯
`,
)
.add(
'Local placementMode',
() => html`
Overlay
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
⨯
`,
)
.add(
'Override the popper config',
() => html`
The API is aligned with Popper.js, visit their documentation for more information:
Popper.js Docs
UK
`,
)
.add('Switch overlays configuration', () => {
const overlay = renderOffline(html`
Overlay
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
⨯
`);
return html`
{
overlay.config = {
...withModalDialogConfig(),
};
}}
>
modal dialog
{
overlay.config = {
...withBottomSheetConfig(),
};
}}
>
bottom sheet
{
overlay.config = {
...withDropdownConfig(),
};
}}
>
dropdown
${overlay}
`;
})
.add(
'Responsive switching',
() => html`
Open the overlay on a big screen and it will be a dialog
Close and open it again on a small screen (< 600px) and it will be a bottom sheet
{
if (window.innerWidth >= 600) {
e.target.config = { ...withModalDialogConfig() };
} else {
e.target.config = { ...withBottomSheetConfig() };
}
}}
>
Overlay
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
⨯
`,
)
.add('On hover', () => {
const popup = renderOffline(html`
{
popup.opened = true;
}}
@mouseleave=${() => {
popup.opened = false;
}}
>UK
United Kingdom
`);
return html`
In the beautiful ${popup} the weather is nice.
`;
})
.add('On an input', () => {
const popup = renderOffline(html`
e.stopImmediatePropagation()}
@focusout=${() => {
popup.opened = false;
}}
@focusin=${() => {
popup.opened = true;
}}
/>
`);
return html`
Input with a dropdown on focus
${popup}
`;
})
.add('Sync application state', () => {
const appState = {
opened: true,
};
const openedStateNode = renderOffline(
html`
${appState.opened}
`,
);
function onOpenClosed(ev) {
appState.opened = ev.target.opened;
openedStateNode.innerText = appState.opened;
}
const popup = renderOffline(html`
Overlay
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
⨯
`);
return html`
appState.opened: ${openedStateNode}
${popup}
`;
})
.add('Intercept open/close', () => {
let shouldIntercept = true;
let shouldInterceptButton;
function toggleIntercept() {
shouldIntercept = !shouldIntercept;
shouldInterceptButton.textContent = shouldIntercept;
}
function intercept(ev) {
if (shouldIntercept) {
ev.preventDefault();
}
}
shouldInterceptButton = renderOffline(
html`
${shouldIntercept}
`,
);
const popup = renderOffline(html`
Overlay
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
⨯
`);
return html`
toggle shouldIntercept:${shouldInterceptButton}
${popup}
`;
});
/* .add('Toggle placement with knobs', () => {
const overlay = (placementMode = 'global') => html`
Overlay
Hello! You can close this notification here:
e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>⨯
`;
return html`
Local
${overlay('local')}
`;
}) */