lion/packages/dialog/stories/index.stories.mdx
Thomas Rutten 2c9e71a328
chore(dialog): improve styled content docs (#633)
Co-Authored-By: Thomas Allmer <d4kmor@gmail.com>
Co-Authored-By: Joren Broekema <joren.broekema@gmail.com>
2020-03-11 16:48:05 +01:00

279 lines
7.7 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Story, Meta, html } from '@open-wc/demoing-storybook';
import demoStyle from './demo-dialog-style.js';
import './styled-dialog-content.js';
import '../lion-dialog.js';
<Meta title="Overlays/Dialog" parameters={{ component: 'lion-dialog' }} />
# Dialog
`lion-dialog` is a component wrapping a modal dialog controller.
Its purpose is to make it easy to use our Overlay System declaratively.
<Story name="Default">
{html`
<style>${demoStyle}</style>
<lion-dialog>
<button slot="invoker">Click me to open dialog</button>
<div slot="content" class="dialog">
Hello! You can close this dialog here:
<button
class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
</button>
</div>
</lion-dialog>
`}
</Story>
```html
<lion-dialog>
<button slot="invoker">Click me to open dialog</button>
<div slot="content" class="dialog">
Hello! You can close this dialog here:
<button
class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
</button>
</div>
</lion-dialog>
```
## Features
- Show content when clicking the invoker
- Respond to close event in the slot="content" element, to close the content
- Have a `.config` object to set or update the OverlayController's configuration
## How to use
### Installation
```sh
npm i --save @lion/dialog
```
```js
import '@lion/dialog/lion-dialog.js';
```
## Usage notes
- Your `slot="content"` node will be moved to the global overlay container during initialization.
After, your content node is no longer a child of `lion-dialog`.
If you still need to access it from the `lion-dialog` you can do so by using the `._overlayContentNode` property.
- To close the overlay from within the content node, you need to dispatch a `close-overlay` event that bubbles.
It has to be able to reach the content node.
- If you need to traverse shadow boundaries, you will have to add `composed: true` as well, although this is discouraged as a practice.
## Changing the configuration
You can use the `config` property on the dialog to change the configuration.
The documentation of the full config object can be found in the `lion/overlay` package.
The `config` property uses a setter to merge the passed configuration with the current, so you only **overwrite what you pass** when updating `config`.
### Styling content
It's not possible to style content from the dialog component. This is because the content slot is moved to the global root node. This is why a custom component should be created and slotted in as the content. This ensures style encapsulation on the dialog content.
<Story name="Styling content">
{() => {
return html`
<style>${demoStyle}</style>
<lion-dialog .config=${{ hidesOnOutsideClick: true, hidesOnEsc: true }}>
<button slot="invoker">Styled dialog</button>
<styled-dialog-content slot="content"></styled-dialog-content>
</lion-dialog>
`;
}}
</Story>
```html
<lion-dialog .config=${{ hidesOnOutsideClick: true, hidesOnEsc: true }}>
<button slot="invoker">Styled dialog</button>
<styled-dialog-content slot="content"></styled-dialog-content>
</lion-dialog>
```
```js
class StyledDialogContent extends LitElement {
static get styles() {
return [
css`
:host {
background-color: #fff;
}
.nice {
font-weight: bold;
color: green;
}
.close-button {
color: black;
font-size: 28px;
line-height: 28px;
}
`
];
}
_closeOverlay() {
this.dispatchEvent(new Event('close-overlay', { bubbles: true }));
}
render() {
return html`
<div><p>Hello person who opened the dialog!</p></div>
<div><p>Look how nice this <span class="nice">dialog</span> looks!</p>/div>
<button
class="close-button"
@click=${this._closeOverlay}
>
</button>
`;
}
}
customElements.define('styled-dialog-content',StyledDialogContent);
```
### Close overlay from component slotted as content
The overlay cannot be closed by dispatching the `close-overlay` from a button in a styled component that is slotted in as content, because it will not cross the shadow boundary of the component. A method should be created that will dispatch the `close-overlay` event from the component.
<Story name="Close overlay from component">
{() => {
return html`
<style>${demoStyle}</style>
<lion-dialog .config=${{ hidesOnOutsideClick: true, hidesOnEsc: true }}>
<button slot="invoker">Styled dialog</button>
<styled-dialog-content slot="content"></styled-dialog-content>
</lion-dialog>
`;
}}
</Story>
```js
_closeOverlay() {
this.dispatchEvent(new Event('close-overlay', { bubbles: true }));
}
render() {
return html`
<div><p>Hello person who opened the dialog!</p></div>
<div><p>Look how nice this <span class="nice">dialog</span> looks!</p>/div>
<button
class="close-button"
@click=${this._closeOverlay}
>
</button>
`;
}
```
### Placement overrides
<Story name="Placement overrides">
{() => {
const dialog = placement => html`
<lion-dialog .config=${{ viewportConfig: { placement } }}>
<button slot="invoker">Dialog ${placement}</button>
<div slot="content" class="dialog">
Hello! You can close this notification here:
<button
class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
</button>
</div>
</lion-dialog>
`;
return html`
<style>${demoStyle}</style>
<div class="demo-box_placements">
${dialog('center')} ${dialog('top-left')} ${dialog('top-right')} ${dialog('bottom-left')}
${dialog('bottom-right')}
</div>
`;
}}
</Story>
```html
<lion-dialog .config=${{ viewportConfig: { placement: 'top-left' } }}>
<button slot="invoker">Dialog top-left</button>
<div slot="content" class="dialog">
Hello! You can close this notification here:
<button
class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
</button>
</div>
</lion-dialog>
```
Configuration passed to `config` property:
```js
{
viewportConfig: {
placement: ... // <-- choose a position
}
}
```
### Other overrides
No backdrop, hides on escape, prevents scrolling while opened, and focuses the body when hiding.
<Story name="Other overrides">
{html`
<style>${demoStyle}</style>
<lion-dialog .config=${{
hasBackdrop: false,
hidesOnEscape: true,
preventsScroll: true,
elementToFocusAfterHide: document.body
}}>
<button slot="invoker">Click me to open dialog</button>
<div slot="content" class="dialog">
Hello! You can close this dialog here:
<button
class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
</button>
</div>
</lion-dialog>
`}
</Story>
```html
<lion-dialog .config="${{}}">
<button slot="invoker">Open dialog</button>
<div slot="content" class="dialog">
Hello! You can close this notification here:
<button
class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close-overlay', { bubbles: true }))}
>
</button>
</div>
</lion-dialog>
```
Configuration passed to `config` property:
```js
{
hasBackdrop: false,
hidesOnEscape: true,
preventsScroll: true,
elementToFocusAfterHide: document.body
}
```