add floating compose button

This commit is contained in:
Nolan Lawson 2018-03-27 00:02:55 -07:00
parent 62c82a05c0
commit 58b700788c
11 changed files with 195 additions and 49 deletions

View File

@ -31,5 +31,6 @@ module.exports = [
{id: 'fa-exclamation-triangle', src: 'node_modules/font-awesome-svg-png/white/svg/exclamation-triangle.svg', title: 'Content warning'}, {id: 'fa-exclamation-triangle', src: 'node_modules/font-awesome-svg-png/white/svg/exclamation-triangle.svg', title: 'Content warning'},
{id: 'fa-check', src: 'node_modules/font-awesome-svg-png/white/svg/check.svg', title: 'Check'}, {id: 'fa-check', src: 'node_modules/font-awesome-svg-png/white/svg/check.svg', title: 'Check'},
{id: 'fa-trash', src: 'node_modules/font-awesome-svg-png/white/svg/trash-o.svg', title: 'Delete'}, {id: 'fa-trash', src: 'node_modules/font-awesome-svg-png/white/svg/trash-o.svg', title: 'Delete'},
{id: 'fa-hourglass', src: 'node_modules/font-awesome-svg-png/white/svg/hourglass.svg', title: 'Follow requested'} {id: 'fa-hourglass', src: 'node_modules/font-awesome-svg-png/white/svg/hourglass.svg', title: 'Follow requested'},
{id: 'fa-pencil', src: 'node_modules/font-awesome-svg-png/white/svg/pencil.svg', title: 'Compose'}
] ]

View File

