fix: return focus to sensitive media button (#1535)

* fix: return focus to sensitive media button

fixes #1517

* additional fix for media sensitive focus

* fix audio/video name in aria-label of button

* fix hotkeys
This commit is contained in:
Nolan Lawson 2019-09-24 22:31:56 -07:00 committed by GitHub
parent af27c8b26b
commit ea4c1ad819
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 35 deletions

View file

@ -2,7 +2,9 @@
<button id={elementId} <button id={elementId}
type="button" type="button"
class="inline-media play-video-button focus-after {$largeInlineMedia ? '' : 'fixed-size'} {type === 'audio' ? 'play-audio-button' : ''}" class="inline-media play-video-button focus-after {$largeInlineMedia ? '' : 'fixed-size'} {type === 'audio' ? 'play-audio-button' : ''}"
aria-label="Play video: {description}" aria-label="Play {type === 'video' ? 'video' : 'audio'}: {description}"
{tabindex}
aria-hidden={ariaHidden}
style={inlineMediaStyle}> style={inlineMediaStyle}>
<PlayVideoIcon /> <PlayVideoIcon />
{#if type === 'video'} {#if type === 'video'}
@ -26,7 +28,10 @@
aria-label="Show image: {description}" aria-label="Show image: {description}"
title={description} title={description}
on:mouseover="set({mouseover: event})" on:mouseover="set({mouseover: event})"
style={inlineMediaStyle}> style={inlineMediaStyle}
{tabindex}
aria-hidden={ariaHidden}
>
{#if type === 'gifv' && $autoplayGifs && !blurhash} {#if type === 'gifv' && $autoplayGifs && !blurhash}
<AutoplayVideo <AutoplayVideo
ariaLabel="Animated GIF: {description}" ariaLabel="Animated GIF: {description}"
@ -159,7 +164,9 @@ export default {
} else { } else {
return `width: ${inlineWidth}px; height: ${inlineHeight}px;` return `width: ${inlineWidth}px; height: ${inlineHeight}px;`
} }
} },
tabindex: ({ showAsSensitive }) => showAsSensitive ? '-1' : '0',
ariaHidden: ({ showAsSensitive }) => showAsSensitive
}, },
methods: { methods: {
onClick () { onClick () {

View file

@ -5,7 +5,9 @@
<button id={elementId} <button id={elementId}
type="button" type="button"
class="status-sensitive-media-button" class="status-sensitive-media-button"
aria-label="Hide sensitive media" > aria-label="Hide sensitive media"
ref:hideSensitiveMedia
>
<div class="svg-wrapper"> <div class="svg-wrapper">
<SvgIcon className="status-sensitive-media-svg" <SvgIcon className="status-sensitive-media-svg"
href="#fa-eye-slash" /> href="#fa-eye-slash" />
@ -15,7 +17,9 @@
<button id={elementId} <button id={elementId}
type="button" type="button"
class="status-sensitive-media-button" class="status-sensitive-media-button"
aria-label="Show sensitive media" > aria-label="Show sensitive media"
ref:showSensitiveMedia
>
<div class="status-sensitive-media-warning"> <div class="status-sensitive-media-warning">
<div class="status-sensitive-media-warning-text"> <div class="status-sensitive-media-warning-text">
@ -31,7 +35,7 @@
</div> </div>
</div> </div>
{#if enableShortcuts} {#if enableShortcuts}
<Shortcut scope={shortcutScope} key="y" on:pressed="toggleSensitiveMedia()"/> <Shortcut scope={shortcutScope} key="y" on:pressed="toggleSensitiveMedia(false)"/>
{/if} {/if}
{:else} {:else}
<MediaAttachments {mediaAttachments} {sensitive} {sensitiveShown} {uuid} /> <MediaAttachments {mediaAttachments} {sensitive} {sensitiveShown} {uuid} />
@ -167,7 +171,7 @@
export default { export default {
oncreate () { oncreate () {
const { elementId } = this.get() const { elementId } = this.get()
registerClickDelegate(this, elementId, () => this.toggleSensitiveMedia()) registerClickDelegate(this, elementId, () => this.toggleSensitiveMedia(true))
}, },
components: { components: {
MediaAttachments, MediaAttachments,
@ -206,12 +210,24 @@
} }
}, },
methods: { methods: {
toggleSensitiveMedia () { toggleSensitiveMedia (changeFocus) {
const { uuid } = this.get() const { uuid } = this.get()
const { sensitivesShown } = this.store.get() const { sensitivesShown } = this.store.get()
sensitivesShown[uuid] = !sensitivesShown[uuid] sensitivesShown[uuid] = !sensitivesShown[uuid]
this.store.set({ sensitivesShown }) this.store.set({ sensitivesShown })
this.fire('recalculateHeight') this.fire('recalculateHeight')
// Only change focus for clicks, not for hotkeys. It's weird if, when the entire toot
// is focused and you press "y", that the focus changes to the sensitive media button.
if (changeFocus) {
requestAnimationFrame(() => {
const element = this.refs.hideSensitiveMedia || this.refs.showSensitiveMedia
try {
element.focus({ preventScroll: true })
} catch (e) {
console.error('ignored focus error', e)
}
})
}
return true return true
} }
} }

View file

@ -1,7 +1,20 @@
import { import {
getNthStatus, scrollToStatus, closeDialogButton, modalDialogContents, goBack, getUrl, getNthStatus,
goBackButton, getActiveElementInnerText, getNthReplyButton, getActiveElementInsideNthStatus, focus, scrollToStatus,
getNthStatusSelector, getActiveElementTagName, getActiveElementClassList closeDialogButton,
modalDialogContents,
goBack,
getUrl,
goBackButton,
getActiveElementInnerText,
getNthReplyButton,
getActiveElementInsideNthStatus,
focus,
getNthStatusSelector,
getActiveElementTagName,
getActiveElementClassList,
getNthStatusSensitiveMediaButton,
getActiveElementAriaLabel
} from '../utils' } from '../utils'
import { loginAsFoobar } from '../roles' import { loginAsFoobar } from '../roles'
import { Selector as $ } from 'testcafe' import { Selector as $ } from 'testcafe'
@ -113,3 +126,14 @@ test('reply preserves focus and moves focus to the text input', async t => {
test('focus main content element on index page load', async t => { test('focus main content element on index page load', async t => {
await t.expect(getActiveElementTagName()).match(/body/i) await t.expect(getActiveElementTagName()).match(/body/i)
}) })
test('clicking sensitive button returns focus to sensitive button', async t => {
await loginAsFoobar(t)
const sensitiveKittenIdx = homeTimeline.findIndex(_ => _.spoiler === 'kitten CW')
await scrollToStatus(t, sensitiveKittenIdx + 1)
await t
.click(getNthStatusSensitiveMediaButton(sensitiveKittenIdx + 1))
.expect(getActiveElementAriaLabel()).eql('Hide sensitive media')
.click(getNthStatusSensitiveMediaButton(sensitiveKittenIdx + 1))
.expect(getActiveElementAriaLabel()).eql('Show sensitive media')
})