forked from cybrespace/pinafore
improve a11y of fields, status page, and more (#505)
* improve a11y of fields, status page, and more * tweak nav name * fix community page and tweak text * don't show pinned statuses heading unless there are pinned statuses
This commit is contained in:
parent
46fa65f25a
commit
120f50919e
|
@ -1,12 +1,15 @@
|
||||||
<div class="dynamic-page-banner {icon ? 'dynamic-page-with-icon' : ''}">
|
<div class="dynamic-page-banner {icon ? 'dynamic-page-with-icon' : ''}"
|
||||||
|
role="navigation" aria-label="Page header"
|
||||||
|
>
|
||||||
{#if icon}
|
{#if icon}
|
||||||
<svg class="dynamic-page-banner-svg">
|
<svg class="dynamic-page-banner-svg">
|
||||||
<use xlink:href={icon} />
|
<use xlink:href={icon} />
|
||||||
</svg>
|
</svg>
|
||||||
{/if}
|
{/if}
|
||||||
<h1 class="dynamic-page-title">{title}</h1>
|
<h1 class="dynamic-page-title" aria-label={ariaTitle}>{title}</h1>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="dynamic-page-go-back"
|
class="dynamic-page-go-back"
|
||||||
|
aria-label="Go back"
|
||||||
on:click="onGoBack(event)">Back</button>
|
on:click="onGoBack(event)">Back</button>
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
|
@ -61,7 +64,8 @@
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
icon: void 0
|
icon: void 0,
|
||||||
|
ariaTitle: ''
|
||||||
}),
|
}),
|
||||||
methods: {
|
methods: {
|
||||||
onGoBack (e) {
|
onGoBack (e) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<svg class="page-list-item-svg">
|
<svg class="page-list-item-svg">
|
||||||
<use xlink:href={icon} />
|
<use xlink:href={icon} />
|
||||||
</svg>
|
</svg>
|
||||||
<span aria-label="{label} {$pinnedPage === href ? 'Pinned page' : 'Unpinned page'}">
|
<span aria-label={ariaLabel}>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
{#if pinnable}
|
{#if pinnable}
|
||||||
|
@ -72,6 +72,15 @@
|
||||||
data: () => ({
|
data: () => ({
|
||||||
pinnable: false
|
pinnable: false
|
||||||
}),
|
}),
|
||||||
|
computed: {
|
||||||
|
ariaLabel: ({label, pinnable, $pinnedPage, href}) => {
|
||||||
|
let res = label
|
||||||
|
if (pinnable) {
|
||||||
|
res += ' (' + ($pinnedPage === href ? 'Pinned page' : 'Unpinned page') + ')'
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
IconButton
|
IconButton
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{#if realm === 'home'}
|
{#if realm === 'home'}
|
||||||
<h1 class="sr-only">Compose toot</h1>
|
<h1 class="sr-only">Compose status</h1>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="{computedClassName} {hideAndFadeIn}">
|
<div class="{computedClassName} {hideAndFadeIn}">
|
||||||
<ComposeAuthor />
|
<ComposeAuthor />
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<h1 class="sr-only">Profile for {accountName}</h1>
|
||||||
<div class="account-profile {headerImageIsMissing ? 'header-image-is-missing' : ''}"
|
<div class="account-profile {headerImageIsMissing ? 'header-image-is-missing' : ''}"
|
||||||
style="background-image: url({headerImage});">
|
style="background-image: url({headerImage});">
|
||||||
<div class="account-profile-grid-wrapper">
|
<div class="account-profile-grid-wrapper">
|
||||||
|
@ -79,7 +80,8 @@
|
||||||
store: () => store,
|
store: () => store,
|
||||||
computed: {
|
computed: {
|
||||||
headerImageIsMissing: ({ account }) => account.header.endsWith('missing.png'),
|
headerImageIsMissing: ({ account }) => account.header.endsWith('missing.png'),
|
||||||
headerImage: ({ $autoplayGifs, account }) => $autoplayGifs ? account.header : account.header_static
|
headerImage: ({ $autoplayGifs, account }) => $autoplayGifs ? account.header : account.header_static,
|
||||||
|
accountName: ({ account }) => (account && (account.display_name || account.username)) || ''
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
AccountProfileHeader,
|
AccountProfileHeader,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<h2 class="sr-only">Stats and more options</h2>
|
||||||
<div class="account-profile-details">
|
<div class="account-profile-details">
|
||||||
<div class="account-profile-details-item">
|
<div class="account-profile-details-item">
|
||||||
<span class="account-profile-details-item-title">
|
<span class="account-profile-details-item-title">
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<h2 class="sr-only">Name and following</h2>
|
||||||
<div class="account-profile-avatar">
|
<div class="account-profile-avatar">
|
||||||
<Avatar {account} size="big" />
|
<Avatar {account} size="big" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
{#if emojifiedFields.length}
|
{#if emojifiedFields.length}
|
||||||
|
<h2 class="sr-only">Fields</h2>
|
||||||
<div class="account-profile-meta">
|
<div class="account-profile-meta">
|
||||||
<div class="account-profile-meta-border"></div>
|
<div class="account-profile-meta-border"></div>
|
||||||
{#each emojifiedFields as field, i}
|
{#each emojifiedFields as field, i}
|
||||||
<div class="account-profile-meta-cell account-profile-meta-name">
|
<div
|
||||||
|
id="account-profile-meta-name-{i}"
|
||||||
|
class="account-profile-meta-cell account-profile-meta-name"
|
||||||
|
role="term"
|
||||||
|
>
|
||||||
{field.name}
|
{field.name}
|
||||||
</div>
|
</div>
|
||||||
<div class="account-profile-meta-cell account-profile-meta-value">
|
<div
|
||||||
|
class="account-profile-meta-cell account-profile-meta-value"
|
||||||
|
role="definition"
|
||||||
|
aria-labelledby="account-profile-meta-name-{i}"
|
||||||
|
>
|
||||||
{@html field.value}
|
{@html field.value}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<h2 class="sr-only">Description</h2>
|
||||||
<div class="account-profile-note">
|
<div class="account-profile-note">
|
||||||
{@html massagedNote}
|
{@html massagedNote}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -217,9 +217,10 @@
|
||||||
}
|
}
|
||||||
return originalAccountDisplayName
|
return originalAccountDisplayName
|
||||||
},
|
},
|
||||||
ariaLabel: ({ originalAccountAccessibleName, originalStatus, visibility }) => (
|
ariaLabel: ({ originalAccountAccessibleName, originalStatus, visibility, isStatusInOwnThread }) => (
|
||||||
(visibility === 'direct' ? 'Direct message' : 'Status') +
|
(visibility === 'direct' ? 'Direct message' : 'Status') +
|
||||||
` by ${originalAccountAccessibleName}`
|
` by ${originalAccountAccessibleName}` +
|
||||||
|
(isStatusInOwnThread ? ' (focused)' : '')
|
||||||
),
|
),
|
||||||
showHeader: ({ notification, status, timelineType }) => (
|
showHeader: ({ notification, status, timelineType }) => (
|
||||||
(notification && (notification.type === 'reblog' || notification.type === 'favourite')) ||
|
(notification && (notification.type === 'reblog' || notification.type === 'favourite')) ||
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
<div role="feed" aria-label="Pinned toots" class="pinned-statuses">
|
{#if pinnedStatuses.length }
|
||||||
{#each pinnedStatuses as status, index (status.id)}
|
<h1 class="sr-only">Pinned statuses</h1>
|
||||||
<Status {status}
|
<div role="feed" aria-label="Pinned statuses" class="pinned-statuses">
|
||||||
timelineType="pinned"
|
{#each pinnedStatuses as status, index (status.id)}
|
||||||
timelineValue={accountId}
|
<Status {status}
|
||||||
{index}
|
timelineType="pinned"
|
||||||
length={pinnedStatuses.length}
|
timelineValue={accountId}
|
||||||
/>
|
{index}
|
||||||
{/each}
|
length={pinnedStatuses.length}
|
||||||
</div>
|
/>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<script>
|
<script>
|
||||||
import { store } from '../../_store/store'
|
import { store } from '../../_store/store'
|
||||||
import Status from '../status/Status.html'
|
import Status from '../status/Status.html'
|
||||||
|
|
|
@ -109,20 +109,20 @@
|
||||||
},
|
},
|
||||||
label: ({ timeline, $currentInstance, timelineType, timelineValue }) => {
|
label: ({ timeline, $currentInstance, timelineType, timelineValue }) => {
|
||||||
if (timelines[timeline]) {
|
if (timelines[timeline]) {
|
||||||
return `${timelines[timeline].label} timeline for ${$currentInstance}`
|
return `Statuses: ${timelines[timeline].label} timeline on ${$currentInstance}`
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (timelineType) {
|
switch (timelineType) {
|
||||||
case 'tag':
|
case 'tag':
|
||||||
return `#${timelineValue} timeline for ${$currentInstance}`
|
return `Statuses: #${timelineValue} hashtag`
|
||||||
case 'status':
|
case 'status':
|
||||||
return 'Status context'
|
return `Statuses: thread`
|
||||||
case 'account':
|
case 'account':
|
||||||
return `Account #${timelineValue} on ${$currentInstance}`
|
return `Statuses: account timeline`
|
||||||
case 'list':
|
case 'list':
|
||||||
return `List #${timelineValue} on ${$currentInstance}`
|
return `Statuses: list`
|
||||||
case 'notifications':
|
case 'notifications':
|
||||||
return `Notifications for ${$currentInstance}`
|
return `Notifications on ${$currentInstance}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
timelineType: ({ timeline }) => {
|
timelineType: ({ timeline }) => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{#if $isUserLoggedIn}
|
{#if $isUserLoggedIn}
|
||||||
<TimelinePage timeline="account/{params.accountId}">
|
<TimelinePage timeline="account/{params.accountId}">
|
||||||
<DynamicPageBanner title="" />
|
<DynamicPageBanner title="" ariaTitle="Profile page for {accountName}"/>
|
||||||
{#if $currentAccountProfile && $currentVerifyCredentials}
|
{#if $currentAccountProfile && $currentVerifyCredentials}
|
||||||
<AccountProfile account={$currentAccountProfile}
|
<AccountProfile account={$currentAccountProfile}
|
||||||
relationship={$currentAccountRelationship}
|
relationship={$currentAccountRelationship}
|
||||||
|
@ -42,6 +42,9 @@
|
||||||
},
|
},
|
||||||
shortProfileName: ({ $currentAccountProfile }) => {
|
shortProfileName: ({ $currentAccountProfile }) => {
|
||||||
return ($currentAccountProfile && ('@' + $currentAccountProfile.username)) || ''
|
return ($currentAccountProfile && ('@' + $currentAccountProfile.username)) || ''
|
||||||
|
},
|
||||||
|
accountName: ({ $currentAccountProfile }) => {
|
||||||
|
return ($currentAccountProfile && ($currentAccountProfile.display_name || $currentAccountProfile.username)) || ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{#if $isUserLoggedIn}
|
{#if $isUserLoggedIn}
|
||||||
<TimelinePage timeline="status/{params.statusId}">
|
<TimelinePage timeline="status/{params.statusId}">
|
||||||
<DynamicPageBanner title=""/>
|
<DynamicPageBanner title="" ariaTitle="Status thread page" />
|
||||||
</TimelinePage>
|
</TimelinePage>
|
||||||
{:else}
|
{:else}
|
||||||
<HiddenFromSSR>
|
<HiddenFromSSR>
|
||||||
|
|
Loading…
Reference in New Issue