# Dialog

[component-header:sl-dialog]

Dialogs, sometimes called "modals", appear above the page and require the user's immediate attention.

```html preview
<sl-dialog label="Dialog" class="dialog-overview">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  <sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>

<sl-button>Open Dialog</sl-button>

<script>
  (() => {
    const dialog = document.querySelector('.dialog-overview');
    const openButton = dialog.nextElementSibling;
    const closeButton = dialog.querySelector('sl-button[slot="footer"]');

    openButton.addEventListener('click', () => dialog.show());
    closeButton.addEventListener('click', () => dialog.hide());
  })();
</script>
```

## UX Tips

- Use a dialog when you immediately require the user's attention, e.g. confirming a destructive action.
- Always provide an obvious way for the user to dismiss the dialog.
- Don't nest dialogs. It almost always leads to a poor experience for the user.

## Examples

### Different header styles

Use the `header-style` prop to define how the header should be shown.

```html preview
<sl-dialog label="Dialog" class="dialog-width" style="--width: 50vw;">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  <sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>

<sl-button id="btn_header_normal">Normal header</sl-button>
<sl-button id="btn_header_dense">Dense header</sl-button>
<sl-button id="btn_header_discreet">Discreet header</sl-button>
<sl-button id="btn_header_hidden">Hidden header</sl-button>

<script>
  (() => {
    const dialog = document.querySelector('.dialog-width');
    const openButtonNormal = document.getElementById('btn_header_normal');
    const openButtonDense = document.getElementById('btn_header_dense');
    const openButtonDiscreet = document.getElementById('btn_header_discreet');
    const openButtonHidden = document.getElementById('btn_header_hidden');
    const closeButton = dialog.querySelector('sl-button[slot="footer"]');

    openButtonNormal.addEventListener('click', () => {dialog.headerStyle='normal';dialog.show()});
    openButtonDense.addEventListener('click', () => {dialog.headerStyle='dense';dialog.show()});
    openButtonDiscreet.addEventListener('click', () => {dialog.headerStyle='discreet';dialog.show()});
    openButtonHidden.addEventListener('click', () => {dialog.headerStyle='hidden';dialog.show()});
    closeButton.addEventListener('click', () => dialog.hide());
  })();
</script>
```

### Alignment

Set alignment to either `center` or `top` via the `position` property.

```html preview
<sl-dialog label="Dialog" class="dialog-position" position="top">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  <sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>

<sl-button>Open Dialog aligned to the top</sl-button>

<script>
  (() => {
    const dialog = document.querySelector('.dialog-position');
    const openButton = dialog.nextElementSibling;
    const closeButton = dialog.querySelector('sl-button[slot="footer"]');

    openButton.addEventListener('click', () => dialog.show());
    closeButton.addEventListener('click', () => dialog.hide());
  })();
</script>
```

### Custom Width

Use the `--width` custom property to set the dialog's width.

```html preview
<sl-dialog label="Dialog" class="dialog-width" style="--width: 50vw;">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  <sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>

<sl-button>Open Dialog</sl-button>

<script>
  (() => {
    const dialog = document.querySelector('.dialog-width');
    const openButton = dialog.nextElementSibling;
    const closeButton = dialog.querySelector('sl-button[slot="footer"]');

    openButton.addEventListener('click', () => dialog.show());
    closeButton.addEventListener('click', () => dialog.hide());
  })();
</script>
```

### Scrolling

By design, a dialog's height will never exceed that of the viewport. As such, dialogs will not scroll with the page ensuring the header and footer are always accessible to the user.

```html preview
<sl-dialog label="Dialog" class="dialog-scrolling">
  <div style="height: 150vh; border: dashed 2px var(--sl-color-gray-200); padding: 0 1rem;">
    <p>Scroll down and give it a try! 👇</p>
  </div>
  <sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>

<sl-button>Open Dialog</sl-button>

<script>
  (() => {
    const dialog = document.querySelector('.dialog-scrolling');
    const openButton = dialog.nextElementSibling;
    const closeButton = dialog.querySelector('sl-button[slot="footer"]');

    openButton.addEventListener('click', () => dialog.show());
    closeButton.addEventListener('click', () => dialog.hide());
  })();
</script>
```

### Ignoring Clicks on the Overlay

By default, dialogs are closed when the user clicks or taps on the overlay. To prevent this behavior, cancel the `sl-overlay-dismiss` event.

```html preview
<sl-dialog label="Dialog" class="dialog-no-overlay-dismiss">
  This dialog will not be closed when you click outside of it.
  <sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>

<sl-button>Open Dialog</sl-button>

<script>
  (() => {
    const dialog = document.querySelector('.dialog-no-overlay-dismiss');
    const openButton = dialog.nextElementSibling;
    const closeButton = dialog.querySelector('sl-button[slot="footer"]');

    openButton.addEventListener('click', () => dialog.show());
    closeButton.addEventListener('click', () => dialog.hide());

    dialog.addEventListener('slOverlayDismiss', event => event.preventDefault());
  })();
</script>
```

### Customizing Initial Focus

By default, the dialog's panel will gain focus when opened. To set focus on a different element, listen for the `sl-initial-focus` event.

```html preview
<sl-dialog label="Dialog" class="dialog-focus">
  <sl-input placeholder="I will have focus when the dialog is opened"></sl-input>
  <sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>

<sl-button>Open Dialog</sl-button>

<script>
  (() => {
    const dialog = document.querySelector('.dialog-focus');
    const input = dialog.querySelector('sl-input');
    const openButton = dialog.nextElementSibling;
    const closeButton = dialog.querySelector('sl-button[slot="footer"]');

    openButton.addEventListener('click', () => dialog.show());
    closeButton.addEventListener('click', () => dialog.hide());

    dialog.addEventListener('slInitialFocus', event => {
      event.preventDefault();
      input.setFocus({ preventScroll: true });
    });
  })();
</script>
```

[component-metadata:sl-dialog]
