# Modal (w-modal)

## Description

Modals (or dialogs) display important information that users need to acknowledge.

[Warp component reference](https://warp-ds.github.io/docs/components/modal/frameworks/elements)

## Usage

To creat a modal you need three different components:

- `<w-modal>` - the parent component.
- `<w-modal-header>` - for the title and close button.
- `<w-modal-footer>` - for the actions such as Cancel and Confirm.

### JavaScript API

To open and close the modal using JavaScript, get a reference to the `<w-modal>` and call `open()` and `close()` respectively.


<elements-example>

```html
<w-button data-testid="js-example-show" aria-haspopup="dialog">Show me some lyrics</w-button>
<w-modal data-testid="js-example-modal">
    <w-modal-header slot="header" title="Triumph by Wu Tang Clan"></w-modal-header>
    <div slot="content">
        <p>
        My beats travel like a vortex through your spine, to the top of your
        cerebral cortex. The rebel, I make more noise than heavy metal. Now,
        lo and behold, another deadly episode, bound to catch another charge
        when I explode Perpendicular to the square we stay in gold like
        Flair, escape from your dragon's lair in particular. Handcuffed in
        the back of a bus, forty of us. Slammin a hype verse til ya head
        burst. Handcuffed in the back of a bus, forty of us. I bomb
        atomically Socrates' philosophies and hypothesis can't define how I
        be dropping these mockeries. I be that insane one from the psycho
        ward, I'm on the trigger, plus I got the Wu-Tang sword. Step through
        your section with the Force like Luke Skywalker, rhyme author,
        orchestrate mind torture.
        </p>
    </div>
    <w-modal-footer slot="footer">
        <w-button variant="secondary" data-testid="js-example-cancel">Cancel</w-button>
        <w-button variant="primary" data-testid="js-example-confirm">Confirm</w-button>
    </w-modal-footer>
</w-modal>

<script>
const modal = document.querySelector('w-modal[data-testid="js-example-modal"]');

const openButton = document.querySelector('w-button[data-testid="js-example-show"]');
const confirmButton = document.querySelector('w-button[data-testid="js-example-confirm"]');
const cancelButton = document.querySelector('w-button[data-testid="js-example-cancel"]');

openButton.addEventListener('click', () => modal.open());
confirmButton.addEventListener('click', () => modal.close());
cancelButton.addEventListener('click', () => modal.close());
</script>
```

</elements-example>

### Invoker Commands

In [supported browsers](https://caniuse.com/?search=commandfor) (or [if you include the polyfill](https://github.com/keithamus/invokers-polyfill)) you can use the [Invoker Commands API](https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API) to potentially skip JavaScript alltogether.

The available commands for `<w-modal>` are:

- `--show-modal`
- `--close`
- `--confirm`

<elements-example>

```html
<w-button commandfor="invoker-modal" command="--show-modal" aria-haspopup="dialog">Show me some lyrics</w-button>
<w-modal id="invoker-modal">
    <w-modal-header slot="header" title="Triumph by Wu Tang Clan"></w-modal-header>
    <div slot="content">
        <p>
        First I'm gonna getcha, once I gotcha, I gat-cha, You could never
        capture the Method Man's stature. So uhh, tic toc and keep ticking,
        while I get you flipping off what I'm kicking. Yes, the rhythm, the
        rebel, alone in my level heat it up past the boiling point of metal.
        Shackling the masses with drastic rap tactics, graphic displays melt
        the steel like blacksmiths. My beats travel like a vortex through
        your spine, to the top of your cerebral cortex. Yes, the rhythm, the
        rebel, alone in my level heat it up past the boiling point of metal.
        Small change, they putting shame in the game. Murderous material,
        made by a madman, it's the mic wrecker, Inspector, bad man.
        </p>
    </div>
    <w-modal-footer slot="footer">
        <w-button variant="secondary" commandfor="invoker-modal" command="--close">Dope</w-button>
        <w-button variant="primary" commandfor="invoker-modal" command="--confirm">Dope</w-button>
    </w-modal-footer>
</w-modal>
```

</elements-example>

Since `--confirm` and `--cancel` both close the modal, but mean different things, listen for the `command` event on `w-modal` to do stuff on the `--confirm` event, such as submit a response to an API. You can listen for the other commands as well (including `--show-modal`) if you need to add tracking events for example.

```ts
const modal = document.querySelector('w-modal');

modal.addEventListener('command', function (event: CommandEvent) {
    if (event.command === '--confirm') {
        console.log("Doing stuff!");
    }
});
```

## Accessibility

## Examples



### With a titlebar

<elements-example>

```html
<div>
  <w-button aria-haspopup='dialog'>
    Open a modal
  </w-button>
  <w-modal>
    <w-modal-header
      slot='header'
      title='An example modal'
    ></w-modal-header>
    <div slot='content'>
      <w-button variant='utility' small>
        Toggle back button
      </w-button>
      <p>
        I bomb atomically, Socrates' philosophies and hypotheses...
      </p>
      <p>
        First I'm gonna getcha, once I gotcha, I gat-cha...
      </p>
    </div>
    <w-modal-footer slot='footer'>
      <w-button variant='primary'>
        OK
      </w-button>
    </w-modal-footer>
  </w-modal>
</div>
```

</elements-example>

### With an image at the top

<elements-example>

```html
<w-button aria-haspopup="dialog" commandfor="my-modal" command="show-modal">
    Open a modal
</w-button>
<w-modal id="my-modal">
    <w-modal-header slot="header" title="Look a doggo!">
        <img
        slot="top"
        class="h-[256] w-full object-cover"
        src="/pages/public/unocssmusical.jpeg"
        alt="AI-generated picture of a band in colourful setup"
        >
    </w-modal-header>
    <div slot="content">
        <p>I bomb atomically, Socrates' philosophies and hypotheses...</p>
    </div>
    <w-modal-footer slot="footer">
        <w-button variant="primary" id="modal-close-button-two">OK</w-button>
    </w-modal-footer>
</w-modal>
```

</elements-example>

## Styling API

Modal supports styling through **component tokens** (CSS custom properties with a `--w-c-` prefix) and **parts**.

### Parts

Use `::part(part-name)` from outside the component.

#### `<w-modal>` parts

- `dialog` - the root element inside the component (`<dialog>` element).
- `wrapper` - container for all elements, direct child of `<dialog>`.
- `content` - the container for the `content` slot items (children).

#### `<w-modal-header>` parts

- `header` - the root element inside the component.
- `top` - the container for the image (`top` slot).
- `back` - the back button, if visible.
- `title` - the title element.
- `close` - the close button, if visible.

#### `<w-modal-footer>` parts

- `footer` - the container for slotted items (children)

### Component tokens

#### `<w-modal>` tokens

Set these on `<w-modal>` to override visuals.

```css
w-modal {
    --w-c-modal-backdrop-color: transparent;
}
```

##### Layout and typography

- `--w-c-modal-height`
- `--w-c-modal-max-height`
- `--w-c-modal-min-height`
- `--w-c-modal-padding-bottom`
- `--w-c-modal-translate-distance`
- `--w-c-modal-width`

##### Background

- `--w-c-modal-backdrop-color`
- `--w-c-modal-bg`

##### Text color

- `--w-c-modal-color`

##### Shadow

- `--w-c-modal-box-shadow`

#### `<w-modal-header>` tokens

Set these on `<w-modal-header>` to override visuals.

##### Layout and typography

- `--w-c-modal-header-font-size`
- `--w-c-modal-header-line-height`
- `--w-c-modal-header-margin-bottom`

#### `<w-modal-footer>` tokens

Set these on `<w-modal-footer>` to override visuals.

##### Layout and typography

- `--w-c-modal-footer-gap` - adjusts the flex gap between actions in the footer

## `<w-modal>` API

Unless otherwise noted all properties are HTML attributes (as opposed to JavaScript object properties).

### Properties

| Name | Type | Default | Summary |
|-|-|-|-|
| close (JS only) | `close() => void` | `-` | - |
| content-id | `string \| undefined` | `-` | **Deprecated**: This ID has no effect |
| ignore-backdrop-clicks | `boolean` | `false` | Ignores clicks to the backdrop when set |
| open (JS only) | `open() => void` | `-` | - |
| show | `boolean` | `false` | Controls if the modal should show or hide. |

### Property Details

#### close (JS only)



- Type: `close() => void`
- Default: `-`

#### content-id

**Deprecated**: This ID has no effect



- Type: `string | undefined`
- Default: `-`

#### ignore-backdrop-clicks

Ignores clicks to the backdrop when set

- Type: `boolean`
- Default: `false`

#### open (JS only)



- Type: `open() => void`
- Default: `-`

#### show

Controls if the modal should show or hide.

You can also call the `open()` and `close()` methods.

- Type: `boolean`
- Default: `false`

### Events

#### hidden



- Type: `CustomEvent`
#### shown



- Type: `CustomEvent`


