add auto-focus to reply input text

This commit is contained in:
Nolan Lawson 2018-03-16 19:04:48 -07:00
parent 9a0071a934
commit ed0db17ca0
7 changed files with 40 additions and 4 deletions

View file

@ -4,7 +4,8 @@
aria-pressed="{{pressable ? !!pressed : ''}}"
class="{{computedClass}}"
:disabled
delegate-key="{{delegateKey}}" >
delegate-key="{{delegateKey}}"
focus-key="{{focusKey || ''}}" >
<svg class="icon-button-svg">
<use xlink:href="{{href}}" />
</svg>
@ -14,6 +15,7 @@
aria-label="{{label}}"
aria-pressed="{{pressable ? !!pressed : ''}}"
class="{{computedClass}}"
focus-key="{{focusKey || ''}}"
:disabled
on:click >
<svg class="icon-button-svg">

View file

@ -6,7 +6,7 @@
<ComposeContentWarning :realm :contentWarning />
</div>
{{/if}}
<ComposeInput :realm :text />
<ComposeInput :realm :text :autoFocus />
<ComposeLengthGauge :length :overLimit />
<ComposeToolbar :realm :postPrivacy :media :contentWarningShown />
<ComposeLengthIndicator :length :overLimit />

View file

@ -43,6 +43,9 @@
setupSyncFromStore() {
this.observe('text', text => {
this.set({rawText: text})
if (this.get('autoFocus')) {
this.refs.textarea.focus()
}
})
},
setupSyncToStore() {

View file

@ -4,6 +4,7 @@
href="#fa-reply"
disabled="{{disableReply}}"
delegateKey="{{replyKey}}"
focusKey="{{replyKey}}"
/>
<IconButton
label="{{reblogLabel}}"

View file

@ -7,7 +7,7 @@
timelineValue="{{params.statusId}}"
:status
/>
<ComposeBox realm="{{params.statusId}}" />
<ComposeBox realm="{{params.statusId}}" autoFocus="true" />
{{else}}
<LoadingPage />
{{/if}}

View file

@ -1,6 +1,6 @@
import {
getNthStatus, scrollToStatus, closeDialogButton, modalDialogContents, getActiveElementClass, goBack, getUrl,
goBackButton, getActiveElementInnerText
goBackButton, getActiveElementInnerText, getNthReplyButton, getActiveElementAriaLabel, getActiveElementInsideNthStatus
} from '../utils'
import { foobarRole } from '../roles'
@ -14,6 +14,7 @@ test('modal preserves focus', async t => {
.click(closeDialogButton)
.expect(modalDialogContents.exists).notOk()
.expect(getActiveElementClass()).contains('play-video-button')
.expect(getActiveElementInsideNthStatus()).eql('9')
})
test('timeline preserves focus', async t => {
@ -24,6 +25,7 @@ test('timeline preserves focus', async t => {
await goBack()
await t.expect(getUrl()).eql('http://localhost:4002/')
.expect(getActiveElementClass()).contains('status-article status-in-timeline')
.expect(getActiveElementInsideNthStatus()).eql('0')
})
test('timeline link preserves focus', async t => {
@ -38,6 +40,7 @@ test('timeline link preserves focus', async t => {
.click(goBackButton)
.expect(getUrl()).eql('http://localhost:4002/')
.expect(getActiveElementClass()).contains('status-sidebar')
.expect(getActiveElementInsideNthStatus()).eql('0')
})
test('notification timeline preserves focus', async t => {
@ -49,4 +52,17 @@ test('notification timeline preserves focus', async t => {
.click(goBackButton)
.expect(getUrl()).eql('http://localhost:4002/notifications')
.expect(getActiveElementInnerText()).eql('quux')
.expect(getActiveElementInsideNthStatus()).eql('5')
})
test('reply preserves focus and moves focus to the text input', async t => {
await t.useRole(foobarRole)
.click(getNthReplyButton(1))
.expect(getUrl()).contains('/reply')
.expect(getActiveElementClass()).contains('compose-box-input')
.click(goBackButton)
.expect(getUrl()).eql('http://localhost:4002/')
.expect(getActiveElementClass()).contains('icon-button')
.expect(getActiveElementAriaLabel()).eql('Reply')
.expect(getActiveElementInsideNthStatus()).eql('1')
})

View file

@ -53,6 +53,20 @@ export const getActiveElementInnerText = exec(() =>
document.activeElement && document.activeElement.innerText
)
export const getActiveElementAriaLabel = exec(() =>
document.activeElement ? document.activeElement.getAttribute('aria-label') : ''
)
export const getActiveElementInsideNthStatus = exec(() => {
let element = document.activeElement
while (element) {
if (element.hasAttribute('aria-posinset')) {
return element.getAttribute('aria-posinset')
}
element = element.parentElement
}
})
export const goBack = exec(() => window.history.back())
export const forceOffline = exec(() => window.store.set({online: false}))