add data- invokers to dialog and drawer

This commit is contained in:
Cory LaViska
2025-06-04 16:15:24 -04:00
parent eac60a9022
commit a78e63c821
6 changed files with 84 additions and 21 deletions

View File

@@ -67,24 +67,28 @@ Footers can be used to display titles and more. Use the `footer` slot to add a f
</script>
```
### Dismissing Dialogs
### Opening and Closing Dialogs Declaratively
You can add the special `data-dialog="close"` attribute to a button inside the dialog to tell it to close without additional JavaScript. Alternatively, you can set the `open` property to `false` to close the dialog programmatically.
You can open and close dialogs with JavaScript by toggling the `open` attribute, but you can also do it declaratively. Add the `data-dialog="open id"` to any button on the page, where `id` is the ID of the dialog you want to open.
```html {.example}
<wa-dialog label="Dialog" class="dialog-dismiss">
<wa-dialog label="Dialog" id="dialog-opening">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
</wa-dialog>
<wa-button>Open Dialog</wa-button>
<wa-button data-dialog="open dialog-opening">Open Dialog</wa-button>
```
<script>
const dialog = document.querySelector('.dialog-dismiss');
const openButton = dialog.nextElementSibling;
Similarly, you can add `data-dialog="close"` to a button _inside_ of a dialog to tell it to close.
openButton.addEventListener('click', () => dialog.open = true);
</script>
```html {.example}
<wa-dialog label="Dialog" id="dialog-dismiss">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-dialog="close">Close</wa-button>
</wa-dialog>
<wa-button data-dialog="open dialog-dismiss">Open Dialog</wa-button>
```
### Custom Width

View File

@@ -65,24 +65,28 @@ Footers can be used to display titles and more. Use the `footer` slot to add a f
</script>
```
### Dismissing Drawers
### Opening and Closing Drawers Declaratively
You can add the special `data-drawer="close"` attribute to a button inside the drawer to tell it to close without additional JavaScript. Alternatively, you can set the `open` property to `false` to close the drawer programmatically.
You can open and close drawers with JavaScript by toggling the `open` attribute, but you can also do it declaratively. Add the `data-drawer="open id"` to any button on the page, where `id` is the ID of the drawer you want to open.
```html {.example}
<wa-drawer label="Drawer" class="drawer-dismiss">
<wa-drawer label="Drawer" id="drawer-opening">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
</wa-drawer>
<wa-button>Open Drawer</wa-button>
<wa-button data-drawer="open drawer-opening">Open Drawer</wa-button>
```
<script>
const drawer = document.querySelector('.drawer-dismiss');
const openButton = drawer.nextElementSibling;
Similarly, you can add `data-drawer="close"` to a button _inside_ of a drawer to tell it to close.
openButton.addEventListener('click', () => drawer.open = true);
</script>
```html {.example}
<wa-drawer label="Drawer" id="drawer-dismiss">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<wa-button slot="footer" variant="brand" data-drawer="close">Close</wa-button>
</wa-drawer>
<wa-button data-drawer="open drawer-dismiss">Open Drawer</wa-button>
```
### Slide in From Start

View File

@@ -43,6 +43,8 @@ During the alpha period, things might break! We take breaking changes very serio
- Added support for `name` in `<wa-details>` for exclusively opening one in a group
- Added `--checked-icon-scale` to `<wa-checkbox>`
- Added `--tag-max-size` to `<wa-select>` when using `multiple`
- Added support for `data-dialog="open <id>"` to `<wa-dialog>`
- Added support for `data-drawer="open <id>"` to `<wa-drawer>`
- Fixed a bug in `<wa-radio-group>` that caused radios to uncheck when assigning a numeric value [issue:924]
- Fixed `<wa-button-group>` so dividers properly show between buttons
- Fixed the tooltip position in `<wa-slider>` when using RTL

View File

