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
					
				
					 13 changed files with 62 additions and 28 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		
		Reference in a new issue