Refine modal system
This commit is contained in:
		
							parent
							
								
									e0574615a7
								
							
						
					
					
						commit
						3bc176936c
					
				@ -21,7 +21,7 @@
 | 
				
			|||||||
            <slot name="actions">
 | 
					            <slot name="actions">
 | 
				
			||||||
                <button class="btn btn-action" ref="action-info" @click="details = !details">
 | 
					                <button class="btn btn-action" ref="action-info" @click="details = !details">
 | 
				
			||||||
                    <tooltip>dodatkowe informacje</tooltip>
 | 
					                    <tooltip>dodatkowe informacje</tooltip>
 | 
				
			||||||
                    <ui-icon :icon="details ? 'info-hide' : 'info'"/>
 | 
					                    <ui-icon icon="info"/>
 | 
				
			||||||
                </button>
 | 
					                </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <button class="btn btn-action" ref="action-map" v-hover:map>
 | 
					                <button class="btn btn-action" ref="action-map" v-hover:map>
 | 
				
			||||||
@ -30,11 +30,16 @@
 | 
				
			|||||||
            </slot>
 | 
					            </slot>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <fold :visible="details" class="stop__details-fold" lazy>
 | 
					 | 
				
			||||||
        <stop-details :stop="stop"/>
 | 
					 | 
				
			||||||
    </fold>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <keep-alive>
 | 
					    <keep-alive>
 | 
				
			||||||
 | 
					        <portal to="popups">
 | 
				
			||||||
 | 
					            <ui-dialog v-if="details" @leave="details = false" behaviour="modal" class="ui-modal--medium" title="Szczegóły przystanku">
 | 
				
			||||||
 | 
					                <stop-details :stop="stop"/>
 | 
				
			||||||
 | 
					            </ui-dialog>
 | 
				
			||||||
 | 
					        </portal>
 | 
				
			||||||
 | 
					    </keep-alive>
 | 
				
			||||||
 | 
					    <keep-alive>
 | 
				
			||||||
 | 
					        <!-- FIXME: This should be in portal but it's not possible due to information loss, maybe in vue3 it will be better?-->
 | 
				
			||||||
        <ui-dialog reference="action-map" v-if="showMap" arrow class="ui-popup--no-padding" style="width: 500px;" placement="right-start" v-hover:inMap>
 | 
					        <ui-dialog reference="action-map" v-if="showMap" arrow class="ui-popup--no-padding" style="width: 500px;" placement="right-start" v-hover:inMap>
 | 
				
			||||||
            <stop-map :stop="stop" style="height: 300px"/>
 | 
					            <stop-map :stop="stop" style="height: 300px"/>
 | 
				
			||||||
        </ui-dialog>
 | 
					        </ui-dialog>
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,9 @@
 | 
				
			|||||||
                <div class="track__description">
 | 
					                <div class="track__description">
 | 
				
			||||||
                    {{ track.description }}
 | 
					                    {{ track.description }}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <span class="badge badge-pill badge-light track__order">#{{ order }}</span>
 | 
					                <span class="badge badge-pill badge-light track__order">
 | 
				
			||||||
 | 
					                    #{{ order }}
 | 
				
			||||||
 | 
					                </span>
 | 
				
			||||||
            </li>
 | 
					            </li>
 | 
				
			||||||
        </ul>
 | 
					        </ul>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,9 @@
 | 
				
			|||||||
<div class="ui-backdrop" @click="handleBackdropClick" v-if="currentBehaviour === 'modal'">
 | 
					<div class="ui-backdrop" @click="handleBackdropClick" v-if="currentBehaviour === 'modal'">
 | 
				
			||||||
    <div class="ui-modal" v-bind="$attrs">
 | 
					    <div class="ui-modal" v-bind="attrs" v-on="$listeners">
 | 
				
			||||||
        <div class="ui-modal__top-bar">
 | 
					        <div class="ui-modal__top-bar">
 | 
				
			||||||
            <div class="ui-modal__header">
 | 
					            <div class="ui-modal__header">
 | 
				
			||||||
                <slot name="header">
 | 
					                <slot name="header">
 | 
				
			||||||
                    <div class="ui-modal__title">{{ title }}</div>
 | 
					                    <div class="ui-modal__title"><slot name="title">{{ title }}</slot></div>
 | 
				
			||||||
                </slot>
 | 
					                </slot>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <button class="btn btn-action ui-modal__close" @click.prevent="handleCloseClick">
 | 
					            <button class="btn btn-action ui-modal__close" @click.prevent="handleCloseClick">
 | 
				
			||||||
