diff --git a/docs/components/dialog.md b/docs/components/dialog.md index a5102a1e..7d332113 100644 --- a/docs/components/dialog.md +++ b/docs/components/dialog.md @@ -159,10 +159,12 @@ By default, dialogs will close when the user clicks the close button, clicks the 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. +You can use `event.detail.source` to determine what triggered the request to close. This example prevents the dialog from closing when the overlay is clicked, but allows the close button or Escape to dismiss it. + ```html preview - This dialog will not close unless you use the button below. - Save & Close + This dialog will not close when you click on the overlay. + Close Open Dialog @@ -170,12 +172,17 @@ To keep the dialog open in such cases, you can cancel the `sl-request-close` eve ``` @@ -186,17 +193,24 @@ import { SlButton, SlDialog } from '@shoelace-style/shoelace/dist/react'; const App = () => { const [open, setOpen] = useState(false); + // Prevent the dialog from closing when the user clicks on the overlay + function handleRequestClose(event) { + if (event.detail.source === 'overlay') { + event.preventDefault(); + } + } + return ( <> event.preventDefault()} + onSlRequestClose={handleRequestClose} onSlAfterHide={() => setOpen(false)} > - This dialog will not close unless you use the button below. + This dialog will not close when you click on the overlay. setOpen(false)}> - Save & Close + Close diff --git a/docs/components/drawer.md b/docs/components/drawer.md index 8c02017d..fab6c3d4 100644 --- a/docs/components/drawer.md +++ b/docs/components/drawer.md @@ -346,10 +346,12 @@ By default, drawers will close when the user clicks the close button, clicks the 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. +You can use `event.detail.source` to determine what triggered the request to close. This example prevents the drawer from closing when the overlay is clicked, but allows the close button or Escape to dismiss it. + ```html preview - This drawer will not close unless you use the button below. - Save & Close + This drawer will not close when you click on the overlay. + Close Open Drawer @@ -362,7 +364,13 @@ To keep the drawer open in such cases, you can cancel the `sl-request-close` eve openButton.addEventListener('click', () => drawer.show()); closeButton.addEventListener('click', () => drawer.hide()); - drawer.addEventListener('sl-request-close', event => event.preventDefault()); + // Prevent the drawer from closing when the user clicks on the overlay + drawer.addEventListener('sl-request-close', event => { + if (event.detail.source === 'overlay') { + event.preventDefault(); + } + }); + ``` @@ -373,15 +381,22 @@ import { SlButton, SlDrawer } from '@shoelace-style/shoelace/dist/react'; const App = () => { const [open, setOpen] = useState(false); + // Prevent the drawer from closing when the user clicks on the overlay + function handleRequestClose(event) { + if (event.detail.source === 'overlay') { + event.preventDefault(); + } + } + return ( <> event.preventDefault()} + onSlRequestClose={handleRequestClose} onSlAfterHide={() => setOpen(false)} > - This drawer will not close unless you use the button below. + This drawer will not close when you click on the overlay. setOpen(false)}> Save & Close diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index 50e52196..ddec02b3 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -11,6 +11,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis - 🚨 BREAKING: the `unit` property of `` has changed to `byte | bit` instead of `bytes | bits` - Added `display-label` part to `` [#650](https://github.com/shoelace-style/shoelace/issues/650) - Added `--spacing` CSS custom property to `` [#664](https://github.com/shoelace-style/shoelace/pull/664) +- Added `event.detail.source` to the `sl-request-close` event in `` and `` - Fixed a bug that caused `` to render the wrong size when `--track-width` was increased [#656](https://github.com/shoelace-style/shoelace/issues/656) - Fixed a bug that allowed `` to open and close when disabled using a screen reader [#658](https://github.com/shoelace-style/shoelace/issues/658) - Fixed a bug in the FormData event polyfill that threw an error in some environments [#666](https://github.com/shoelace-style/shoelace/issues/666) diff --git a/src/components/dialog/dialog.ts b/src/components/dialog/dialog.ts index f9e22154..67998dda 100644 --- a/src/components/dialog/dialog.ts +++ b/src/components/dialog/dialog.ts @@ -32,9 +32,10 @@ const hasPreventScroll = isPreventScrollSupported(); * @event sl-after-hide - Emitted after the dialog closes and all animations are complete. * @event sl-initial-focus - Emitted when the dialog opens and the panel gains focus. Calling `event.preventDefault()` * will prevent focus and allow you to set it on a different element in the dialog, such as an input or button. - * @event sl-request-close - 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 {{ source: 'close-button' | 'keyboard' | 'overlay' }} sl-request-close - Emitted when the user attempts to + * close the dialog by clicking the close button, clicking the overlay, or pressing escape. Calling + * `event.preventDefault()` will keep the dialog open. Avoid using this unless closing the dialog will result in + * destructive behavior such as data loss. * * @csspart base - The component's base wrapper. * @csspart overlay - The overlay. @@ -123,8 +124,12 @@ export default class SlDialog extends LitElement { return waitForEvent(this, 'sl-after-hide'); } - private requestClose() { - const slRequestClose = emit(this, 'sl-request-close', { cancelable: true }); + private requestClose(source: 'close-button' | 'keyboard' | 'overlay') { + const slRequestClose = emit(this, 'sl-request-close', { + cancelable: true, + detail: { source } + }); + if (slRequestClose.defaultPrevented) { const animation = getAnimation(this, 'dialog.denyClose'); animateTo(this.panel, animation.keyframes, animation.options); @@ -137,7 +142,7 @@ export default class SlDialog extends LitElement { handleKeyDown(event: KeyboardEvent) { if (event.key === 'Escape') { event.stopPropagation(); - this.requestClose(); + this.requestClose('keyboard'); } } @@ -217,7 +222,7 @@ export default class SlDialog extends LitElement { })} @keydown=${this.handleKeyDown} > -
+
this.requestClose('overlay')} tabindex="-1">
` diff --git a/src/components/drawer/drawer.ts b/src/components/drawer/drawer.ts index 5bf0cf0a..3319b70f 100644 --- a/src/components/drawer/drawer.ts +++ b/src/components/drawer/drawer.ts @@ -33,9 +33,10 @@ const hasPreventScroll = isPreventScrollSupported(); * @event sl-after-hide - Emitted after the drawer closes and all animations are complete. * @event sl-initial-focus - 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-request-close - 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 {{ source: 'close-button' | 'keyboard' | 'overlay' }} sl-request-close - Emitted when the user attempts to + * close the drawer by clicking the close button, clicking the overlay, or pressing escape. Calling + * `event.preventDefault()` will keep the drawer open. Avoid using this unless closing the drawer will result in + * destructive behavior such as data loss. * * @csspart base - The component's base wrapper. * @csspart overlay - The overlay. @@ -140,8 +141,12 @@ export default class SlDrawer extends LitElement { return waitForEvent(this, 'sl-after-hide'); } - private requestClose() { - const slRequestClose = emit(this, 'sl-request-close', { cancelable: true }); + private requestClose(source: 'close-button' | 'keyboard' | 'overlay') { + const slRequestClose = emit(this, 'sl-request-close', { + cancelable: true, + detail: { source } + }); + if (slRequestClose.defaultPrevented) { const animation = getAnimation(this, 'drawer.denyClose'); animateTo(this.panel, animation.keyframes, animation.options); @@ -154,7 +159,7 @@ export default class SlDrawer extends LitElement { handleKeyDown(event: KeyboardEvent) { if (event.key === 'Escape') { event.stopPropagation(); - this.requestClose(); + this.requestClose('keyboard'); } } @@ -243,7 +248,7 @@ export default class SlDrawer extends LitElement { })} @keydown=${this.handleKeyDown} > -
+
this.requestClose('overlay')} tabindex="-1">
this.requestClose('close-button')} > `