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:
parent
af27c8b26b
commit
ea4c1ad819
|
@ -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 () {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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')
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in a new issue