diff --git a/js/src/offcanvas.js b/js/src/offcanvas.js index 88eb8c997a..016260437c 100644 --- a/js/src/offcanvas.js +++ b/js/src/offcanvas.js @@ -45,6 +45,7 @@ const DefaultType = { } const CLASS_NAME_SHOW = 'show' +const CLASS_NAME_BACKDROP = 'offcanvas-backdrop' const OPEN_SELECTOR = '.offcanvas.show' const EVENT_SHOW = `show${EVENT_KEY}` @@ -177,6 +178,7 @@ class Offcanvas extends BaseComponent { _initializeBackDrop() { return new Backdrop({ + className: CLASS_NAME_BACKDROP, isVisible: this._config.backdrop, isAnimated: true, rootElement: this._element.parentNode, diff --git a/js/src/util/backdrop.js b/js/src/util/backdrop.js index 7ba7b4c43e..fbe32445ea 100644 --- a/js/src/util/backdrop.js +++ b/js/src/util/backdrop.js @@ -9,6 +9,7 @@ import EventHandler from '../dom/event-handler' import { execute, executeAfterTransition, getElement, reflow, typeCheckConfig } from './index' const Default = { + className: 'modal-backdrop', isVisible: true, // if false, we use the backdrop helper without adding any element to the dom isAnimated: false, rootElement: 'body', // give the choice to place backdrop under different elements @@ -16,13 +17,13 @@ const Default = { } const DefaultType = { + className: 'string', isVisible: 'boolean', isAnimated: 'boolean', rootElement: '(element|string)', clickCallback: '(function|null)' } const NAME = 'backdrop' -const CLASS_NAME_BACKDROP = 'modal-backdrop' const CLASS_NAME_FADE = 'fade' const CLASS_NAME_SHOW = 'show' @@ -73,7 +74,7 @@ class Backdrop { _getElement() { if (!this._element) { const backdrop = document.createElement('div') - backdrop.className = CLASS_NAME_BACKDROP + backdrop.className = this._config.className if (this._config.isAnimated) { backdrop.classList.add(CLASS_NAME_FADE) } diff --git a/js/tests/unit/util/backdrop.spec.js b/js/tests/unit/util/backdrop.spec.js index 3150ba14db..59b7890717 100644 --- a/js/tests/unit/util/backdrop.spec.js +++ b/js/tests/unit/util/backdrop.spec.js @@ -230,46 +230,62 @@ describe('Backdrop', () => { }) }) }) - - describe('rootElement initialization', () => { - it('Should be appended on "document.body" by default', done => { - const instance = new Backdrop({ - isVisible: true + describe('Config', () => { + describe('rootElement initialization', () => { + it('Should be appended on "document.body" by default', done => { + const instance = new Backdrop({ + isVisible: true + }) + const getElement = () => document.querySelector(CLASS_BACKDROP) + instance.show(() => { + expect(getElement().parentElement).toEqual(document.body) + done() + }) }) - const getElement = () => document.querySelector(CLASS_BACKDROP) - instance.show(() => { - expect(getElement().parentElement).toEqual(document.body) - done() + + it('Should find the rootElement if passed as a string', done => { + const instance = new Backdrop({ + isVisible: true, + rootElement: 'body' + }) + const getElement = () => document.querySelector(CLASS_BACKDROP) + instance.show(() => { + expect(getElement().parentElement).toEqual(document.body) + done() + }) + }) + + it('Should appended on any element given by the proper config', done => { + fixtureEl.innerHTML = [ + '
', + '
' + ].join('') + + const wrapper = fixtureEl.querySelector('#wrapper') + const instance = new Backdrop({ + isVisible: true, + rootElement: wrapper + }) + const getElement = () => document.querySelector(CLASS_BACKDROP) + instance.show(() => { + expect(getElement().parentElement).toEqual(wrapper) + done() + }) }) }) - it('Should find the rootElement if passed as a string', done => { - const instance = new Backdrop({ - isVisible: true, - rootElement: 'body' - }) - const getElement = () => document.querySelector(CLASS_BACKDROP) - instance.show(() => { - expect(getElement().parentElement).toEqual(document.body) - done() - }) - }) - - it('Should appended on any element given by the proper config', done => { - fixtureEl.innerHTML = [ - '
', - '
' - ].join('') - - const wrapper = fixtureEl.querySelector('#wrapper') - const instance = new Backdrop({ - isVisible: true, - rootElement: wrapper - }) - const getElement = () => document.querySelector(CLASS_BACKDROP) - instance.show(() => { - expect(getElement().parentElement).toEqual(wrapper) - done() + describe('ClassName', () => { + it('Should be able to have different classNames than default', done => { + const instance = new Backdrop({ + isVisible: true, + className: 'foo' + }) + const getElement = () => document.querySelector('.foo') + instance.show(() => { + expect(getElement()).toEqual(instance._getElement()) + instance.dispose() + done() + }) }) }) }) diff --git a/scss/_mixins.scss b/scss/_mixins.scss index eec085789a..af1f74f72e 100644 --- a/scss/_mixins.scss +++ b/scss/_mixins.scss @@ -22,6 +22,7 @@ // Components @import "mixins/alert"; +@import "mixins/backdrop"; @import "mixins/buttons"; @import "mixins/caret"; @import "mixins/pagination"; diff --git a/scss/_modal.scss b/scss/_modal.scss index 77473085ce..21e1258f55 100644 --- a/scss/_modal.scss +++ b/scss/_modal.scss @@ -85,17 +85,7 @@ // Modal background .modal-backdrop { - position: fixed; - top: 0; - left: 0; - z-index: $zindex-modal-backdrop; - width: 100vw; - height: 100vh; - background-color: $modal-backdrop-bg; - - // Fade for backdrop - &.fade { opacity: 0; } - &.show { opacity: $modal-backdrop-opacity; } + @include overlay-backdrop($zindex-modal-backdrop, $modal-backdrop-bg, $modal-backdrop-opacity); } // Modal header diff --git a/scss/_offcanvas.scss b/scss/_offcanvas.scss index 91db686434..a089c2a081 100644 --- a/scss/_offcanvas.scss +++ b/scss/_offcanvas.scss @@ -14,6 +14,10 @@ @include transition(transform $offcanvas-transition-duration ease-in-out); } +.offcanvas-backdrop { + @include overlay-backdrop($zindex-offcanvas-backdrop, $offcanvas-backdrop-bg, $offcanvas-backdrop-opacity); +} + .offcanvas-header { display: flex; align-items: center; diff --git a/scss/_variables.scss b/scss/_variables.scss index 8abd750329..aa4d4ff2fb 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -907,9 +907,10 @@ $form-validation-states: ( $zindex-dropdown: 1000 !default; $zindex-sticky: 1020 !default; $zindex-fixed: 1030 !default; -$zindex-modal-backdrop: 1040 !default; -$zindex-offcanvas: 1050 !default; -$zindex-modal: 1060 !default; +$zindex-offcanvas-backdrop: 1040 !default; +$zindex-offcanvas: 1045 !default; +$zindex-modal-backdrop: 1050 !default; +$zindex-modal: 1055 !default; $zindex-popover: 1070 !default; $zindex-tooltip: 1080 !default; // scss-docs-end zindex-stack @@ -1453,6 +1454,8 @@ $offcanvas-title-line-height: $modal-title-line-height !default; $offcanvas-bg-color: $modal-content-bg !default; $offcanvas-color: $modal-content-color !default; $offcanvas-box-shadow: $modal-content-box-shadow-xs !default; +$offcanvas-backdrop-bg: $modal-backdrop-bg !default; +$offcanvas-backdrop-opacity: $modal-backdrop-opacity !default; // scss-docs-end offcanvas-variables // Code diff --git a/scss/mixins/_backdrop.scss b/scss/mixins/_backdrop.scss new file mode 100644 index 0000000000..9705ae9eea --- /dev/null +++ b/scss/mixins/_backdrop.scss @@ -0,0 +1,14 @@ +// Shared between modals and offcanvases +@mixin overlay-backdrop($zindex, $backdrop-bg, $backdrop-opacity) { + position: fixed; + top: 0; + left: 0; + z-index: $zindex; + width: 100vw; + height: 100vh; + background-color: $backdrop-bg; + + // Fade for backdrop + &.fade { opacity: 0; } + &.show { opacity: $backdrop-opacity; } +}