@ -16,7 +16,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<div :class="[ 'ui-popup', arrow && 'ui-popup--arrow' ]" v-bind="$attrs" v-on="$listeners" v-else>
 | 
					<div :class="[ 'ui-popup', arrow && 'ui-popup--arrow' ]" v-bind="attrs" :style="{ zIndex: zIndex }" v-on="$listeners" v-else>
 | 
				
			||||||
    <div class="ui-popup__arrow" ref="arrow" v-if="arrow"></div>
 | 
					    <div class="ui-popup__arrow" ref="arrow" v-if="arrow"></div>
 | 
				
			||||||
    <div class="ui-popup__header" v-if="hasHeader">
 | 
					    <div class="ui-popup__header" v-if="hasHeader">
 | 
				
			||||||
        <slot name="header" />
 | 
					        <slot name="header" />
 | 
				
			||||||
 | 
				
			|||||||
@ -116,6 +116,10 @@ body {
 | 
				
			|||||||
  flex-direction: column;
 | 
					  flex-direction: column;
 | 
				
			||||||
  background: url("../images/background.png") repeat-x center bottom 63px;
 | 
					  background: url("../images/background.png") repeat-x center bottom 63px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.contains-modal {
 | 
				
			||||||
 | 
					    overflow-y: hidden;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  main {
 | 
					  main {
 | 
				
			||||||
    flex: 1 1 auto;
 | 
					    flex: 1 1 auto;
 | 
				
			||||||
    position: relative;
 | 
					    position: relative;
 | 
				
			||||||
 | 
				
			|||||||
@ -7,11 +7,14 @@
 | 
				
			|||||||
  align-items: center;
 | 
					  align-items: center;
 | 
				
			||||||
  overflow-y: auto;
 | 
					  overflow-y: auto;
 | 
				
			||||||
  overscroll-behavior-y: contain;
 | 
					  overscroll-behavior-y: contain;
 | 
				
			||||||
 | 
					  z-index: 10000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &::after {
 | 
					  &::after {
 | 
				
			||||||
    height: 1rem;
 | 
					    height: $spacer;
 | 
				
			||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
    content: "";
 | 
					    content: "";
 | 
				
			||||||
 | 
					    width: 1px;
 | 
				
			||||||
 | 
					    flex: 0 0 auto;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -31,7 +34,7 @@ $dialog-sizes: (
 | 
				
			|||||||
  border-radius: 1px;
 | 
					  border-radius: 1px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @each $size, $width in $dialog-sizes {
 | 
					  @each $size, $width in $dialog-sizes {
 | 
				
			||||||
    .ui-modal--#{$size} {
 | 
					    &.ui-modal--#{$size} {
 | 
				
			||||||
      width: $width;
 | 
					      width: $width;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -56,3 +59,11 @@ $dialog-sizes: (
 | 
				
			|||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  margin-bottom: $dialog-margin * 0.75;
 | 
					  margin-bottom: $dialog-margin * 0.75;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@include media-breakpoint-down('sm') {
 | 
				
			||||||
 | 
					  @each $size, $width in $dialog-sizes {
 | 
				
			||||||
 | 
					    .ui-modal.ui-modal--#{$size} {
 | 
				
			||||||
 | 
					      width: 100%;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -10,9 +10,31 @@ import { defaultBreakpoints } from "../../filters";
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export type DialogBehaviour = "modal" | "popup";
 | 
					export type DialogBehaviour = "modal" | "popup";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let openModalCounter: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function computeZIndexOfElement(element: HTMLElement): number {
 | 
				
			||||||
 | 
					    let current = element;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (true) {
 | 
				
			||||||
 | 
					        const zIndex = window.getComputedStyle(current).zIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (zIndex !== "auto") {
 | 
				
			||||||
 | 
					            return parseInt(zIndex);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!current.parentElement) {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        current = current.parentElement;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
    template: require('../../../components/ui/dialog.html'),
 | 
					 | 
				
			||||||
    inheritAttrs: false,
 | 
					    inheritAttrs: false,
 | 
				
			||||||
 | 
					    template: require('../../../components/ui/dialog.html'),
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export default class UiDialog extends Vue {
 | 
					export default class UiDialog extends Vue {
 | 
				
			||||||
    @Prop({ type: String, default: "popup" })
 | 
					    @Prop({ type: String, default: "popup" })
 | 
				
			||||||
@ -41,11 +63,23 @@ export default class UiDialog extends Vue {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private isMobile: boolean = false;
 | 
					    private isMobile: boolean = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Inherited class hack */
 | 
				
			||||||
 | 
					    private staticClass: string[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private zIndex: number = 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private _focusOutEvent;
 | 
					    private _focusOutEvent;
 | 
				
			||||||
    private _resizeEvent;
 | 
					    private _resizeEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private _popper;
 | 
					    private _popper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get attrs() {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            ...this.$attrs,
 | 
				
			||||||
 | 
					            "class": this.staticClass
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get currentBehaviour(): DialogBehaviour {
 | 
					    get currentBehaviour(): DialogBehaviour {
 | 
				
			||||||
        if (!this.mobileBehaviour) {
 | 
					        if (!this.mobileBehaviour) {
 | 
				
			||||||
            return this.behaviour;
 | 
					            return this.behaviour;
 | 
				
			||||||
@ -93,16 +127,60 @@ export default class UiDialog extends Vue {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mounted() {
 | 
					    mounted() {
 | 
				
			||||||
 | 
					        this.zIndex = computeZIndexOfElement(this.getReferenceElement()) + 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.handleWindowResize();
 | 
					        this.handleWindowResize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.behaviour === 'popup') {
 | 
					        if (this.behaviour === 'popup') {
 | 
				
			||||||
            this.initPopper();
 | 
					            this.mountPopper();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.staticClass = Array.from(this.$el.classList).filter(cls => ["ui-backdrop", "ui-popup", "ui-popup--arrow"].indexOf(cls) === -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        window.addEventListener('resize', this._resizeEvent = this.handleWindowResize.bind(this));
 | 
					        window.addEventListener('resize', this._resizeEvent = this.handleWindowResize.bind(this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this._activated();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private initPopper() {
 | 
					    private _activated() {
 | 
				
			||||||
 | 
					        if (this.behaviour === 'modal') {
 | 
				
			||||||
 | 
					            this.mountModal();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private _deactivated() {
 | 
				
			||||||
 | 
					        if (this.behaviour === 'modal') {
 | 
				
			||||||
 | 
					            this.dismountModal();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private mountModal() {
 | 
				
			||||||
 | 
					        if (openModalCounter === 0) {
 | 
				
			||||||
 | 
					            document.body.style.paddingRight = `${window.screen.width - document.body.clientWidth}px`
 | 
				
			||||||
 | 
					            document.body.classList.add('contains-modal');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        openModalCounter++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private dismountModal() {
 | 
				
			||||||
 | 
					        openModalCounter--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (openModalCounter === 0) {
 | 
				
			||||||
 | 
					            document.body.style.paddingRight = "";
 | 
				
			||||||
 | 
					            document.body.classList.remove('contains-modal');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    activated() {
 | 
				
			||||||
 | 
					        this._activated();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    deactivated() {
 | 
				
			||||||
 | 
					        this._deactivated();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private mountPopper() {
 | 
				
			||||||
        const reference = this.getReferenceElement();
 | 
					        const reference = this.getReferenceElement();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this._popper = new Popper(reference, this.$el, {
 | 
					        this._popper = new Popper(reference, this.$el, {
 | 
				
			||||||
@ -147,6 +225,8 @@ export default class UiDialog extends Vue {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    beforeDestroy() {
 | 
					    beforeDestroy() {
 | 
				
			||||||
        this._focusOutEvent && document.removeEventListener('click', this._focusOutEvent, { capture: true });
 | 
					        this._focusOutEvent && document.removeEventListener('click', this._focusOutEvent, { capture: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this._deactivated()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    removed() {
 | 
					    removed() {
 | 
				
			||||||
@ -179,7 +259,15 @@ export default class UiDialog extends Vue {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (newBehaviour === 'popup') {
 | 
					        if (newBehaviour === 'popup') {
 | 
				
			||||||
            this.$nextTick(() => this.initPopper());
 | 
					            this.$nextTick(() => this.mountPopper());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (newBehaviour === 'modal') {
 | 
				
			||||||
 | 
					            this.mountModal();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (oldBehaviour === 'modal') {
 | 
				
			||||||
 | 
					            this.dismountModal();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -105,11 +105,9 @@
 | 
				
			|||||||
                        </button>
 | 
					                        </button>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <portal to="popups">
 | 
					                    <ui-dialog reference="save" v-if="visibility.save" arrow placement="bottom-end" @leave="visibility.save = false">
 | 
				
			||||||
                        <ui-dialog reference="settings-messages" v-if="visibility.messages" arrow placement="left-start" @leave="visibility.messages = false">
 | 
					 | 
				
			||||||
                        <favourites-adder @saved="visibility.save = false"/>
 | 
					                        <favourites-adder @saved="visibility.save = false"/>
 | 
				
			||||||
                    </ui-dialog>
 | 
					                    </ui-dialog>
 | 
				
			||||||
                    </portal>
 | 
					 | 
				
			||||||
                </section>
 | 
					                </section>
 | 
				
			||||||
                <section class="section picker">
 | 
					                <section class="section picker">
 | 
				
			||||||
                    <header class="section__title flex">
 | 
					                    <header class="section__title flex">
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user