@ -1,4 +1,4 @@
<div class="compose-box {{overLimit ? 'over-char-limit' : ''}}"> <div class="compose-box {{overLimit ? 'over-char-limit' : ''}} {{realm === 'dialog' ? 'dialog-size' : '' }}">
<ComposeAuthor /> <ComposeAuthor />
{{#if contentWarningShown}} {{#if contentWarningShown}}
<div class="compose-content-warning-wrapper" <div class="compose-content-warning-wrapper"
@ -11,12 +11,16 @@
<ComposeToolbar :realm :postPrivacy :media :contentWarningShown :text /> <ComposeToolbar :realm :postPrivacy :media :contentWarningShown :text />
<ComposeLengthIndicator :length :overLimit /> <ComposeLengthIndicator :length :overLimit />
<ComposeMedia :realm :media /> <ComposeMedia :realm :media />
<ComposeButton :length :overLimit on:click="onClickPostButton()" />
</div> </div>
<div class="compose-box-button-sentinel" ref:sentinel></div>
<div class="compose-box-button-wrapper" >
<ComposeButton :length :overLimit :sticky on:click="onClickPostButton()" />
</div>
<div class="compose-box-border-bottom"></div>
<style> <style>
.compose-box { .compose-box {
border-radius: 4px; border-radius: 4px;
padding: 20px; padding: 20px 20px 0 20px;
display: grid; display: grid;
align-items: flex-start; align-items: flex-start;
grid-template-areas: grid-template-areas:
@ -25,24 +29,50 @@
"avatar input input input" "avatar input input input"
"avatar gauge gauge gauge" "avatar gauge gauge gauge"
"avatar toolbar toolbar length" "avatar toolbar toolbar length"
"avatar media media media" "avatar media media media";
"avatar button button button";
grid-template-columns: min-content minmax(0, max-content) 1fr 1fr; grid-template-columns: min-content minmax(0, max-content) 1fr 1fr;
border-bottom: 1px solid var(--main-border);
width: 560px; width: 560px;
max-width: calc(100vw - 40px); max-width: calc(100vw - 40px);
} }
.compose-box.dialog-size {
width: 540px;
max-width: calc(100vw - 80px);
}
.compose-box-border-bottom {
height: 1px;
background: var(--main-border);
width: 100%;
}
.compose-box-button-wrapper {
width: 100%;
display: flex;
justify-content: flex-end;
position: -webkit-sticky;
position: sticky;
top: 10px;
z-index: 10;
}
.compose-content-warning-wrapper { .compose-content-warning-wrapper {
grid-area: cw; grid-area: cw;
} }
@media (max-width: 767px) { @media (max-width: 767px) {
.compose-box { .compose-box {
padding: 10px 10px; padding: 10px 10px 0 10px;
max-width: calc(100vw - 20px); max-width: calc(100vw - 20px);
width: 580px; width: 580px;
} }
.compose-box.dialog-size {
width: 560px;
max-width: calc(100vw - 40px);
}
.compose-box-button-wrapper {
top: 5px;
}
} }
</style> </style>
<script> <script>
@ -59,20 +89,35 @@
import { store } from '../../_store/store' import { store } from '../../_store/store'
import { slide } from 'svelte-transitions' import { slide } from 'svelte-transitions'
import { postStatus, insertHandleForReply } from '../../_actions/compose' import { postStatus, insertHandleForReply } from '../../_actions/compose'
import { importDialogs } from '../../_utils/asyncModules'
export default { export default {
oncreate() { oncreate() {
let realm = this.get('realm') let realm = this.get('realm')
if (realm !== 'home') { if (realm === 'home') {
this.__stickyObserver = new IntersectionObserver(entries => {
this.set({sticky: !entries[0].isIntersecting})
})
this.__stickyObserver.observe(this.refs.sentinel)
} else if (realm !== 'dialog') {
// if this is a reply, populate the handle immediately // if this is a reply, populate the handle immediately
insertHandleForReply(realm) insertHandleForReply(realm)
}
this.observe('postedStatusForRealm', postedStatusForRealm => {
if (postedStatusForRealm !== realm) {
return
}
this.fire('postedStatus')
// if this is a reply, go back immediately after it's posted // if this is a reply, go back immediately after it's posted
this.observe('postedStatusForRealm', postedStatusForRealm => { if (realm !== 'home' && realm !== 'dialog') {
if (postedStatusForRealm === realm) { window.history.back()
window.history.back() }
} }, {init: false})
}, {init: false}) },
ondestroy() {
if (this.__stickyObserver) {
this.__stickyObserver.disconnect()
} }
}, },
components: { components: {
@ -107,23 +152,32 @@
slide slide
}, },
methods: { methods: {
onClickPostButton() { async onClickPostButton() {
let text = this.get('text') if (this.get('sticky')) {
let media = this.get('media') // when the button is sticky, we're scrolled down the home timeline,
let postPrivacyKey = this.get('postPrivacyKey') // so we should launch a new compose dialog
let contentWarning = this.get('contentWarning') let dialogs = await importDialogs()
let sensitive = media.length && !!contentWarning dialogs.showComposeDialog()
let realm = this.get('realm') } else {
let mediaIds = media.map(_ => _.data.id) // else we're actually posting a new toot
let inReplyTo = realm === 'home' ? null : realm let text = this.get('text')
let overLimit = this.get('overLimit') let media = this.get('media')
let postPrivacyKey = this.get('postPrivacyKey')
let contentWarning = this.get('contentWarning')
let sensitive = media.length && !!contentWarning
let realm = this.get('realm')
let mediaIds = media.map(_ => _.data.id)
let inReplyTo = (realm === 'home' || realm === 'dialog') ? null : realm
let overLimit = this.get('overLimit')
if (!text || overLimit) { if (!text || overLimit) {
return // do nothing if invalid return // do nothing if invalid
}
/* no await */
postStatus(realm, text, inReplyTo, mediaIds,
sensitive, contentWarning, postPrivacyKey)
} }
/* no await */ postStatus(realm, text, inReplyTo, mediaIds,
sensitive, contentWarning, postPrivacyKey)
} }
} }
} }

View File

@ -1,26 +1,40 @@
<button class="primary compose-box-button" <div class="compose-box-button-halo frosted-glass">
:disabled <button class="primary compose-box-button"
on:click> :disabled
<span class="{{$postingStatus ? 'hidden' : ''}}"> aria-label="{{sticky ? 'Compose' : 'Toot!'}}"
Toot! on:click>
</span> <span class="{{$postingStatus || sticky ? 'hidden' : ''}}">
<div class="compose-box-button-spinner {{$postingStatus ? 'spin' : 'hidden'}}" Toot!
aria-hidden="true"> </span>
<svg class="compose-box-button-spinner-svg"> <div class="compose-box-button-spinner {{$postingStatus ? 'spin' : 'hidden'}}"
<use xlink:href="#fa-spinner" /> aria-hidden="true">
</svg> <svg class="compose-box-button-svg">
</div> <use xlink:href="#fa-spinner" />
</button> </svg>
</div>
<div class="compose-box-button-compose {{sticky ? '' : 'hidden'}}"
aria-hidden="true">
<svg class="compose-box-button-svg">
<use xlink:href="#fa-pencil" />
</svg>
</div>
</button>
</div>
<style> <style>
.compose-box-button-halo {
border-radius: 2px;
margin: 5px 15px 15px 5px;
background: var(--compose-button-halo);
}
.compose-box-button { .compose-box-button {
grid-area: button; grid-area: button;
justify-self: right; justify-self: right;
text-transform: uppercase; text-transform: uppercase;
margin-top: 10px;
position: relative; position: relative;
margin: 5px;
} }
.compose-box-button-spinner { .compose-box-button-spinner, .compose-box-button-compose {
pointer-events: none;
position: absolute; position: absolute;
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -31,11 +45,20 @@
left: 0; left: 0;
right: 0; right: 0;
} }
.compose-box-button-spinner-svg { .compose-box-button-svg {
width: 24px; width: 24px;
height: 24px; height: 24px;
fill: var(--button-primary-text); fill: var(--button-primary-text);
} }
@media (max-width: 767px) {
.compose-box-button-halo {
margin: 5px;
}
.compose-box-button {
margin: 5px;
}
}
</style> </style>
<script> <script>
import { store } from '../../_store/store' import { store } from '../../_store/store'

View File

@ -0,0 +1,22 @@
<ModalDialog :label :shown :closed :title background="var(--main-bg)">
<ComposeBox realm="dialog" on:postedStatus="onPostedStatus()" />
</ModalDialog>
<script>
import ModalDialog from './ModalDialog.html'
import ComposeBox from '../compose/ComposeBox.html'
export default {
components: {
ModalDialog,
ComposeBox
},
methods: {
async show() {
this.set({shown: true})
},
onPostedStatus() {
this.set({closed: true})
}
}
}
</script>

View File

@ -4,7 +4,7 @@
></div> ></div>
<div class="modal-dialog-contents {{fadedIn ? '' : 'hidden'}} {{muted ? 'muted-style' : ''}}" <div class="modal-dialog-contents {{fadedIn ? '' : 'hidden'}} {{muted ? 'muted-style' : ''}}"
role="dialog" role="dialog"
aria-label="{{label}}" aria-label="{{label || ''}}"
ref:node ref:node
> >
<div class="modal-dialog-document" role="document" style="background: {{background || '#000'}};"> <div class="modal-dialog-document" role="document" style="background: {{background || '#000'}};">
@ -41,7 +41,10 @@
position: fixed; position: fixed;
top: 50%; top: 50%;
left: 50%; left: 50%;
-webkit-filter: blur(0);
will-change: transform;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
-webkit-font-smoothing: antialiased; /* fix for transform:translate causing blurry text in Chrome/Safari */
padding: 0; padding: 0;
border: 1px solid var(--main-border); border: 1px solid var(--main-border);
border-radius: 2px; border-radius: 2px;

View File

@ -4,3 +4,4 @@ export * from './showVideoDialog'
export * from './showEmojiDialog' export * from './showEmojiDialog'
export * from './showPostPrivacyDialog' export * from './showPostPrivacyDialog'
export * from './showStatusOptionsDialog' export * from './showStatusOptionsDialog'
export * from './showComposeDialog'

View File

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

View File

@ -78,4 +78,6 @@
--compose-autosuggest-item-hover: $compose-background; --compose-autosuggest-item-hover: $compose-background;
--compose-autosuggest-item-active: darken($compose-background, 5%); --compose-autosuggest-item-active: darken($compose-background, 5%);
--compose-autosuggest-outline: lighten($focus-outline, 5%); --compose-autosuggest-outline: lighten($focus-outline, 5%);
--compose-button-halo: rgba(255, 255, 255, 0.2);
} }