@@ -6,6 +6,7 @@ import { WaAfterShowEvent } from '../../events/after-show.js';
import { WaHideEvent } from '../../events/hide.js';
import { WaShowEvent } from '../../events/show.js';
import { animateWithClass } from '../../internal/animate.js';
import { parseSpaceDelimitedTokens } from '../../internal/parse.js';
import { lockBodyScrolling, unlockBodyScrolling } from '../../internal/scroll.js';
import { HasSlotController } from '../../internal/slot.js';
import { watch } from '../../internal/watch.js';
@@ -264,6 +265,28 @@ export default class WaDialog extends WebAwesomeElement {
}
}
//
// Watch for data-dialog="open *" clicks
//
document.addEventListener('click', (event: MouseEvent) => {
const dialogAttrEl = (event.target as Element).closest('[data-dialog]');
if (dialogAttrEl instanceof Element) {
const [command, id] = parseSpaceDelimitedTokens(dialogAttrEl.getAttribute('data-dialog') || '');
if (command === 'open' && id?.length) {
const doc = dialogAttrEl.getRootNode() as Document | ShadowRoot;
const dialog = doc.getElementById(id) as WaDialog;
if (dialog?.localName === 'wa-dialog') {
dialog.open = true;
} else {
console.warn(`A dialog with an ID of "${id}" could not be found in this document.`);
}
}
}
});
// Ugly, but it fixes light dismiss in Safari: https://bugs.webkit.org/show_bug.cgi?id=267688
if (!isServer) {
document.addEventListener('pointerdown', () => {

View File

@@ -6,6 +6,7 @@ import { WaAfterShowEvent } from '../../events/after-show.js';
import { WaHideEvent } from '../../events/hide.js';
import { WaShowEvent } from '../../events/show.js';
import { animateWithClass } from '../../internal/animate.js';
import { parseSpaceDelimitedTokens } from '../../internal/parse.js';
import { lockBodyScrolling, unlockBodyScrolling } from '../../internal/scroll.js';
import { HasSlotController } from '../../internal/slot.js';
import { watch } from '../../internal/watch.js';
@@ -32,9 +33,9 @@ import styles from './drawer.css';
* @event wa-hide - Emitted when the drawer closes.
* @event wa-after-hide - Emitted after the drawer closes and all animations are complete.
* @event {{ source: Element }} wa-hide - Emitted when the drawer is requesting to close. Calling
* `event.preventDefault()` will prevent the dialog from closing. You can inspect `event.detail.source` to see which
* element caused the dialog to close. If the source is the dialog element itself, the user has pressed [[Escape]] or
* the dialog has been closed programmatically. Avoid using this unless closing the dialog will result in destructive
* `event.preventDefault()` will prevent the drawer from closing. You can inspect `event.detail.source` to see which
* element caused the drawer to close. If the source is the drawer element itself, the user has pressed [[Escape]] or
* the drawer has been closed programmatically. Avoid using this unless closing the drawer will result in destructive
* behavior such as data loss.
*
* @csspart header - The drawer's header. This element wraps the title and header actions.
@@ -280,6 +281,28 @@ export default class WaDrawer extends WebAwesomeElement {
}
}
//
// Watch for data-drawer="open *" clicks
//
document.addEventListener('click', (event: MouseEvent) => {
const dialogAttrEl = (event.target as Element).closest('[data-drawer]');
if (dialogAttrEl instanceof Element) {
const [command, id] = parseSpaceDelimitedTokens(dialogAttrEl.getAttribute('data-drawer') || '');
if (command === 'open' && id?.length) {
const doc = dialogAttrEl.getRootNode() as Document | ShadowRoot;
const dialog = doc.getElementById(id) as WaDrawer;
if (dialog?.localName === 'wa-drawer') {
dialog.open = true;
} else {
console.warn(`A drawer with an ID of "${id}" could not be found in this document.`);
}
}
}
});
if (!isServer) {
// Ugly, but it fixes light dismiss in Safari: https://bugs.webkit.org/show_bug.cgi?id=267688
document.body.addEventListener('pointerdown', () => {

View File

@@ -0,0 +1,7 @@
/** Parses a space-delimited set of tokens and returns an array with all whitespace removed. */
export function parseSpaceDelimitedTokens(input: string): string[] {
return input
.split(' ')
.map(token => token.trim())
.filter(token => token !== '');
}