feat(a11y): add option for short article aria labels (#705)

Actually fixes #694 by providing an option to make the labels like they used to be.
This commit is contained in:
Nolan Lawson 2018-12-01 11:53:20 -08:00 committed by GitHub
parent 0515133ece
commit 153e4f4fcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 65 deletions

View File

@ -2,9 +2,7 @@ import { getAccountAccessibleName } from './getAccountAccessibleName'
import { POST_PRIVACY_OPTIONS } from '../_static/statuses'
import { htmlToPlainText } from '../_utils/htmlToPlainText'
const MAX_TEXT_LENGTH = 150
function notificationText (notification, omitEmojiInDisplayNames) {
function getNotificationText (notification, omitEmojiInDisplayNames) {
if (!notification) {
return
}
@ -16,7 +14,7 @@ function notificationText (notification, omitEmojiInDisplayNames) {
}
}
function privacyText (visibility) {
function getPrivacyText (visibility) {
for (let option of POST_PRIVACY_OPTIONS) {
if (option.key === visibility) {
return option.label
@ -24,7 +22,7 @@ function privacyText (visibility) {
}
}
function reblogText (reblog, account, omitEmojiInDisplayNames) {
function getReblogText (reblog, account, omitEmojiInDisplayNames) {
if (!reblog) {
return
}
@ -32,32 +30,34 @@ function reblogText (reblog, account, omitEmojiInDisplayNames) {
return `Boosted by ${accountDisplayName}`
}
// Works around a bug in NVDA where it may crash if the string is too long
// https://github.com/nolanlawson/pinafore/issues/694
function truncateTextForSRs (text) {
if (text.length > MAX_TEXT_LENGTH) {
text = text.substring(0, MAX_TEXT_LENGTH)
text = text.replace(/\S+$/, '') + ' (truncated)'
}
function cleanupText (text) {
return text.replace(/\s+/g, ' ').trim()
}
export function getAccessibleLabelForStatus (originalAccount, account, content,
timeagoFormattedDate, spoilerText, showContent,
reblog, notification, visibility, omitEmojiInDisplayNames) {
reblog, notification, visibility, omitEmojiInDisplayNames,
disableLongAriaLabels) {
let originalAccountDisplayName = getAccountAccessibleName(originalAccount, omitEmojiInDisplayNames)
let contentTextToShow = (showContent || !spoilerText)
? truncateTextForSRs(htmlToPlainText(content))
: `Content warning: ${truncateTextForSRs(spoilerText)}`
? cleanupText(htmlToPlainText(content))
: `Content warning: ${cleanupText(spoilerText)}`
let privacyText = getPrivacyText(visibility)
if (disableLongAriaLabels) {
// Long text can crash NVDA; allow users to shorten it like we had it before.
// https://github.com/nolanlawson/pinafore/issues/694
return `${privacyText} status by ${originalAccountDisplayName}`
}
let values = [
notificationText(notification, omitEmojiInDisplayNames),
getNotificationText(notification, omitEmojiInDisplayNames),
originalAccountDisplayName,
contentTextToShow,
timeagoFormattedDate,
`@${originalAccount.acct}`,
privacyText(visibility),
reblogText(reblog, account, omitEmojiInDisplayNames)
privacyText,
getReblogText(reblog, account, omitEmojiInDisplayNames)
].filter(Boolean)
return values.join(', ')

View File

@ -220,10 +220,10 @@
timeagoFormattedDate: ({ createdAtDate }) => formatTimeagoDate(createdAtDate),
reblog: ({ status }) => status.reblog,
ariaLabel: ({ originalAccount, account, content, timeagoFormattedDate, spoilerText,
showContent, reblog, notification, visibility, $omitEmojiInDisplayNames }) => (
showContent, reblog, notification, visibility, $omitEmojiInDisplayNames, $disableLongAriaLabels }) => (
getAccessibleLabelForStatus(originalAccount, account, content,
timeagoFormattedDate, spoilerText, showContent,
reblog, notification, visibility, $omitEmojiInDisplayNames)
reblog, notification, visibility, $omitEmojiInDisplayNames, $disableLongAriaLabels)
),
showHeader: ({ notification, status, timelineType }) => (
(notification && (notification.type === 'reblog' || notification.type === 'favourite')) ||

View File

@ -28,6 +28,11 @@
bind:checked="$disableCustomScrollbars" on:change="$save()">
<label for="choice-disable-custom-scrollbars">Disable custom scrollbars</label>
</div>
<div class="setting-group">
<input type="checkbox" id="choice-disable-long-aria-labels"
bind:checked="$disableLongAriaLabels" on:change="$save()">
<label for="choice-disable-long-aria-labels">Use short article ARIA labels</label>
</div>
</form>
<h2>Themes

View File

@ -4,58 +4,52 @@ import { mixins } from './mixins/mixins'
import { LocalStorageStore } from './LocalStorageStore'
import { observe } from 'svelte-extras'
const KEYS_TO_STORE_IN_LOCAL_STORAGE = new Set([
'currentInstance',
'currentRegisteredInstance',
'currentRegisteredInstanceName',
'instanceNameInSearch',
'instanceThemes',
'loggedInInstances',
'loggedInInstancesInOrder',
'autoplayGifs',
'markMediaAsSensitive',
'reduceMotion',
'disableCustomScrollbars',
'omitEmojiInDisplayNames',
'pinnedPages',
'composeData',
'pushSubscription'
])
const persistedState = {
autoplayGifs: false,
composeData: {},
currentInstance: null,
currentRegisteredInstanceName: undefined,
currentRegisteredInstance: undefined,
disableCustomScrollbars: false,
disableLongAriaLabels: false,
instanceNameInSearch: '',
instanceThemes: {},
loggedInInstances: {},
loggedInInstancesInOrder: [],
markMediaAsSensitive: false,
omitEmojiInDisplayNames: undefined,
pinnedPages: {},
pushSubscription: null,
reduceMotion: !process.browser || window.matchMedia('(prefers-reduced-motion: reduce)').matches
}
const nonPersistedState = {
customEmoji: {},
instanceInfos: {},
instanceLists: {},
online: !process.browser || navigator.onLine,
pinnedStatuses: {},
pushNotificationsSupport: process.browser && ('serviceWorker' in navigator && 'PushManager' in window && 'getKey' in window.PushSubscription.prototype),
queryInSearch: '',
repliesShown: {},
sensitivesShown: {},
spoilersShown: {},
statusModifications: {},
verifyCredentials: {}
}
const state = Object.assign({}, persistedState, nonPersistedState)
const keysToStoreInLocalStorage = new Set(Object.keys(persistedState))
class PinaforeStore extends LocalStorageStore {
constructor (state) {
super(state, KEYS_TO_STORE_IN_LOCAL_STORAGE)
super(state, keysToStoreInLocalStorage)
}
}
PinaforeStore.prototype.observe = observe
export const store = new PinaforeStore({
instanceNameInSearch: '',
queryInSearch: '',
currentInstance: null,
loggedInInstances: {},
loggedInInstancesInOrder: [],
instanceThemes: {},
spoilersShown: {},
sensitivesShown: {},
repliesShown: {},
autoplayGifs: false,
markMediaAsSensitive: false,
reduceMotion: !process.browser || window.matchMedia('(prefers-reduced-motion: reduce)').matches,
disableCustomScrollbars: false,
pinnedPages: {},
instanceLists: {},
pinnedStatuses: {},
instanceInfos: {},
statusModifications: {},
customEmoji: {},
composeData: {},
verifyCredentials: {},
online: !process.browser || navigator.onLine,
pushNotificationsSupport: process.browser && ('serviceWorker' in navigator && 'PushManager' in window && 'getKey' in window.PushSubscription.prototype),
pushSubscription: null
})
export const store = new PinaforeStore(state)
mixins(PinaforeStore)
computations(store)

View File

@ -1,5 +1,13 @@
import { loginAsFoobar } from '../roles'
import { getNthShowOrHideButton, getNthStatus, notificationsNavButton, scrollToStatus } from '../utils'
import {
generalSettingsButton,
getNthShowOrHideButton,
getNthStatus, homeNavButton,
notificationsNavButton,
scrollToStatus,
settingsNavButton
} from '../utils'
import { Selector as $ } from 'testcafe'
import { indexWhere } from '../../routes/_utils/arrays'
import { homeTimeline } from '../fixtures'
@ -67,3 +75,24 @@ test('aria-labels for notifications', async t => {
/quux followed you, @quux/i
)
})
test('can shorten aria-labels', async t => {
await loginAsFoobar(t)
await t
.click(settingsNavButton)
.click(generalSettingsButton)
.click($('#choice-disable-long-aria-labels'))
.click(homeNavButton)
.hover(getNthStatus(0))
.expect(getNthStatus(0).getAttribute('aria-label')).match(
/Unlisted status by quux/
)
.click(settingsNavButton)
.click(generalSettingsButton)
.click($('#choice-disable-long-aria-labels'))
.click(homeNavButton)
.hover(getNthStatus(0))
.expect(getNthStatus(0).getAttribute('aria-label')).match(
/quux, pinned toot 1, .+ ago, @quux, Unlisted, Boosted by admin/i
)
})