View File

@ -16,9 +16,9 @@
<style> <style>
/* auto-generated w/ build-sass.js */ /* auto-generated w/ build-sass.js */
body{--button-primary-bg:#6081e6;--button-primary-text:#fff;--button-primary-border:#132c76;--button-primary-bg-active:#456ce2;--button-primary-bg-hover:#6988e7;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#4169e1;--main-bg:#fff;--body-bg:#e8edfb;--body-text-color:#333;--main-border:#dadada;--svg-fill:#4169e1;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#4169e1;--nav-border:#214cce;--nav-a-border:#4169e1;--nav-a-selected-border:#fff;--nav-a-selected-bg:#6d8ce8;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#839deb;--nav-a-bg-hover:#577ae4;--nav-a-border-hover:#4169e1;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#90a8ee;--action-button-fill-color-hover:#a2b6f0;--action-button-fill-color-active:#577ae4;--action-button-fill-color-pressed:#2351dc;--action-button-fill-color-pressed-hover:#3862e0;--action-button-fill-color-pressed-active:#1d44b8;--settings-list-item-bg:#fff;--settings-list-item-text:#4169e1;--settings-list-item-text-hover:#4169e1;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#c5d1f6;--very-deemphasized-link-color:rgba(65,105,225,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#d2dcf8;--main-theme-color:#4169e1;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7);--muted-modal-bg:transparent;--muted-modal-focus:#999;--muted-modal-hover:rgba(255,255,255,0.2);--compose-autosuggest-item-hover:#ced8f7;--compose-autosuggest-item-active:#b8c7f4;--compose-autosuggest-outline:#dbe3f9} body{--button-primary-bg:#6081e6;--button-primary-text:#fff;--button-primary-border:#132c76;--button-primary-bg-active:#456ce2;--button-primary-bg-hover:#6988e7;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#4169e1;--main-bg:#fff;--body-bg:#e8edfb;--body-text-color:#333;--main-border:#dadada;--svg-fill:#4169e1;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#4169e1;--nav-border:#214cce;--nav-a-border:#4169e1;--nav-a-selected-border:#fff;--nav-a-selected-bg:#6d8ce8;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#839deb;--nav-a-bg-hover:#577ae4;--nav-a-border-hover:#4169e1;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#90a8ee;--action-button-fill-color-hover:#a2b6f0;--action-button-fill-color-active:#577ae4;--action-button-fill-color-pressed:#2351dc;--action-button-fill-color-pressed-hover:#3862e0;--action-button-fill-color-pressed-active:#1d44b8;--settings-list-item-bg:#fff;--settings-list-item-text:#4169e1;--settings-list-item-text-hover:#4169e1;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#c5d1f6;--very-deemphasized-link-color:rgba(65,105,225,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#d2dcf8;--main-theme-color:#4169e1;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7);--muted-modal-bg:transparent;--muted-modal-focus:#999;--muted-modal-hover:rgba(255,255,255,0.2);--compose-autosuggest-item-hover:#ced8f7;--compose-autosuggest-item-active:#b8c7f4;--compose-autosuggest-outline:#dbe3f9;--compose-button-halo:rgba(255,255,255,0.2)}
body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue;font-size:14px;line-height:1.4;color:var(--body-text-color);background:var(--body-bg);position:fixed;left:0;right:0;bottom:0;top:0}.container{overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;will-change:transform;position:absolute;top:72px;left:0;right:0;bottom:0}@media (max-width: 767px){.container{top:62px}}main{position:relative;width:602px;max-width:100vw;padding:0;box-sizing:border-box;margin:30px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px;min-height:70vh}@media (max-width: 767px){main{margin:5px auto 15px}}footer{width:602px;max-width:100vw;box-sizing:border-box;margin:20px auto;border-radius:1px;background:var(--main-bg);font-size:0.9em;padding:20px;border:1px solid var(--main-border)}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px;box-sizing:border-box}button,.button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover,.button:hover{background:var(--button-bg-hover);text-decoration:none}button:active,.button:active{background:var(--button-bg-active)}button[disabled],.button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary,.button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover,.button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active,.button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}*:focus{outline:2px solid var(--focus-outline)}button::-moz-focus-inner{border:0}input:required,input:invalid{box-shadow:none}textarea{font-family:inherit;font-size:inherit;box-sizing:border-box}@keyframes spin{0%{transform:rotate(0deg)}50%{transform:rotate(180deg)}100%{transform:rotate(360deg)}}.spin{animation:spin 2s infinite linear}.ellipsis::after{content:"\2026"} body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue;font-size:14px;line-height:1.4;color:var(--body-text-color);background:var(--body-bg);position:fixed;left:0;right:0;bottom:0;top:0}.container{overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;will-change:transform;position:absolute;top:72px;left:0;right:0;bottom:0}@media (max-width: 767px){.container{top:62px}}main{position:relative;width:602px;max-width:100vw;padding:0;box-sizing:border-box;margin:30px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px;min-height:70vh}@media (max-width: 767px){main{margin:5px auto 15px}}footer{width:602px;max-width:100vw;box-sizing:border-box;margin:20px auto;border-radius:1px;background:var(--main-bg);font-size:0.9em;padding:20px;border:1px solid var(--main-border)}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px;box-sizing:border-box}button,.button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover,.button:hover{background:var(--button-bg-hover);text-decoration:none}button:active,.button:active{background:var(--button-bg-active)}button[disabled],.button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary,.button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover,.button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active,.button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}*:focus{outline:2px solid var(--focus-outline)}button::-moz-focus-inner{border:0}input:required,input:invalid{box-shadow:none}textarea{font-family:inherit;font-size:inherit;box-sizing:border-box}@keyframes spin{0%{transform:rotate(0deg)}50%{transform:rotate(180deg)}100%{transform:rotate(360deg)}}.spin{animation:spin 2s infinite linear}.ellipsis::after{content:"\2026"}
body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-oaken.offline,body.theme-scarlet.offline,body.theme-seafoam.offline,body.theme-gecko.offline{--button-primary-bg:#ababab;--button-primary-text:#fff;--button-primary-border:#4d4d4d;--button-primary-bg-active:#9c9c9c;--button-primary-bg-hover:#b0b0b0;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#999;--main-bg:#fff;--body-bg:#fafafa;--body-text-color:#333;--main-border:#dadada;--svg-fill:#999;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#999;--nav-border:gray;--nav-a-border:#999;--nav-a-selected-border:#fff;--nav-a-selected-bg:#b3b3b3;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#bfbfbf;--nav-a-bg-hover:#a6a6a6;--nav-a-border-hover:#999;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#c7c7c7;--action-button-fill-color-hover:#d1d1d1;--action-button-fill-color-active:#a6a6a6;--action-button-fill-color-pressed:#878787;--action-button-fill-color-pressed-hover:#949494;--action-button-fill-color-pressed-active:#737373;--settings-list-item-bg:#fff;--settings-list-item-text:#999;--settings-list-item-text-hover:#999;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#bfbfbf;--very-deemphasized-link-color:rgba(153,153,153,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#ededed;--main-theme-color:#999;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7);--muted-modal-bg:transparent;--muted-modal-focus:#999;--muted-modal-hover:rgba(255,255,255,0.2);--compose-autosuggest-item-hover:#c4c4c4;--compose-autosuggest-item-active:#b8b8b8;--compose-autosuggest-outline:#ccc} body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-oaken.offline,body.theme-scarlet.offline,body.theme-seafoam.offline,body.theme-gecko.offline{--button-primary-bg:#ababab;--button-primary-text:#fff;--button-primary-border:#4d4d4d;--button-primary-bg-active:#9c9c9c;--button-primary-bg-hover:#b0b0b0;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#999;--main-bg:#fff;--body-bg:#fafafa;--body-text-color:#333;--main-border:#dadada;--svg-fill:#999;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#999;--nav-border:gray;--nav-a-border:#999;--nav-a-selected-border:#fff;--nav-a-selected-bg:#b3b3b3;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#bfbfbf;--nav-a-bg-hover:#a6a6a6;--nav-a-border-hover:#999;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#c7c7c7;--action-button-fill-color-hover:#d1d1d1;--action-button-fill-color-active:#a6a6a6;--action-button-fill-color-pressed:#878787;--action-button-fill-color-pressed-hover:#949494;--action-button-fill-color-pressed-active:#737373;--settings-list-item-bg:#fff;--settings-list-item-text:#999;--settings-list-item-text-hover:#999;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#bfbfbf;--very-deemphasized-link-color:rgba(153,153,153,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#ededed;--main-theme-color:#999;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7);--muted-modal-bg:transparent;--muted-modal-focus:#999;--muted-modal-hover:rgba(255,255,255,0.2);--compose-autosuggest-item-hover:#c4c4c4;--compose-autosuggest-item-active:#b8b8b8;--compose-autosuggest-outline:#ccc;--compose-button-halo:rgba(255,255,255,0.2)}
</style> </style>
@ -109,6 +109,7 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
<symbol id="fa-check" viewBox="0 0 1792 1792"><title>Check</title><path d="M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z"></path></symbol> <symbol id="fa-check" viewBox="0 0 1792 1792"><title>Check</title><path d="M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z"></path></symbol>
<symbol id="fa-trash" viewBox="0 0 1792 1792"><title>Delete</title><path d="M704 736v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm128 724V512H448v948q0 22 7 40.5t14.5 27 10.5 8.5h832q3 0 10.5-8.5t14.5-27 7-40.5zM672 384h448l-48-117q-7-9-17-11H738q-10 2-17 11zm928 32v64q0 14-9 23t-23 9h-96v948q0 83-47 143.5t-113 60.5H480q-66 0-113-58.5T320 1464V512h-96q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h309l70-167q15-37 54-63t79-26h320q40 0 79 26t54 63l70 167h309q14 0 23 9t9 23z"></path></symbol> <symbol id="fa-trash" viewBox="0 0 1792 1792"><title>Delete</title><path d="M704 736v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm128 724V512H448v948q0 22 7 40.5t14.5 27 10.5 8.5h832q3 0 10.5-8.5t14.5-27 7-40.5zM672 384h448l-48-117q-7-9-17-11H738q-10 2-17 11zm928 32v64q0 14-9 23t-23 9h-96v948q0 83-47 143.5t-113 60.5H480q-66 0-113-58.5T320 1464V512h-96q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h309l70-167q15-37 54-63t79-26h320q40 0 79 26t54 63l70 167h309q14 0 23 9t9 23z"></path></symbol>
<symbol id="fa-hourglass" viewBox="0 0 1792 1792"><title>Follow requested</title><path d="M1632 1600q14 0 23 9t9 23v128q0 14-9 23t-23 9H160q-14 0-23-9t-9-23v-128q0-14 9-23t23-9h1472zm-1374-64q3-55 16-107t30-95 46-87 53.5-76 64.5-69.5 66-60 70.5-55T671 939t65-43q-43-28-65-43t-66.5-47.5-70.5-55-66-60-64.5-69.5-53.5-76-46-87-30-95-16-107h1276q-3 55-16 107t-30 95-46 87-53.5 76-64.5 69.5-66 60-70.5 55T1121 853t-65 43q43 28 65 43t66.5 47.5 70.5 55 66 60 64.5 69.5 53.5 76 46 87 30 95 16 107H258zM1632 0q14 0 23 9t9 23v128q0 14-9 23t-23 9H160q-14 0-23-9t-9-23V32q0-14 9-23t23-9h1472z"></path></symbol> <symbol id="fa-hourglass" viewBox="0 0 1792 1792"><title>Follow requested</title><path d="M1632 1600q14 0 23 9t9 23v128q0 14-9 23t-23 9H160q-14 0-23-9t-9-23v-128q0-14 9-23t23-9h1472zm-1374-64q3-55 16-107t30-95 46-87 53.5-76 64.5-69.5 66-60 70.5-55T671 939t65-43q-43-28-65-43t-66.5-47.5-70.5-55-66-60-64.5-69.5-53.5-76-46-87-30-95-16-107h1276q-3 55-16 107t-30 95-46 87-53.5 76-64.5 69.5-66 60-70.5 55T1121 853t-65 43q43 28 65 43t66.5 47.5 70.5 55 66 60 64.5 69.5 53.5 76 46 87 30 95 16 107H258zM1632 0q14 0 23 9t9 23v128q0 14-9 23t-23 9H160q-14 0-23-9t-9-23V32q0-14 9-23t23-9h1472z"></path></symbol>
<symbol id="fa-pencil" viewBox="0 0 1792 1792"><title>Compose</title><path d="M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z"></path></symbol>
</svg><!-- end insert svg here --> </svg><!-- end insert svg here -->
</svg> </svg>
<!-- The application will be rendered inside this element, <!-- The application will be rendered inside this element,

View File

@ -0,0 +1,27 @@
import {
composeButton, getNthStatus, scrollToStatus, scrollToTopOfTimeline, modalDialog, sleep, showMoreButton,
scrollContainerToTop
} from '../utils'
import { foobarRole } from '../roles'
fixture`108-compose-dialog.js`
.page`http://localhost:4002`
test('can compose using a dialog', async t => {
await t.useRole(foobarRole)
await scrollToStatus(t, 15)
await t.expect(modalDialog.getAttribute('aria-hidden')).eql('true')
.click(composeButton)
.expect(modalDialog.hasAttribute('aria-hidden')).notOk()
.typeText(modalDialog.find('.compose-box-input'), 'hello from the modal')
.click(modalDialog.find('.compose-box-button-compose'))
.expect(modalDialog.getAttribute('aria-hidden')).eql('true')
await sleep(5000)
await scrollToTopOfTimeline(t)
await t.hover(getNthStatus(0))
await scrollContainerToTop()
await t
.expect(showMoreButton.innerText).contains('Show 1 more')
.click(showMoreButton)
await t.expect(getNthStatus(0).innerText).contains('hello from the modal', {timeout: 20000})
})

View File

@ -6,6 +6,7 @@ const SCROLL_INTERVAL = 1
export const settingsButton = $('nav a[aria-label=Settings]') export const settingsButton = $('nav a[aria-label=Settings]')
export const instanceInput = $('#instanceInput') export const instanceInput = $('#instanceInput')
export const modalDialog = $('#modal-dialog')
export const modalDialogContents = $('.modal-dialog-contents') export const modalDialogContents = $('.modal-dialog-contents')
export const closeDialogButton = $('.close-dialog-button') export const closeDialogButton = $('.close-dialog-button')
export const notificationsNavButton = $('nav a[href="/notifications"]') export const notificationsNavButton = $('nav a[href="/notifications"]')