mirror of
https://github.com/twbs/bootstrap.git
synced 2025-01-18 10:52:19 +01:00
Use a streamlined way to trigger component dismiss (#34170)
* use a streamlined way to trigger component dismiss * add documentation Co-authored-by: XhmikosR <xhmikosr@gmail.com>
This commit is contained in:
parent
047145e808
commit
4bfd8a2cbc
@ -5,13 +5,10 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { defineJQueryPlugin } from './util/index'
|
||||||
defineJQueryPlugin,
|
|
||||||
getElementFromSelector,
|
|
||||||
isDisabled
|
|
||||||
} from './util/index'
|
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
|
import { enableDismissTrigger } from './util/component-functions'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
@ -22,15 +19,9 @@ import BaseComponent from './base-component'
|
|||||||
const NAME = 'alert'
|
const NAME = 'alert'
|
||||||
const DATA_KEY = 'bs.alert'
|
const DATA_KEY = 'bs.alert'
|
||||||
const EVENT_KEY = `.${DATA_KEY}`
|
const EVENT_KEY = `.${DATA_KEY}`
|
||||||
const DATA_API_KEY = '.data-api'
|
|
||||||
|
|
||||||
const SELECTOR_DISMISS = '[data-bs-dismiss="alert"]'
|
|
||||||
|
|
||||||
const EVENT_CLOSE = `close${EVENT_KEY}`
|
const EVENT_CLOSE = `close${EVENT_KEY}`
|
||||||
const EVENT_CLOSED = `closed${EVENT_KEY}`
|
const EVENT_CLOSED = `closed${EVENT_KEY}`
|
||||||
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
|
|
||||||
|
|
||||||
const CLASS_NAME_ALERT = 'alert'
|
|
||||||
const CLASS_NAME_FADE = 'fade'
|
const CLASS_NAME_FADE = 'fade'
|
||||||
const CLASS_NAME_SHOW = 'show'
|
const CLASS_NAME_SHOW = 'show'
|
||||||
|
|
||||||
@ -94,20 +85,7 @@ class Alert extends BaseComponent {
|
|||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DISMISS, function (event) {
|
enableDismissTrigger(Alert, 'close')
|
||||||
if (['A', 'AREA'].includes(this.tagName)) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDisabled(this)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const target = getElementFromSelector(this) || this.closest(`.${CLASS_NAME_ALERT}`)
|
|
||||||
const alert = Alert.getOrCreateInstance(target)
|
|
||||||
alert.close()
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
* jQuery
|
* jQuery
|
||||||
|
@ -20,6 +20,7 @@ import ScrollBarHelper from './util/scrollbar'
|
|||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
import Backdrop from './util/backdrop'
|
import Backdrop from './util/backdrop'
|
||||||
import FocusTrap from './util/focustrap'
|
import FocusTrap from './util/focustrap'
|
||||||
|
import { enableDismissTrigger } from './util/component-functions'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
@ -62,11 +63,9 @@ const CLASS_NAME_FADE = 'fade'
|
|||||||
const CLASS_NAME_SHOW = 'show'
|
const CLASS_NAME_SHOW = 'show'
|
||||||
const CLASS_NAME_STATIC = 'modal-static'
|
const CLASS_NAME_STATIC = 'modal-static'
|
||||||
|
|
||||||
const SELECTOR = '.modal'
|
|
||||||
const SELECTOR_DIALOG = '.modal-dialog'
|
const SELECTOR_DIALOG = '.modal-dialog'
|
||||||
const SELECTOR_MODAL_BODY = '.modal-body'
|
const SELECTOR_MODAL_BODY = '.modal-body'
|
||||||
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]'
|
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]'
|
||||||
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
@ -143,11 +142,7 @@ class Modal extends BaseComponent {
|
|||||||
this._showBackdrop(() => this._showElement(relatedTarget))
|
this._showBackdrop(() => this._showElement(relatedTarget))
|
||||||
}
|
}
|
||||||
|
|
||||||
hide(event) {
|
hide() {
|
||||||
if (event && ['A', 'AREA'].includes(event.target.tagName)) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._isShown || this._isTransitioning) {
|
if (!this._isShown || this._isTransitioning) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -421,12 +416,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
|
|||||||
data.toggle(this)
|
data.toggle(this)
|
||||||
})
|
})
|
||||||
|
|
||||||
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_DISMISS, function (event) {
|
enableDismissTrigger(Modal)
|
||||||
const target = getElementFromSelector(this) || this.closest(SELECTOR)
|
|
||||||
const modal = Modal.getOrCreateInstance(target)
|
|
||||||
|
|
||||||
modal.hide(event)
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
|
@ -19,6 +19,7 @@ import SelectorEngine from './dom/selector-engine'
|
|||||||
import Manipulator from './dom/manipulator'
|
import Manipulator from './dom/manipulator'
|
||||||
import Backdrop from './util/backdrop'
|
import Backdrop from './util/backdrop'
|
||||||
import FocusTrap from './util/focustrap'
|
import FocusTrap from './util/focustrap'
|
||||||
|
import { enableDismissTrigger } from './util/component-functions'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
@ -54,10 +55,8 @@ const EVENT_SHOWN = `shown${EVENT_KEY}`
|
|||||||
const EVENT_HIDE = `hide${EVENT_KEY}`
|
const EVENT_HIDE = `hide${EVENT_KEY}`
|
||||||
const EVENT_HIDDEN = `hidden${EVENT_KEY}`
|
const EVENT_HIDDEN = `hidden${EVENT_KEY}`
|
||||||
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
|
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
|
||||||
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`
|
|
||||||
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`
|
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`
|
||||||
|
|
||||||
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]'
|
|
||||||
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]'
|
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,8 +196,6 @@ class Offcanvas extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_addEventListeners() {
|
_addEventListeners() {
|
||||||
EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide())
|
|
||||||
|
|
||||||
EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {
|
EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {
|
||||||
if (this._config.keyboard && event.key === ESCAPE_KEY) {
|
if (this._config.keyboard && event.key === ESCAPE_KEY) {
|
||||||
this.hide()
|
this.hide()
|
||||||
@ -263,6 +260,7 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () =>
|
|||||||
SelectorEngine.find(OPEN_SELECTOR).forEach(el => Offcanvas.getOrCreateInstance(el).show())
|
SelectorEngine.find(OPEN_SELECTOR).forEach(el => Offcanvas.getOrCreateInstance(el).show())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enableDismissTrigger(Offcanvas)
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
* jQuery
|
* jQuery
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from './dom/event-handler'
|
||||||
import Manipulator from './dom/manipulator'
|
import Manipulator from './dom/manipulator'
|
||||||
import BaseComponent from './base-component'
|
import BaseComponent from './base-component'
|
||||||
|
import { enableDismissTrigger } from './util/component-functions'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
@ -24,7 +25,6 @@ const NAME = 'toast'
|
|||||||
const DATA_KEY = 'bs.toast'
|
const DATA_KEY = 'bs.toast'
|
||||||
const EVENT_KEY = `.${DATA_KEY}`
|
const EVENT_KEY = `.${DATA_KEY}`
|
||||||
|
|
||||||
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`
|
|
||||||
const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`
|
const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`
|
||||||
const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`
|
const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`
|
||||||
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`
|
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`
|
||||||
@ -51,8 +51,6 @@ const Default = {
|
|||||||
delay: 5000
|
delay: 5000
|
||||||
}
|
}
|
||||||
|
|
||||||
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="toast"]'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
* Class Definition
|
* Class Definition
|
||||||
@ -202,7 +200,6 @@ class Toast extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_setListeners() {
|
_setListeners() {
|
||||||
EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide())
|
|
||||||
EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true))
|
EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true))
|
||||||
EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false))
|
EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false))
|
||||||
EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true))
|
EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true))
|
||||||
@ -231,6 +228,8 @@ class Toast extends BaseComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableDismissTrigger(Toast)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
* jQuery
|
* jQuery
|
||||||
|
34
js/src/util/component-functions.js
Normal file
34
js/src/util/component-functions.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* Bootstrap (v5.0.2): util/component-functions.js
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
import EventHandler from '../dom/event-handler'
|
||||||
|
import { getElementFromSelector, isDisabled } from './index'
|
||||||
|
|
||||||
|
const enableDismissTrigger = (component, method = 'hide') => {
|
||||||
|
const clickEvent = `click.dismiss${component.EVENT_KEY}`
|
||||||
|
const name = component.NAME
|
||||||
|
|
||||||
|
EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) {
|
||||||
|
if (['A', 'AREA'].includes(this.tagName)) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDisabled(this)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = getElementFromSelector(this) || this.closest(`.${name}`)
|
||||||
|
const instance = component.getOrCreateInstance(target)
|
||||||
|
|
||||||
|
// Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
|
||||||
|
instance[method]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
enableDismissTrigger
|
||||||
|
}
|
@ -467,18 +467,14 @@ describe('Toast', () => {
|
|||||||
fixtureEl.innerHTML = '<div></div>'
|
fixtureEl.innerHTML = '<div></div>'
|
||||||
|
|
||||||
const toastEl = fixtureEl.querySelector('div')
|
const toastEl = fixtureEl.querySelector('div')
|
||||||
spyOn(toastEl, 'addEventListener').and.callThrough()
|
|
||||||
spyOn(toastEl, 'removeEventListener').and.callThrough()
|
|
||||||
|
|
||||||
const toast = new Toast(toastEl)
|
const toast = new Toast(toastEl)
|
||||||
|
|
||||||
expect(Toast.getInstance(toastEl)).not.toBeNull()
|
expect(Toast.getInstance(toastEl)).not.toBeNull()
|
||||||
expect(toastEl.addEventListener).toHaveBeenCalledWith('click', jasmine.any(Function), jasmine.any(Boolean))
|
|
||||||
|
|
||||||
toast.dispose()
|
toast.dispose()
|
||||||
|
|
||||||
expect(Toast.getInstance(toastEl)).toBeNull()
|
expect(Toast.getInstance(toastEl)).toBeNull()
|
||||||
expect(toastEl.removeEventListener).toHaveBeenCalledWith('click', jasmine.any(Function), jasmine.any(Boolean))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should allow to destroy toast and hide it before that', done => {
|
it('should allow to destroy toast and hide it before that', done => {
|
||||||
|
108
js/tests/unit/util/component-functions.spec.js
Normal file
108
js/tests/unit/util/component-functions.spec.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* Test helpers */
|
||||||
|
|
||||||
|
import { clearFixture, createEvent, getFixture } from '../../helpers/fixture'
|
||||||
|
import { enableDismissTrigger } from '../../../src/util/component-functions'
|
||||||
|
import BaseComponent from '../../../src/base-component'
|
||||||
|
|
||||||
|
class DummyClass2 extends BaseComponent {
|
||||||
|
static get NAME() {
|
||||||
|
return 'test'
|
||||||
|
}
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
testMethod() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Plugin functions', () => {
|
||||||
|
let fixtureEl
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
fixtureEl = getFixture()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
clearFixture()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('data-bs-dismiss functionality', () => {
|
||||||
|
it('should get Plugin and execute the given method, when a click occurred on data-bs-dismiss="PluginName"', () => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<div id="foo" class="test">',
|
||||||
|
' <button type="button" data-bs-dismiss="test" data-bs-target="#foo"></button>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
spyOn(DummyClass2, 'getOrCreateInstance').and.callThrough()
|
||||||
|
spyOn(DummyClass2.prototype, 'testMethod')
|
||||||
|
const componentWrapper = fixtureEl.querySelector('#foo')
|
||||||
|
const btnClose = fixtureEl.querySelector('[data-bs-dismiss="test"]')
|
||||||
|
const event = createEvent('click')
|
||||||
|
|
||||||
|
enableDismissTrigger(DummyClass2, 'testMethod')
|
||||||
|
btnClose.dispatchEvent(event)
|
||||||
|
|
||||||
|
expect(DummyClass2.getOrCreateInstance).toHaveBeenCalledWith(componentWrapper)
|
||||||
|
expect(DummyClass2.prototype.testMethod).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('if data-bs-dismiss="PluginName" hasn\'t got "data-bs-target", "getOrCreateInstance" has to be initialized by closest "plugin.Name" class', () => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<div id="foo" class="test">',
|
||||||
|
' <button type="button" data-bs-dismiss="test"></button>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
spyOn(DummyClass2, 'getOrCreateInstance').and.callThrough()
|
||||||
|
spyOn(DummyClass2.prototype, 'hide')
|
||||||
|
const componentWrapper = fixtureEl.querySelector('#foo')
|
||||||
|
const btnClose = fixtureEl.querySelector('[data-bs-dismiss="test"]')
|
||||||
|
const event = createEvent('click')
|
||||||
|
|
||||||
|
enableDismissTrigger(DummyClass2)
|
||||||
|
btnClose.dispatchEvent(event)
|
||||||
|
|
||||||
|
expect(DummyClass2.getOrCreateInstance).toHaveBeenCalledWith(componentWrapper)
|
||||||
|
expect(DummyClass2.prototype.hide).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('if data-bs-dismiss="PluginName" is disabled, must not trigger function', () => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<div id="foo" class="test">',
|
||||||
|
' <button type="button" disabled data-bs-dismiss="test"></button>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
spyOn(DummyClass2, 'getOrCreateInstance').and.callThrough()
|
||||||
|
const btnClose = fixtureEl.querySelector('[data-bs-dismiss="test"]')
|
||||||
|
const event = createEvent('click')
|
||||||
|
|
||||||
|
enableDismissTrigger(DummyClass2)
|
||||||
|
btnClose.dispatchEvent(event)
|
||||||
|
|
||||||
|
expect(DummyClass2.getOrCreateInstance).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should prevent default when the trigger is <a> or <area>', () => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<div id="foo" class="test">',
|
||||||
|
' <a type="button" data-bs-dismiss="test"></a>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const btnClose = fixtureEl.querySelector('[data-bs-dismiss="test"]')
|
||||||
|
const event = createEvent('click')
|
||||||
|
|
||||||
|
enableDismissTrigger(DummyClass2)
|
||||||
|
spyOn(Event.prototype, 'preventDefault').and.callThrough()
|
||||||
|
|
||||||
|
btnClose.dispatchEvent(event)
|
||||||
|
|
||||||
|
expect(Event.prototype.preventDefault).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -204,17 +204,7 @@ See the [triggers](#triggers) section for more details.
|
|||||||
|
|
||||||
### Triggers
|
### Triggers
|
||||||
|
|
||||||
Dismissal can be achieved with `data` attributes on a button **within the alert** as demonstrated above:
|
{{% js-dismiss "alert" %}}
|
||||||
|
|
||||||
```html
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
```
|
|
||||||
|
|
||||||
or on a button **outside the alert** using the `data-bs-target` as demonstrated above:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" data-bs-target="#my-alert" aria-label="Close"></button>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note that closing an alert will remove it from the DOM.**
|
**Note that closing an alert will remove it from the DOM.**
|
||||||
|
|
||||||
|
@ -840,17 +840,8 @@ Activate a modal without writing JavaScript. Set `data-bs-toggle="modal"` on a c
|
|||||||
```
|
```
|
||||||
#### Dismiss
|
#### Dismiss
|
||||||
|
|
||||||
Dismissal can be achieved with `data` attributes on a button **within the modal** as demonstrated below:
|
{{% js-dismiss "modal" %}}
|
||||||
|
|
||||||
```html
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
```
|
|
||||||
|
|
||||||
or on a button **outside the modal** using the `data-bs-target` as demonstrated below:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" data-bs-target="#my-modal" aria-label="Close"></button>
|
|
||||||
```
|
|
||||||
{{< callout warning >}}
|
{{< callout warning >}}
|
||||||
While both ways to dismiss a modal are supported, keep in mind that dismissing from outside a modal does not match [the WAI-ARIA modal dialog design pattern](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal). Do this at your own risk.
|
While both ways to dismiss a modal are supported, keep in mind that dismissing from outside a modal does not match [the WAI-ARIA modal dialog design pattern](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal). Do this at your own risk.
|
||||||
{{< /callout >}}
|
{{< /callout >}}
|
||||||
|
@ -194,8 +194,18 @@ Add a dismiss button with the `data-bs-dismiss="offcanvas"` attribute, which tri
|
|||||||
|
|
||||||
### Via data attributes
|
### Via data attributes
|
||||||
|
|
||||||
|
#### Toggle
|
||||||
|
|
||||||
Add `data-bs-toggle="offcanvas"` and a `data-bs-target` or `href` to the element to automatically assign control of one offcanvas element. The `data-bs-target` attribute accepts a CSS selector to apply the offcanvas to. Be sure to add the class `offcanvas` to the offcanvas element. If you'd like it to default open, add the additional class `show`.
|
Add `data-bs-toggle="offcanvas"` and a `data-bs-target` or `href` to the element to automatically assign control of one offcanvas element. The `data-bs-target` attribute accepts a CSS selector to apply the offcanvas to. Be sure to add the class `offcanvas` to the offcanvas element. If you'd like it to default open, add the additional class `show`.
|
||||||
|
|
||||||
|
#### Dismiss
|
||||||
|
|
||||||
|
{{% js-dismiss "offcanvas" %}}
|
||||||
|
|
||||||
|
{{< callout warning >}}
|
||||||
|
While both ways to dismiss an offcanvas are supported, keep in mind that dismissing from outside an offcanvas does not match [the WAI-ARIA modal dialog design pattern](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal). Do this at your own risk.
|
||||||
|
{{< /callout >}}
|
||||||
|
|
||||||
### Via JavaScript
|
### Via JavaScript
|
||||||
|
|
||||||
Enable manually with:
|
Enable manually with:
|
||||||
|
@ -341,6 +341,10 @@ var toastList = toastElList.map(function (toastEl) {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Triggers
|
||||||
|
|
||||||
|
{{% js-dismiss "toast" %}}
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
Options can be passed via data attributes or JavaScript. For data attributes, append the option name to `data-bs-`, as in `data-bs-animation=""`.
|
Options can be passed via data attributes or JavaScript. For data attributes, append the option name to `data-bs-`, as in `data-bs-animation=""`.
|
||||||
|
15
site/layouts/shortcodes/js-dismiss.html
Normal file
15
site/layouts/shortcodes/js-dismiss.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{{- /* Usage: js-dismiss "ComponentName" */ -}}
|
||||||
|
|
||||||
|
{{- $name := .Get 0 -}}
|
||||||
|
|
||||||
|
Dismissal can be achieved with the `data` attribute on a button **within the {{ $name }}** as demonstrated below:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="{{ $name }}" aria-label="Close"></button>
|
||||||
|
```
|
||||||
|
|
||||||
|
or on a button **outside the {{ $name }}** using the `data-bs-target` as demonstrated below:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="{{ $name }}" data-bs-target="#my-{{ $name }}" aria-label="Close"></button>
|
||||||
|
```
|
Loading…
x
Reference in New Issue
Block a user