kopia lustrzana https://github.com/shoelace-style/shoelace
add sl-request-close event
rodzic
95ba1b5849
commit
1c010ffe5a
|
@ -76,27 +76,29 @@ By design, a dialog's height will never exceed that of the viewport. As such, di
|
|||
</script>
|
||||
```
|
||||
|
||||
### Ignoring Clicks on the Overlay
|
||||
### Preventing the Dialog from Closing
|
||||
|
||||
By default, dialogs are closed when the user clicks or taps on the overlay. To prevent this behavior, cancel the `sl-overlay-dismiss` event.
|
||||
By default, dialogs will close when the user clicks the close button, clicks the overlay, or presses the <kbd>Escape</kbd> key. In most cases, the default behavior is the best behavior in terms of UX. However, there are situations where this may be undesirable, such as when data loss will occur.
|
||||
|
||||
To keep the dialog open in such cases, you can cancel the `sl-request-close` event. When canceled, the dialog will remain open and pulse briefly to draw the user's attention to it.
|
||||
|
||||
```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 label="Dialog" class="dialog-deny-close">
|
||||
This dialog will not close unless you use the button below.
|
||||
<sl-button slot="footer" type="primary">Save & Close</sl-button>
|
||||
</sl-dialog>
|
||||
|
||||
<sl-button>Open Dialog</sl-button>
|
||||
|
||||
<script>
|
||||
const dialog = document.querySelector('.dialog-no-overlay-dismiss');
|
||||
const dialog = document.querySelector('.dialog-deny-close');
|
||||
const openButton = dialog.nextElementSibling;
|
||||
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
const saveButton = dialog.querySelector('sl-button[slot="footer"]');
|
||||
|
||||
openButton.addEventListener('click', () => dialog.show());
|
||||
closeButton.addEventListener('click', () => dialog.hide());
|
||||
saveButton.addEventListener('click', () => dialog.hide());
|
||||
|
||||
dialog.addEventListener('sl-overlay-dismiss', event => event.preventDefault());
|
||||
dialog.addEventListener('sl-request-close', event => event.preventDefault());
|
||||
</script>
|
||||
```
|
||||
|
||||
|
|
|
@ -164,27 +164,30 @@ By design, a drawer's height will never exceed 100% of its container. As such, d
|
|||
</script>
|
||||
```
|
||||
|
||||
### Ignoring Clicks on the Overlay
|
||||
### Preventing the Drawer from Closing
|
||||
|
||||
By default, drawers will close when the user clicks the close button, clicks the overlay, or presses the <kbd>Escape</kbd> key. In most cases, the default behavior is the best behavior in terms of UX. However, there are situations where this may be undesirable, such as when data loss will occur.
|
||||
|
||||
To keep the drawer open in such cases, you can cancel the `sl-request-close` event. When canceled, the drawer will remain open and pulse briefly to draw the user's attention to it.
|
||||
|
||||
By default, drawers are closed when the user clicks or taps on the overlay. To prevent this behavior, cancel the `sl-overlay-dismiss` event.
|
||||
|
||||
```html preview
|
||||
<sl-drawer label="Drawer" class="drawer-no-overlay-dismiss">
|
||||
This drawer will not be closed when you click outside of it.
|
||||
<sl-button slot="footer" type="primary">Close</sl-button>
|
||||
<sl-drawer label="Drawer" class="drawer-deny-close">
|
||||
This dialog will not close unless you use the button below.
|
||||
<sl-button slot="footer" type="primary">Save & Close</sl-button>
|
||||
</sl-drawer>
|
||||
|
||||
<sl-button>Open Drawer</sl-button>
|
||||
|
||||
<script>
|
||||
const drawer = document.querySelector('.drawer-no-overlay-dismiss');
|
||||
const drawer = document.querySelector('.drawer-deny-close');
|
||||
const openButton = drawer.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('sl-button[type="primary"]');
|
||||
|
||||
openButton.addEventListener('click', () => drawer.show());
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
|
||||
drawer.addEventListener('sl-overlay-dismiss', event => event.preventDefault());
|
||||
drawer.addEventListener('sl-request-close', event => event.preventDefault());
|
||||
</script>
|
||||
```
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
|
|||
|
||||
## Next
|
||||
|
||||
- 🚨 BREAKING: removed the `sl-overlay-click` event from `sl-dialog` and `sl-drawer` (use `sl-request-close` instead) [#471](https://github.com/shoelace-style/shoelace/discussions/471)
|
||||
- Added `sl-request-close` event to `sl-dialog` and `sl-drawer`
|
||||
- Added `dialog.denyClose` and `drawer.denyClose` animations
|
||||
- Fixed a bug in `sl-color-picker` where setting `value` immediately wouldn't trigger an update
|
||||
|
||||
## 2.0.0-beta.44
|
||||
|
|
|
@ -42,6 +42,7 @@ let id = 0;
|
|||
*
|
||||
* @animation dialog.show - The animation to use when showing the dialog.
|
||||
* @animation dialog.hide - The animation to use when hiding the dialog.
|
||||
* @animation dialog.denyClose - The animation to use when a request to close the dialog is denied.
|
||||
* @animation dialog.overlay.show - The animation to use when showing the dialog's overlay.
|
||||
* @animation dialog.overlay.hide - The animation to use when hiding the dialog's overlay.
|
||||
*/
|
||||
|
@ -92,8 +93,12 @@ export default class SlDialog extends LitElement {
|
|||
*/
|
||||
@event('sl-initial-focus') slInitialFocus: EventEmitter<void>;
|
||||
|
||||
/** Emitted when the overlay is clicked. Calling `event.preventDefault()` will prevent the dialog from closing. */
|
||||
@event('sl-overlay-dismiss') slOverlayDismiss: EventEmitter<void>;
|
||||
/**
|
||||
* Emitted when the user attempts to close the dialog by clicking the close button, clicking the overlay, or pressing
|
||||
* the escape key. Calling `event.preventDefault()` will prevent the dialog from closing. Avoid using this unless
|
||||
* closing the dialog will result in destructive behavior such as data loss.
|
||||
*/
|
||||
@event('sl-request-close') slRequestClose: EventEmitter<void>;
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
@ -131,14 +136,21 @@ export default class SlDialog extends LitElement {
|
|||
return waitForEvent(this, 'sl-after-hide');
|
||||
}
|
||||
|
||||
handleCloseClick() {
|
||||
private requestClose() {
|
||||
const slRequestClose = this.slRequestClose.emit({ cancelable: true });
|
||||
if (slRequestClose.defaultPrevented) {
|
||||
const animation = getAnimation(this, 'dialog.denyClose');
|
||||
animateTo(this.panel, animation.keyframes, animation.options);
|
||||
return;
|
||||
}
|
||||
|
||||
this.hide();
|
||||
}
|
||||
|
||||
handleKeyDown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') {
|
||||
event.stopPropagation();
|
||||
this.hide();
|
||||
this.requestClose();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,13 +218,6 @@ export default class SlDialog extends LitElement {
|
|||
}
|
||||
}
|
||||
|
||||
handleOverlayClick() {
|
||||
const slOverlayDismiss = this.slOverlayDismiss.emit({ cancelable: true });
|
||||
if (!slOverlayDismiss.defaultPrevented) {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
handleSlotChange() {
|
||||
this.hasFooter = hasSlot(this, 'footer');
|
||||
}
|
||||
|
@ -228,7 +233,7 @@ export default class SlDialog extends LitElement {
|
|||
})}
|
||||
@keydown=${this.handleKeyDown}
|
||||
>
|
||||
<div part="overlay" class="dialog__overlay" @click=${this.handleOverlayClick} tabindex="-1"></div>
|
||||
<div part="overlay" class="dialog__overlay" @click=${this.requestClose} tabindex="-1"></div>
|
||||
|
||||
<div
|
||||
part="panel"
|
||||
|
@ -251,7 +256,7 @@ export default class SlDialog extends LitElement {
|
|||
class="dialog__close"
|
||||
name="x"
|
||||
library="system"
|
||||
@click="${this.handleCloseClick}"
|
||||
@click="${this.requestClose}"
|
||||
></sl-icon-button>
|
||||
</header>
|
||||
`
|
||||
|
@ -286,6 +291,11 @@ setDefaultAnimation('dialog.hide', {
|
|||
options: { duration: 250, easing: 'ease' }
|
||||
});
|
||||
|
||||
setDefaultAnimation('dialog.denyClose', {
|
||||
keyframes: [{ transform: 'scale(1)' }, { transform: 'scale(1.02)' }, { transform: 'scale(1)' }],
|
||||
options: { duration: 250 }
|
||||
});
|
||||
|
||||
setDefaultAnimation('dialog.overlay.show', {
|
||||
keyframes: [{ opacity: 0 }, { opacity: 1 }],
|
||||
options: { duration: 250 }
|
||||
|
|
|
@ -50,6 +50,7 @@ let id = 0;
|
|||
* @animation drawer.hideEnd - The animation to use when hiding a drawer with `end` placement.
|
||||
* @animation drawer.hideBottom - The animation to use when hiding a drawer with `bottom` placement.
|
||||
* @animation drawer.hideStart - The animation to use when hiding a drawer with `start` placement.
|
||||
* @animation drawer.denyClose - The animation to use when a request to close the drawer is denied.
|
||||
* @animation drawer.overlay.show - The animation to use when showing the drawer's overlay.
|
||||
* @animation drawer.overlay.hide - The animation to use when hiding the drawer's overlay.
|
||||
*/
|
||||
|
@ -106,8 +107,12 @@ export default class SlDrawer extends LitElement {
|
|||
/** Emitted when the drawer opens and the panel gains focus. Calling `event.preventDefault()` will prevent focus and allow you to set it on a different element in the drawer, such as an input or button. */
|
||||
@event('sl-initial-focus') slInitialFocus: EventEmitter<void>;
|
||||
|
||||
/** Emitted when the overlay is clicked. Calling `event.preventDefault()` will prevent the drawer from closing. */
|
||||
@event('sl-overlay-dismiss') slOverlayDismiss: EventEmitter<void>;
|
||||
/**
|
||||
* Emitted when the user attempts to close the drawer by clicking the close button, clicking the overlay, or pressing
|
||||
* the escape key. Calling `event.preventDefault()` will prevent the drawer from closing. Avoid using this unless
|
||||
* closing the drawer will result in destructive behavior such as data loss.
|
||||
*/
|
||||
@event('sl-request-close') slRequestClose: EventEmitter<void>;
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
@ -145,14 +150,21 @@ export default class SlDrawer extends LitElement {
|
|||
return waitForEvent(this, 'sl-after-hide');
|
||||
}
|
||||
|
||||
handleCloseClick() {
|
||||
private requestClose() {
|
||||
const slRequestClose = this.slRequestClose.emit({ cancelable: true });
|
||||
if (slRequestClose.defaultPrevented) {
|
||||
const animation = getAnimation(this, 'drawer.denyClose');
|
||||
animateTo(this.panel, animation.keyframes, animation.options);
|
||||
return;
|
||||
}
|
||||
|
||||
this.hide();
|
||||
}
|
||||
|
||||
handleKeyDown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') {
|
||||
event.stopPropagation();
|
||||
this.hide();
|
||||
this.requestClose();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,13 +235,6 @@ export default class SlDrawer extends LitElement {
|
|||
}
|
||||
}
|
||||
|
||||
handleOverlayClick() {
|
||||
const slOverlayDismiss = this.slOverlayDismiss.emit({ cancelable: true });
|
||||
if (!slOverlayDismiss.defaultPrevented) {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
handleSlotChange() {
|
||||
this.hasFooter = hasSlot(this, 'footer');
|
||||
}
|
||||
|
@ -251,7 +256,7 @@ export default class SlDrawer extends LitElement {
|
|||
})}
|
||||
@keydown=${this.handleKeyDown}
|
||||
>
|
||||
<div part="overlay" class="drawer__overlay" @click=${this.handleOverlayClick} tabindex="-1"></div>
|
||||
<div part="overlay" class="drawer__overlay" @click=${this.requestClose} tabindex="-1"></div>
|
||||
|
||||
<div
|
||||
part="panel"
|
||||
|
@ -275,7 +280,7 @@ export default class SlDrawer extends LitElement {
|
|||
class="drawer__close"
|
||||
name="x"
|
||||
library="system"
|
||||
@click=${this.handleCloseClick}
|
||||
@click=${this.requestClose}
|
||||
></sl-icon-button>
|
||||
</header>
|
||||
`
|
||||
|
@ -362,6 +367,12 @@ setDefaultAnimation('drawer.hideStart', {
|
|||
options: { duration: 250, easing: 'ease' }
|
||||
});
|
||||
|
||||
// Deny close
|
||||
setDefaultAnimation('drawer.denyClose', {
|
||||
keyframes: [{ transform: 'scale(1)' }, { transform: 'scale(1.01)' }, { transform: 'scale(1)' }],
|
||||
options: { duration: 250 }
|
||||
});
|
||||
|
||||
// Overlay
|
||||
setDefaultAnimation('drawer.overlay.show', {
|
||||
keyframes: [{ opacity: 0 }, { opacity: 1 }],
|
||||
|
|
Ładowanie…
Reference in New Issue