forked from AkkomaGang/akkoma-fe
Merge branch 'modal-scroll-lock' into 'develop'
Lock body scroll when modal is open globally See merge request pleroma/pleroma-fe!974
This commit is contained in:
commit
cd95618520
9 changed files with 106 additions and 83 deletions
25
src/App.scss
25
src/App.scss
|
@ -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 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import StillImage from '../still-image/still-image.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'
|
||||
|
||||
const MediaModal = {
|
||||
components: {
|
||||
StillImage,
|
||||
VideoAttachment
|
||||
VideoAttachment,
|
||||
Modal
|
||||
},
|
||||
computed: {
|
||||
showing () {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<template>
|
||||
<div
|
||||
<Modal
|
||||
v-if="showing"
|
||||
v-body-scroll-lock="showing"
|
||||
class="modal-view media-modal-view"
|
||||
@click.prevent="hide"
|
||||
class="media-modal-view"
|
||||
@backdropClicked="hide"
|
||||
>
|
||||
<img
|
||||
v-if="type === 'image'"
|
||||
|
@ -33,21 +32,15 @@
|
|||
>
|
||||
<i class="icon-right-open arrow-icon" />
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script src="./media_modal.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
|
||||
.media-modal-view {
|
||||
.modal-view.media-modal-view {
|
||||
z-index: 1001;
|
||||
|
||||
body:not(.scroll-locked) & {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.modal-view-button-arrow {
|
||||
opacity: 0.75;
|
||||
|
@ -114,5 +107,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
52
src/components/modal/modal.vue
Normal file
52
src/components/modal/modal.vue
Normal file
|
@ -0,0 +1,52 @@
|
|||
<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>
|
|
@ -1,9 +1,11 @@
|
|||
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
||||
import Modal from '../modal/modal.vue'
|
||||
import get from 'lodash/get'
|
||||
|
||||
const PostStatusModal = {
|
||||
components: {
|
||||
PostStatusForm
|
||||
PostStatusForm,
|
||||
Modal
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
<template>
|
||||
<div
|
||||
<Modal
|
||||
v-if="isLoggedIn && !resettingForm"
|
||||
v-show="modalActivated"
|
||||
class="post-form-modal-view modal-view"
|
||||
@click="closeModal"
|
||||
>
|
||||
<div
|
||||
class="post-form-modal-panel panel"
|
||||
@click.stop=""
|
||||
:is-open="modalActivated"
|
||||
class="post-form-modal-view"
|
||||
@backdropClicked="closeModal"
|
||||
>
|
||||
<div class="post-form-modal-panel panel">
|
||||
<div class="panel-heading">
|
||||
{{ $t('post_status.new_status') }}
|
||||
</div>
|
||||
|
@ -18,15 +15,13 @@
|
|||
@posted="closeModal"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script src="./post_status_modal.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
|
||||
.post-form-modal-view {
|
||||
.modal-view.post-form-modal-view {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
import Status from '../status/status.vue'
|
||||
import List from '../list/list.vue'
|
||||
import Checkbox from '../checkbox/checkbox.vue'
|
||||
import Modal from '../modal/modal.vue'
|
||||
|
||||
const UserReportingModal = {
|
||||
components: {
|
||||
Status,
|
||||
List,
|
||||
Checkbox
|
||||
Checkbox,
|
||||
Modal
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
<template>
|
||||
<div
|
||||
<Modal
|
||||
v-if="isOpen"
|
||||
class="modal-view"
|
||||
@click="closeModal"
|
||||
>
|
||||
<div
|
||||
class="user-reporting-panel panel"
|
||||
@click.stop=""
|
||||
@backdropClicked="closeModal"
|
||||
>
|
||||
<div class="user-reporting-panel panel">
|
||||
<div class="panel-heading">
|
||||
<div class="title">
|
||||
{{ $t('user_reporting.title', [user.screen_name]) }}
|
||||
|
@ -69,7 +65,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script src="./user_reporting_modal.js"></script>
|
||||
|
|
|
@ -2,13 +2,16 @@ import * as bodyScrollLock from 'body-scroll-lock'
|
|||
|
||||
let previousNavPaddingRight
|
||||
let previousAppBgWrapperRight
|
||||
const lockerEls = new Set([])
|
||||
|
||||
const disableBodyScroll = (el) => {
|
||||
const scrollBarGap = window.innerWidth - document.documentElement.clientWidth
|
||||
bodyScrollLock.disableBodyScroll(el, {
|
||||
reserveScrollBarGap: true
|
||||
})
|
||||
lockerEls.add(el)
|
||||
setTimeout(() => {
|
||||
if (lockerEls.size <= 1) {
|
||||
// If previousNavPaddingRight is already set, don't set it again.
|
||||
if (previousNavPaddingRight === undefined) {
|
||||
const navEl = document.getElementById('nav')
|
||||
|
@ -22,11 +25,14 @@ const disableBodyScroll = (el) => {
|
|||
appBgWrapperEl.style.right = previousAppBgWrapperRight ? `calc(${previousAppBgWrapperRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
||||
}
|
||||
document.body.classList.add('scroll-locked')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const enableBodyScroll = (el) => {
|
||||
lockerEls.delete(el)
|
||||
setTimeout(() => {
|
||||
if (lockerEls.size === 0) {
|
||||
if (previousNavPaddingRight !== undefined) {
|
||||
document.getElementById('nav').style.paddingRight = previousNavPaddingRight
|
||||
// Restore previousNavPaddingRight to undefined so disableBodyScroll knows it can be set again.
|
||||
|
@ -38,6 +44,7 @@ const enableBodyScroll = (el) => {
|
|||
previousAppBgWrapperRight = undefined
|
||||
}
|
||||
document.body.classList.remove('scroll-locked')
|
||||
}
|
||||
})
|
||||
bodyScrollLock.enableBodyScroll(el)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue