Commit cd956185 authored by HJ's avatar HJ 🐼

Merge branch 'modal-scroll-lock' into 'develop'

Lock body scroll when modal is open globally

See merge request pleroma/pleroma-fe!974
parents 051e6ea5 eb695fd6
Pipeline #18988 passed with stages
in 5 minutes and 11 seconds
...@@ -705,31 +705,6 @@ nav { ...@@ -705,31 +705,6 @@ nav {
} }
} }
@keyframes modal-background-fadein {
from {
background-color: rgba(0, 0, 0, 0);
}
to {
background-color: rgba(0, 0, 0, 0.5);
}
}
.modal-view {
z-index: 1000;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
overflow: auto;
animation-duration: 0.2s;
background-color: rgba(0, 0, 0, 0.5);
animation-name: modal-background-fadein;
}
.button-icon { .button-icon {
font-size: 1.2em; font-size: 1.2em;
} }
......
import StillImage from '../still-image/still-image.vue' import StillImage from '../still-image/still-image.vue'
import VideoAttachment from '../video_attachment/video_attachment.vue' import VideoAttachment from '../video_attachment/video_attachment.vue'
import Modal from '../modal/modal.vue'
import fileTypeService from '../../services/file_type/file_type.service.js' import fileTypeService from '../../services/file_type/file_type.service.js'
const MediaModal = { const MediaModal = {
components: { components: {
StillImage, StillImage,
VideoAttachment VideoAttachment,
Modal
}, },
computed: { computed: {
showing () { showing () {
......
<template> <template>
<div <Modal
v-if="showing" v-if="showing"
v-body-scroll-lock="showing" class="media-modal-view"
class="modal-view media-modal-view" @backdropClicked="hide"
@click.prevent="hide"
> >
<img <img
v-if="type === 'image'" v-if="type === 'image'"
...@@ -33,21 +32,15 @@ ...@@ -33,21 +32,15 @@
> >
<i class="icon-right-open arrow-icon" /> <i class="icon-right-open arrow-icon" />
</button> </button>
</div> </Modal>
</template> </template>
<script src="./media_modal.js"></script> <script src="./media_modal.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; .modal-view.media-modal-view {
.media-modal-view {
z-index: 1001; z-index: 1001;
body:not(.scroll-locked) & {
display: none;
}
&:hover { &:hover {
.modal-view-button-arrow { .modal-view-button-arrow {
opacity: 0.75; opacity: 0.75;
...@@ -114,5 +107,4 @@ ...@@ -114,5 +107,4 @@
} }
} }
} }
</style> </style>
<template>
<div
v-show="isOpen"
v-body-scroll-lock="isOpen"
class="modal-view"
@click.self="$emit('backdropClicked')"
>
<slot />
</div>
</template>
<script>
export default {
props: {
isOpen: {
type: Boolean,
default: true
}
}
}
</script>
<style lang="scss">
.modal-view {
z-index: 1000;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
overflow: auto;
animation-duration: 0.2s;
background-color: rgba(0, 0, 0, 0.5);
animation-name: modal-background-fadein;
body:not(.scroll-locked) & {
opacity: 0;
}
}
@keyframes modal-background-fadein {
from {
background-color: rgba(0, 0, 0, 0);
}
to {
background-color: rgba(0, 0, 0, 0.5);
}
}
</style>
import PostStatusForm from '../post_status_form/post_status_form.vue' import PostStatusForm from '../post_status_form/post_status_form.vue'
import Modal from '../modal/modal.vue'
import get from 'lodash/get' import get from 'lodash/get'
const PostStatusModal = { const PostStatusModal = {
components: { components: {
PostStatusForm PostStatusForm,
Modal
}, },
data () { data () {
return { return {
......
<template> <template>
<div <Modal
v-if="isLoggedIn && !resettingForm" v-if="isLoggedIn && !resettingForm"
v-show="modalActivated" :is-open="modalActivated"
class="post-form-modal-view modal-view" class="post-form-modal-view"
@click="closeModal" @backdropClicked="closeModal"
> >
<div <div class="post-form-modal-panel panel">
class="post-form-modal-panel panel"
@click.stop=""
>
<div class="panel-heading"> <div class="panel-heading">
{{ $t('post_status.new_status') }} {{ $t('post_status.new_status') }}
</div> </div>
...@@ -18,15 +15,13 @@ ...@@ -18,15 +15,13 @@
@posted="closeModal" @posted="closeModal"
/> />
</div> </div>
</div> </Modal>
</template> </template>
<script src="./post_status_modal.js"></script> <script src="./post_status_modal.js"></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; .modal-view.post-form-modal-view {
.post-form-modal-view {
align-items: flex-start; align-items: flex-start;
} }
......
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
import Status from '../status/status.vue' import Status from '../status/status.vue'
import List from '../list/list.vue' import List from '../list/list.vue'
import Checkbox from '../checkbox/checkbox.vue' import Checkbox from '../checkbox/checkbox.vue'
import Modal from '../modal/modal.vue'
const UserReportingModal = { const UserReportingModal = {
components: { components: {
Status, Status,
List, List,
Checkbox Checkbox,
Modal
}, },
data () { data () {
return { return {
......
<template> <template>
<div <Modal
v-if="isOpen" v-if="isOpen"
class="modal-view" @backdropClicked="closeModal"
@click="closeModal"
> >
<div <div class="user-reporting-panel panel">
class="user-reporting-panel panel"
@click.stop=""
>
<div class="panel-heading"> <div class="panel-heading">
<div class="title"> <div class="title">
{{ $t('user_reporting.title', [user.screen_name]) }} {{ $t('user_reporting.title', [user.screen_name]) }}
...@@ -69,7 +65,7 @@ ...@@ -69,7 +65,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> </Modal>
</template> </template>
<script src="./user_reporting_modal.js"></script> <script src="./user_reporting_modal.js"></script>
......
...@@ -2,42 +2,49 @@ import * as bodyScrollLock from 'body-scroll-lock' ...@@ -2,42 +2,49 @@ import * as bodyScrollLock from 'body-scroll-lock'
let previousNavPaddingRight let previousNavPaddingRight
let previousAppBgWrapperRight let previousAppBgWrapperRight
const lockerEls = new Set([])
const disableBodyScroll = (el) => { const disableBodyScroll = (el) => {
const scrollBarGap = window.innerWidth - document.documentElement.clientWidth const scrollBarGap = window.innerWidth - document.documentElement.clientWidth
bodyScrollLock.disableBodyScroll(el, { bodyScrollLock.disableBodyScroll(el, {
reserveScrollBarGap: true reserveScrollBarGap: true
}) })
lockerEls.add(el)
setTimeout(() => { setTimeout(() => {
// If previousNavPaddingRight is already set, don't set it again. if (lockerEls.size <= 1) {
if (previousNavPaddingRight === undefined) { // If previousNavPaddingRight is already set, don't set it again.
const navEl = document.getElementById('nav') if (previousNavPaddingRight === undefined) {
previousNavPaddingRight = window.getComputedStyle(navEl).getPropertyValue('padding-right') const navEl = document.getElementById('nav')
navEl.style.paddingRight = previousNavPaddingRight ? `calc(${previousNavPaddingRight} + ${scrollBarGap}px)` : `${scrollBarGap}px` previousNavPaddingRight = window.getComputedStyle(navEl).getPropertyValue('padding-right')
navEl.style.paddingRight = previousNavPaddingRight ? `calc(${previousNavPaddingRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
}
// If previousAppBgWrapeprRight is already set, don't set it again.
if (previousAppBgWrapperRight === undefined) {
const appBgWrapperEl = document.getElementById('app_bg_wrapper')
previousAppBgWrapperRight = window.getComputedStyle(appBgWrapperEl).getPropertyValue('right')
appBgWrapperEl.style.right = previousAppBgWrapperRight ? `calc(${previousAppBgWrapperRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
}
document.body.classList.add('scroll-locked')
} }
// If previousAppBgWrapeprRight is already set, don't set it again.
if (previousAppBgWrapperRight === undefined) {
const appBgWrapperEl = document.getElementById('app_bg_wrapper')
previousAppBgWrapperRight = window.getComputedStyle(appBgWrapperEl).getPropertyValue('right')
appBgWrapperEl.style.right = previousAppBgWrapperRight ? `calc(${previousAppBgWrapperRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
}
document.body.classList.add('scroll-locked')
}) })
} }
const enableBodyScroll = (el) => { const enableBodyScroll = (el) => {
lockerEls.delete(el)
setTimeout(() => { setTimeout(() => {
if (previousNavPaddingRight !== undefined) { if (lockerEls.size === 0) {
document.getElementById('nav').style.paddingRight = previousNavPaddingRight if (previousNavPaddingRight !== undefined) {
// Restore previousNavPaddingRight to undefined so disableBodyScroll knows it can be set again. document.getElementById('nav').style.paddingRight = previousNavPaddingRight
previousNavPaddingRight = undefined // Restore previousNavPaddingRight to undefined so disableBodyScroll knows it can be set again.
} previousNavPaddingRight = undefined
if (previousAppBgWrapperRight !== undefined) { }
document.getElementById('app_bg_wrapper').style.right = previousAppBgWrapperRight if (previousAppBgWrapperRight !== undefined) {
// Restore previousAppBgWrapperRight to undefined so disableBodyScroll knows it can be set again. document.getElementById('app_bg_wrapper').style.right = previousAppBgWrapperRight
previousAppBgWrapperRight = undefined // Restore previousAppBgWrapperRight to undefined so disableBodyScroll knows it can be set again.
previousAppBgWrapperRight = undefined
}
document.body.classList.remove('scroll-locked')
} }
document.body.classList.remove('scroll-locked')
}) })
bodyScrollLock.enableBodyScroll(el) bodyScrollLock.enableBodyScroll(el)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment