From 40a4213b98076ae55d7fb5dd0bb618c4f98f7a9d Mon Sep 17 00:00:00 2001 From: Marcos Moura Date: Thu, 17 Nov 2016 03:05:25 -0200 Subject: [PATCH] Create dialog opening from and closing to --- docs/src/pages/components/Dialog.vue | 4 +- src/components/mdDialog/mdDialog.scss | 82 ++++++++++++------- src/components/mdDialog/mdDialog.vue | 112 +++++++++++++++++++++----- 3 files changed, 144 insertions(+), 54 deletions(-) diff --git a/docs/src/pages/components/Dialog.vue b/docs/src/pages/components/Dialog.vue index 0ecf682..4b32bfb 100644 --- a/docs/src/pages/components/Dialog.vue +++ b/docs/src/pages/components/Dialog.vue @@ -2,7 +2,7 @@
- +
@@ -15,7 +15,7 @@ Close - Open + Open
diff --git a/src/components/mdDialog/mdDialog.scss b/src/components/mdDialog/mdDialog.scss index f5e628d..1a6ac6e 100644 --- a/src/components/mdDialog/mdDialog.scss +++ b/src/components/mdDialog/mdDialog.scss @@ -1,44 +1,64 @@ @import '../../core/stylesheets/variables.scss'; -.md-dialog { - min-width: 280px; - max-width: 80%; - max-height: 80%; - overflow: hidden; +.md-dialog-container { + display: flex; + flex-flow: column; + justify-content: center; + align-items: center; + pointer-events: none; position: fixed; - top: 50%; - left: 50%; - z-index: 110; - outline: none; - border-radius: 2px; - opacity: 0; - filter: drop-shadow(0 7px 8px rgba(#000, $shadow-key-umbra-opacity)) - drop-shadow(0 12px 17px rgba(#000, $shadow-key-penumbra-opacity)) - drop-shadow(0 5px 22px rgba(#000, $shadow-ambient-shadow-opacity)); - clip-path: inset(0 7% 12% 7%); - transform: translate3D(-50%, -60%, 0) scale(.85); - transition: transform $swift-ease-out-duration $swift-ease-out-timing-function, - opacity .3s $swift-ease-out-timing-function, - clip-path .3s .1s $swift-ease-out-timing-function; - transition-delay: 0; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 108; &.md-active { pointer-events: auto; - opacity: 1; - clip-path: inset(-22px -22px -22px -22px); - transition: transform $swift-ease-out-duration $swift-ease-out-timing-function, - opacity .5s $swift-ease-out-timing-function, - clip-path .4s .1s $swift-ease-out-timing-function; - transition-delay: 0; - transform: translate3D(-50%, -50%, 0) scale(1); - } -} -.md-dialog-container { - padding: 24px; + .md-dialog { + opacity: 1 !important; + transform: scale(1) !important; + transition: $swift-ease-out; + transform-property: opacity, transform; + + > * { + opacity: 1; + } + } + } } .md-dialog-backdrop { position: fixed; z-index: 109; } + +.md-dialog { + min-width: 280px; + max-width: 80%; + max-height: 80%; + overflow: hidden; + position: relative; + z-index: 110; + outline: none; + border-radius: 2px; + opacity: 0; + box-shadow: $material-shadow-14dp; + transform: scale(.9, .85); + transition: opacity $swift-ease-out-duration $swift-ease-out-timing-function, + transform $swift-ease-out-duration .05s $swift-ease-out-timing-function; + will-change: opacity, transform; + + &.md-transition-off { + transition: none; + } + + > * { + opacity: 0; + transition: $swift-ease-out; + transition-property: opacity; + transition-delay: .1s; + will-change: opacity; + } +} diff --git a/src/components/mdDialog/mdDialog.vue b/src/components/mdDialog/mdDialog.vue index d6b9a53..19f6cb8 100644 --- a/src/components/mdDialog/mdDialog.vue +++ b/src/components/mdDialog/mdDialog.vue @@ -1,10 +1,10 @@ @@ -14,31 +14,99 @@ import transitionEndEventName from '../../core/utils/transitionEndEventName'; export default { + props: { + mdClickOutsideToClose: { + type: Boolean, + default: true + }, + mdEscToClose: { + type: Boolean, + default: true + }, + mdBackdrop: { + type: Boolean, + default: true + }, + mdOpenFrom: String, + mdCloseTo: String, + mdFullscreen: { + type: Boolean, + default: false + } + }, data: () => ({ - active: false + active: false, + transitionOff: false, + dialogTransform: '', + dialogTransformOrigin: '' }), + computed: { + classes() { + return { + 'md-fullscreen': this.mdFullscreen, + 'md-active': this.active + }; + }, + dialogClasses() { + return { + 'md-transition-off': this.transitionOff + }; + }, + styles() { + return { + transform: this.dialogTransform, + 'transform-origin': this.dialogTransformOrigin + }; + } + }, methods: { - open() { - this.close(); - this.$root.$el.appendChild(this.dialogElement); - this.$root.$el.appendChild(this.backdropElement); + removeDialog() { + this.$el.parentNode.removeChild(this.$el); + }, + calculateDialogPos(ref) { + const reference = document.querySelector(ref); - getComputedStyle(this.dialogElement).opacity; - this.dialogElement.focus(); - this.dialogElement.classList.add('md-active'); - this.backdropElement.classList.add('md-active'); + if (reference) { + const openFromRect = reference.getBoundingClientRect(); + const dialogRect = this.dialogInnerElement.getBoundingClientRect(); + const topDistance = dialogRect.top - openFromRect.top; + const leftDistance = dialogRect.left - openFromRect.left; + const widthInScale = openFromRect.width / dialogRect.width; + const heightInScale = openFromRect.height / dialogRect.height; + + this.dialogTransform = `translate3D(-${leftDistance}px, -${topDistance}px, 0) scale(${widthInScale}, ${heightInScale})`; + this.dialogTransformOrigin = 'top left'; + } + }, + open() { + this.$root.$el.appendChild(this.dialogElement); + this.transitionOff = true; + this.calculateDialogPos(this.mdOpenFrom); + + window.setTimeout(() => { + this.dialogElement.focus(); + this.transitionOff = false; + this.active = true; + }); }, close() { if (this.$root.$el.contains(this.dialogElement)) { let cleanElement = () => { - this.dialogElement.removeEventListener(transitionEndEventName, close); + this.dialogInnerElement.removeEventListener(transitionEndEventName, cleanElement); this.$root.$el.removeChild(this.dialogElement); - this.$root.$el.removeChild(this.backdropElement); + + this.dialogTransform = ''; + this.dialogTransformOrigin = ''; }; - this.dialogElement.classList.remove('md-active'); - this.backdropElement.classList.remove('md-active'); - this.dialogElement.addEventListener(cleanElement, close); + this.dialogTransform = ''; + this.dialogTransformOrigin = ''; + this.calculateDialogPos(this.mdCloseTo); + + window.setTimeout(() => { + this.active = false; + this.dialogInnerElement.addEventListener(transitionEndEventName, cleanElement); + }); } } }, @@ -46,10 +114,12 @@ this.$nextTick(() => { this.rootElement = this.$root.$el; this.dialogElement = this.$el; - this.backdropElement = this.$refs.backdrop.$el; - this.$el.parentNode.removeChild(this.$el); - this.$el.removeChild(this.$refs.backdrop.$el); + this.dialogInnerElement = this.$refs.dialog; + this.removeDialog(); }); + }, + beforeDestroy() { + this.removeDialog(); } };