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'}} {{#if type === 'gifv'}}
<AutoplayVideo <AutoplayVideo
ariaLabel="Animated GIF: {{description || ''}}" ariaLabel="Animated GIF: {{description || ''}}"
@ -17,7 +22,7 @@
{{/if}} {{/if}}
</ModalDialog> </ModalDialog>
<style> <style>
:global(#modal-dialog img, #modal-dialog video) { :global(.image-modal-dialog img, .image-modal-dialog video) {
object-fit: contain; object-fit: contain;
max-width: calc(100vw - 20px); max-width: calc(100vw - 20px);
max-height: calc(100% - 20px); max-height: calc(100% - 20px);

View file

@ -1,8 +1,8 @@
<div class="modal-dialog-backdrop {{fadedIn ? '' : 'hidden'}}" <div class="{{backdropClass}}"
tabindex="-1" tabindex="-1"
data-a11y-dialog-hide data-a11y-dialog-hide
></div> ></div>
<div class="modal-dialog-contents {{fadedIn ? '' : 'hidden'}} {{muted ? 'muted-style' : ''}}" <div class="{{contentsClass}}"
role="dialog" role="dialog"
aria-label="{{label || ''}}" aria-label="{{label || ''}}"
ref:node ref:node
@ -25,7 +25,7 @@
</div> </div>
</div> </div>
<style> <style>
:global(#modal-dialog[aria-hidden='true']) { :global(.modal-dialog[aria-hidden='true']) {
display: none; display: none;
} }
.modal-dialog-backdrop { .modal-dialog-backdrop {
@ -36,6 +36,8 @@
bottom: 0; bottom: 0;
top: 0; top: 0;
background: rgba(51, 51, 51, 0.9); background: rgba(51, 51, 51, 0.9);
}
.modal-dialog-backdrop.should-animate {
transition: opacity 0.2s linear; transition: opacity 0.2s linear;
} }
.modal-dialog-contents { .modal-dialog-contents {
@ -51,6 +53,8 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
max-height: calc(100% - 20px); max-height: calc(100% - 20px);
}
.modal-dialog-contents.should-animate {
transition: opacity 0.2s linear; transition: opacity 0.2s linear;
} }
@ -113,7 +117,31 @@
<script> <script>
import A11yDialog from 'a11y-dialog' import A11yDialog from 'a11y-dialog'
import { classname } from '../../_utils/classname'
export default { 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() { oncreate() {
let dialogElement = this.refs.node.parentElement let dialogElement = this.refs.node.parentElement
let a11yDialog = new A11yDialog(dialogElement) let a11yDialog = new A11yDialog(dialogElement)
@ -121,6 +149,7 @@
a11yDialog.destroy() a11yDialog.destroy()
this.fire('close') this.fire('close')
this.destroy() this.destroy()
document.body.removeChild(dialogElement)
}) })
this.observe('shown', shown => { this.observe('shown', shown => {
if (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}}" <video poster="{{poster}}"
src="{{src}}" src="{{src}}"
width="{{width}}" width="{{width}}"
@ -8,7 +13,7 @@
/> />
</ModalDialog> </ModalDialog>
<style> <style>
:global(#modal-dialog video) { :global(.video-modal-dialog video) {
object-fit: contain; object-fit: contain;
max-width: calc(100vw - 20px); max-width: calc(100vw - 20px);
max-height: calc(100% - 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 ComposeDialog from './ComposeDialog.html'
import { createDialogElement } from './createDialogElement'
export function showComposeDialog () { export function showComposeDialog () {
let dialog = new ComposeDialog({ let dialog = new ComposeDialog({
target: document.getElementById('modal-dialog'), target: createDialogElement(),
data: { data: {
label: 'Compose dialog' label: 'Compose dialog'
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,8 +1,9 @@
import VideoDialog from './VideoDialog.html' import VideoDialog from './VideoDialog.html'
import { createDialogElement } from './createDialogElement'
export function showVideoDialog (poster, src, width, height, description) { export function showVideoDialog (poster, src, width, height, description) {
let videoDialog = new VideoDialog({ let videoDialog = new VideoDialog({
target: document.getElementById('modal-dialog'), target: createDialogElement(),
data: { data: {
label: 'Video dialog', label: 'Video dialog',
poster, 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 --> <!-- Toast.html gets rendered here -->
<div id="toast"></div> <div id="toast"></div>
<!-- ModalDialog.html gets rendered here -->
<div id="modal-dialog" aria-hidden="true"></div>
<!-- LoadingMask.html gets rendered here --> <!-- LoadingMask.html gets rendered here -->
<div id="loading-mask" aria-hidden="true"></div> <div id="loading-mask" aria-hidden="true"></div>