fix having multiple modal dialogs

This commit is contained in:
Nolan Lawson 2018-03-31 18:46:44 -07:00
parent 125dd6ab75
commit 80a89a64f1
12 changed files with 67 additions and 17 deletions

View file

@ -1,4 +1,9 @@
<ModalDialog :label :shown background="var(--muted-modal-bg)" muted="true">
<ModalDialog :label
:shown
background="var(--muted-modal-bg)"
muted="true"
className="image-modal-dialog"
>
{{#if type === 'gifv'}}
<AutoplayVideo
ariaLabel="Animated GIF: {{description || ''}}"
@ -17,7 +22,7 @@
{{/if}}
</ModalDialog>
<style>
:global(#modal-dialog img, #modal-dialog video) {
:global(.image-modal-dialog img, .image-modal-dialog video) {
object-fit: contain;
max-width: calc(100vw - 20px);
max-height: calc(100% - 20px);

View file

@ -1,8 +1,8 @@
<div class="modal-dialog-backdrop {{fadedIn ? '' : 'hidden'}}"
<div class="{{backdropClass}}"
tabindex="-1"
data-a11y-dialog-hide
></div>
<div class="modal-dialog-contents {{fadedIn ? '' : 'hidden'}} {{muted ? 'muted-style' : ''}}"
<div class="{{contentsClass}}"
role="dialog"
aria-label="{{label || ''}}"
ref:node
@ -25,7 +25,7 @@
</div>
</div>
<style>
:global(#modal-dialog[aria-hidden='true']) {
:global(.modal-dialog[aria-hidden='true']) {
display: none;
}
.modal-dialog-backdrop {
@ -36,6 +36,8 @@
bottom: 0;
top: 0;
background: rgba(51, 51, 51, 0.9);
}
.modal-dialog-backdrop.should-animate {
transition: opacity 0.2s linear;
}
.modal-dialog-contents {
@ -51,6 +53,8 @@
display: flex;
flex-direction: row;
max-height: calc(100% - 20px);
}
.modal-dialog-contents.should-animate {
transition: opacity 0.2s linear;
}
@ -113,7 +117,31 @@
<script>
import A11yDialog from 'a11y-dialog'
import { classname } from '../../_utils/classname'
export default {
data: () => ({
// don't animate if we're showing a modal dialog on top of another modal dialog. it looks ugly
shouldAnimate: !process.browser || document.getElementsByClassName('modal-dialog').length < 2
}),
computed: {
backdropClass: (fadedIn, shouldAnimate) => {
return classname(
'modal-dialog-backdrop',
!fadedIn && 'hidden',
shouldAnimate && 'should-animate'
)
},
contentsClass: (fadedIn, muted, shouldAnimate, className) => {
return classname(
'modal-dialog-contents',
!fadedIn && 'hidden',
muted && 'muted-style',
shouldAnimate && 'should-animate',
className
)
}
},
oncreate() {
let dialogElement = this.refs.node.parentElement
let a11yDialog = new A11yDialog(dialogElement)
@ -121,6 +149,7 @@
a11yDialog.destroy()
this.fire('close')
this.destroy()
document.body.removeChild(dialogElement)
})
this.observe('shown', shown => {
if (shown) {

View file

@ -1,4 +1,9 @@
<ModalDialog :label :shown background="var(--muted-modal-bg)" muted="true">
<ModalDialog :label
:shown
background="var(--muted-modal-bg)"
muted="true"
className="video-modal-dialog"
>
<video poster="{{poster}}"
src="{{src}}"
width="{{width}}"
@ -8,7 +13,7 @@
/>
</ModalDialog>
<style>
:global(#modal-dialog video) {
:global(.video-modal-dialog video) {
object-fit: contain;
max-width: calc(100vw - 20px);
max-height: calc(100% - 20px);

View file

@ -0,0 +1,7 @@
export function createDialogElement () {
let div = document.createElement('div')
div.setAttribute('class', 'modal-dialog')
div.setAttribute('aria-hidden', 'true')
document.body.appendChild(div)
return div
}

View file

@ -1,8 +1,9 @@
import ComposeDialog from './ComposeDialog.html'
import { createDialogElement } from './createDialogElement'
export function showComposeDialog () {
let dialog = new ComposeDialog({
target: document.getElementById('modal-dialog'),
target: createDialogElement(),
data: {
label: 'Compose dialog'
}

View file

@ -1,8 +1,9 @@
import ConfirmationDialog from './ConfirmationDialog.html'
import { createDialogElement } from './createDialogElement'
export function showConfirmationDialog (options) {
let dialog = new ConfirmationDialog({
target: document.getElementById('modal-dialog'),
target: createDialogElement(),
data: Object.assign({
label: 'Confirmation dialog'
}, options)

View file

@ -1,8 +1,9 @@
import EmojiDialog from './EmojiDialog.html'
import { createDialogElement } from './createDialogElement'
export function showEmojiDialog (realm) {
let emojiDialog = new EmojiDialog({
target: document.getElementById('modal-dialog'),
target: createDialogElement(),
data: {
label: 'Emoji dialog',
title: 'Custom emoji',

View file

@ -1,8 +1,9 @@
import ImageDialog from './ImageDialog.html'
import { createDialogElement } from './createDialogElement'
export function showImageDialog (poster, src, type, width, height, description) {
let imageDialog = new ImageDialog({
target: document.getElementById('modal-dialog'),
target: createDialogElement(),
data: {
label: 'Image dialog',
poster,

View file

@ -1,8 +1,9 @@
import PostPrivacyDialog from './PostPrivacyDialog.html'
import { createDialogElement } from './createDialogElement'
export function showPostPrivacyDialog (realm) {
let dialog = new PostPrivacyDialog({
target: document.getElementById('modal-dialog'),
target: createDialogElement(),
data: {
label: 'Post privacy dialog',
title: 'Post privacy',

View file

@ -1,8 +1,9 @@
import StatusOptionsDialog from './StatusOptionsDialog.html'
import { createDialogElement } from './createDialogElement'
export function showStatusOptionsDialog (statusId) {
let dialog = new StatusOptionsDialog({
target: document.getElementById('modal-dialog'),
target: createDialogElement(),
data: {
label: 'Status options dialog',
title: 'Status options',

View file

@ -1,8 +1,9 @@
import VideoDialog from './VideoDialog.html'
import { createDialogElement } from './createDialogElement'
export function showVideoDialog (poster, src, width, height, description) {
let videoDialog = new VideoDialog({
target: document.getElementById('modal-dialog'),
target: createDialogElement(),
data: {
label: 'Video dialog',
poster,

View file

@ -120,9 +120,6 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
<!-- Toast.html gets rendered here -->
<div id="toast"></div>
<!-- ModalDialog.html gets rendered here -->
<div id="modal-dialog" aria-hidden="true"></div>
<!-- LoadingMask.html gets rendered here -->
<div id="loading-mask" aria-hidden="true"></div>