about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch
diff options
context:
space:
mode:
authorDavid Yip <yipdw@member.fsf.org>2018-09-29 19:01:19 -0500
committerGitHub <noreply@github.com>2018-09-29 19:01:19 -0500
commitc065717b6765435e7374975ae9d71ebaa224f92c (patch)
tree603dc9c3b9def7b7a079f9403d3b5f9cc2d507ea /app/javascript/flavours/glitch
parent2bb3c8c9446dd8cd47e0e0b4d9e899b8a5a546f2 (diff)
parent530da545a532d7e3cbcc5168e97410bd86d92117 (diff)
Merge pull request #681 from ThibG/glitch-soc/fixes/accessibility
Port various accessibility improvements from upstream
Diffstat (limited to 'app/javascript/flavours/glitch')
-rw-r--r--app/javascript/flavours/glitch/components/column.js5
-rw-r--r--app/javascript/flavours/glitch/components/intersection_observer_article.js4
-rw-r--r--app/javascript/flavours/glitch/components/status.js29
-rw-r--r--app/javascript/flavours/glitch/features/community_timeline/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/direct_timeline/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/drawer/index.js8
-rw-r--r--app/javascript/flavours/glitch/features/favourited_statuses/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/getting_started/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/hashtag_timeline/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/home_timeline/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/list_timeline/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/notifications/index.js1
-rw-r--r--app/javascript/flavours/glitch/features/public_timeline/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/standalone/community_timeline/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/standalone/public_timeline/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/status/index.js6
16 files changed, 56 insertions, 18 deletions
diff --git a/app/javascript/flavours/glitch/components/column.js b/app/javascript/flavours/glitch/components/column.js
index 57c4c7a40..dc87818a5 100644
--- a/app/javascript/flavours/glitch/components/column.js
+++ b/app/javascript/flavours/glitch/components/column.js
@@ -9,6 +9,7 @@ export default class Column extends React.PureComponent {
     children: PropTypes.node,
     extraClasses: PropTypes.string,
     name: PropTypes.string,
+    label: PropTypes.string,
   };
 
   scrollTop () {
@@ -42,10 +43,10 @@ export default class Column extends React.PureComponent {
   }
 
   render () {
-    const { children, extraClasses, name } = this.props;
+    const { children, extraClasses, name, label } = this.props;
 
     return (
-      <div role='region' data-column={name} className={`column ${extraClasses || ''}`} ref={this.setRef}>
+      <div role='region' aria-label={label} data-column={name} className={`column ${extraClasses || ''}`} ref={this.setRef}>
         {children}
       </div>
     );
diff --git a/app/javascript/flavours/glitch/components/intersection_observer_article.js b/app/javascript/flavours/glitch/components/intersection_observer_article.js
index f7f6b0a53..6eeca5598 100644
--- a/app/javascript/flavours/glitch/components/intersection_observer_article.js
+++ b/app/javascript/flavours/glitch/components/intersection_observer_article.js
@@ -107,7 +107,7 @@ export default class IntersectionObserverArticle extends ImmutablePureComponent
       return (
         <article
           ref={this.handleRef}
-          aria-posinset={index}
+          aria-posinset={index + 1}
           aria-setsize={listLength}
           style={{ height: `${this.height || cachedHeight}px`, opacity: 0, overflow: 'hidden' }}
           data-id={id}
@@ -119,7 +119,7 @@ export default class IntersectionObserverArticle extends ImmutablePureComponent
     }
 
     return (
-      <article ref={this.handleRef} aria-posinset={index} aria-setsize={listLength} data-id={id} tabIndex='0'>
+      <article ref={this.handleRef} aria-posinset={index + 1} aria-setsize={listLength} data-id={id} tabIndex='0'>
         {children && React.cloneElement(children, { hidden: false })}
       </article>
     );
diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js
index f3709f653..4d47660c2 100644
--- a/app/javascript/flavours/glitch/components/status.js
+++ b/app/javascript/flavours/glitch/components/status.js
@@ -7,7 +7,7 @@ import StatusIcons from './status_icons';
 import StatusContent from './status_content';
 import StatusActionBar from './status_action_bar';
 import AttachmentList from './attachment_list';
-import { FormattedMessage } from 'react-intl';
+import { injectIntl, FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import { MediaGallery, Video } from 'flavours/glitch/util/async-components';
 import { HotKeys } from 'react-hotkeys';
@@ -19,6 +19,24 @@ import { autoUnfoldCW } from 'flavours/glitch/util/content_warning';
 // to use the progress bar to show download progress
 import Bundle from '../features/ui/components/bundle';
 
+export const textForScreenReader = (intl, status, rebloggedByText = false, expanded = false) => {
+  const displayName = status.getIn(['account', 'display_name']);
+
+  const values = [
+    displayName.length === 0 ? status.getIn(['account', 'acct']).split('@')[0] : displayName,
+    status.get('spoiler_text') && !expanded ? status.get('spoiler_text') : status.get('search_index').slice(status.get('spoiler_text').length),
+    intl.formatDate(status.get('created_at'), { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' }),
+    status.getIn(['account', 'acct']),
+  ];
+
+  if (rebloggedByText) {
+    values.push(rebloggedByText);
+  }
+
+  return values.join(', ');
+};
+
+@injectIntl
 export default class Status extends ImmutablePureComponent {
 
   static contextTypes = {
@@ -52,6 +70,7 @@ export default class Status extends ImmutablePureComponent {
     getScrollPosition: PropTypes.func,
     updateScrollBottom: PropTypes.func,
     expanded: PropTypes.bool,
+    intl: PropTypes.object.isRequired,
   };
 
   state = {
@@ -337,6 +356,7 @@ export default class Status extends ImmutablePureComponent {
     } = this;
     const { router } = this.context;
     const {
+      intl,
       status,
       account,
       settings,
@@ -474,6 +494,12 @@ export default class Status extends ImmutablePureComponent {
       selectorAttribs[`data-${notifKind}-by`] = `@${account.get('acct')}`;
     }
 
+    let rebloggedByText;
+
+    if (prepend === 'reblog') {
+      rebloggedByText = intl.formatMessage({ id: 'status.reblogged_by', defaultMessage: '{name} boosted' }, { name: account.get('acct') });
+    }
+
     const handlers = {
       reply: this.handleHotkeyReply,
       favourite: this.handleHotkeyFavourite,
@@ -502,6 +528,7 @@ export default class Status extends ImmutablePureComponent {
           ref={handleRef}
           tabIndex='0'
           data-featured={featured ? 'true' : null}
+          aria-label={textForScreenReader(intl, status, rebloggedByText, !status.get('hidden'))}
         >
           <header className='status__info'>
             <span>
diff --git a/app/javascript/flavours/glitch/features/community_timeline/index.js b/app/javascript/flavours/glitch/features/community_timeline/index.js
index b5843ca16..ddcca2dc0 100644
--- a/app/javascript/flavours/glitch/features/community_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/community_timeline/index.js
@@ -76,7 +76,7 @@ export default class CommunityTimeline extends React.PureComponent {
     const pinned = !!columnId;
 
     return (
-      <Column ref={this.setRef} name='local'>
+      <Column ref={this.setRef} name='local' label={intl.formatMessage(messages.title)}>
         <ColumnHeader
           icon='users'
           active={hasUnread}
diff --git a/app/javascript/flavours/glitch/features/direct_timeline/index.js b/app/javascript/flavours/glitch/features/direct_timeline/index.js
index 418db7c79..dc7e0534d 100644
--- a/app/javascript/flavours/glitch/features/direct_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/direct_timeline/index.js
@@ -76,7 +76,7 @@ export default class DirectTimeline extends React.PureComponent {
     const pinned = !!columnId;
 
     return (
-      <Column ref={this.setRef}>
+      <Column ref={this.setRef} label={intl.formatMessage(messages.title)}>
         <ColumnHeader
           icon='envelope'
           active={hasUnread}
diff --git a/app/javascript/flavours/glitch/features/drawer/index.js b/app/javascript/flavours/glitch/features/drawer/index.js
index 72b36fcae..038a2513e 100644
--- a/app/javascript/flavours/glitch/features/drawer/index.js
+++ b/app/javascript/flavours/glitch/features/drawer/index.js
@@ -2,6 +2,7 @@
 import PropTypes from 'prop-types';
 import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
+import { defineMessages } from 'react-intl';
 import classNames from 'classnames';
 
 //  Actions.
@@ -25,6 +26,11 @@ import DrawerSearch from './search';
 import { me } from 'flavours/glitch/util/initial_state';
 import { wrap } from 'flavours/glitch/util/redux_helpers';
 
+//  Messages.
+const messages = defineMessages({
+  compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new toot' },
+});
+
 //  State mapping.
 const mapStateToProps = state => ({
   account: state.getIn(['accounts', me]),
@@ -96,7 +102,7 @@ class Drawer extends React.Component {
 
     //  The result.
     return (
-      <div className={computedClass}>
+      <div className={computedClass} role='region' aria-label={intl.formatMessage(messages.compose)}>
         {multiColumn ? (
           <DrawerHeader
             columns={columns}
diff --git a/app/javascript/flavours/glitch/features/favourited_statuses/index.js b/app/javascript/flavours/glitch/features/favourited_statuses/index.js
index d8fa1b84e..32bf4e71a 100644
--- a/app/javascript/flavours/glitch/features/favourited_statuses/index.js
+++ b/app/javascript/flavours/glitch/features/favourited_statuses/index.js
@@ -71,7 +71,7 @@ export default class Favourites extends ImmutablePureComponent {
     const pinned = !!columnId;
 
     return (
-      <Column ref={this.setRef} name='favourites'>
+      <Column ref={this.setRef} name='favourites' label={intl.formatMessage(messages.heading)}>
         <ColumnHeader
           icon='star'
           title={intl.formatMessage(messages.heading)}
diff --git a/app/javascript/flavours/glitch/features/getting_started/index.js b/app/javascript/flavours/glitch/features/getting_started/index.js
index fb2e92278..09dcbe716 100644
--- a/app/javascript/flavours/glitch/features/getting_started/index.js
+++ b/app/javascript/flavours/glitch/features/getting_started/index.js
@@ -33,6 +33,7 @@ const messages = defineMessages({
   lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
   lists_subheading: { id: 'column_subheading.lists', defaultMessage: 'Lists' },
   misc: { id: 'navigation_bar.misc', defaultMessage: 'Misc' },
+  menu: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
 });
 
 const makeMapStateToProps = () => {
@@ -148,7 +149,7 @@ export default class GettingStarted extends ImmutablePureComponent {
     ]);
 
     return (
-      <Column name='getting-started' icon='asterisk' heading={intl.formatMessage(messages.heading)} hideHeadingOnMobile>
+      <Column name='getting-started' icon='asterisk' heading={intl.formatMessage(messages.heading)} label={intl.formatMessage(messages.menu)} hideHeadingOnMobile>
         <div className='scrollable optionally-scrollable'>
           <div className='getting-started__wrapper'>
             <ColumnSubheading text={intl.formatMessage(messages.navigation_subheading)} />
diff --git a/app/javascript/flavours/glitch/features/hashtag_timeline/index.js b/app/javascript/flavours/glitch/features/hashtag_timeline/index.js
index 8f77ed42b..311fabb63 100644
--- a/app/javascript/flavours/glitch/features/hashtag_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/hashtag_timeline/index.js
@@ -88,7 +88,7 @@ export default class HashtagTimeline extends React.PureComponent {
     const pinned = !!columnId;
 
     return (
-      <Column ref={this.setRef} name='hashtag'>
+      <Column ref={this.setRef} name='hashtag' label={`#${id}`}>
         <ColumnHeader
           icon='hashtag'
           active={hasUnread}
diff --git a/app/javascript/flavours/glitch/features/home_timeline/index.js b/app/javascript/flavours/glitch/features/home_timeline/index.js
index 3650ffc6d..7d124ba01 100644
--- a/app/javascript/flavours/glitch/features/home_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/home_timeline/index.js
@@ -97,7 +97,7 @@ export default class HomeTimeline extends React.PureComponent {
     const pinned = !!columnId;
 
     return (
-      <Column ref={this.setRef} name='home'>
+      <Column ref={this.setRef} name='home' label={intl.formatMessage(messages.title)}>
         <ColumnHeader
           icon='home'
           active={hasUnread}
diff --git a/app/javascript/flavours/glitch/features/list_timeline/index.js b/app/javascript/flavours/glitch/features/list_timeline/index.js
index 07edf45aa..2e77ba235 100644
--- a/app/javascript/flavours/glitch/features/list_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/list_timeline/index.js
@@ -136,7 +136,7 @@ export default class ListTimeline extends React.PureComponent {
     }
 
     return (
-      <Column ref={this.setRef}>
+      <Column ref={this.setRef} label={title}>
         <ColumnHeader
           icon='list-ul'
           active={hasUnread}
diff --git a/app/javascript/flavours/glitch/features/notifications/index.js b/app/javascript/flavours/glitch/features/notifications/index.js
index ee711bd8a..13ed26865 100644
--- a/app/javascript/flavours/glitch/features/notifications/index.js
+++ b/app/javascript/flavours/glitch/features/notifications/index.js
@@ -203,6 +203,7 @@ export default class Notifications extends React.PureComponent {
         ref={this.setColumnRef}
         name='notifications'
         extraClasses={this.props.notifCleaningActive ? 'notif-cleaning' : null}
+        label={intl.formatMessage(messages.title)}
       >
         <ColumnHeader
           icon='bell'
diff --git a/app/javascript/flavours/glitch/features/public_timeline/index.js b/app/javascript/flavours/glitch/features/public_timeline/index.js
index a6c0b1688..53f2836f1 100644
--- a/app/javascript/flavours/glitch/features/public_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/public_timeline/index.js
@@ -76,7 +76,7 @@ export default class PublicTimeline extends React.PureComponent {
     const pinned = !!columnId;
 
     return (
-      <Column ref={this.setRef} name='federated'>
+      <Column ref={this.setRef} name='federated' label={intl.formatMessage(messages.title)}>
         <ColumnHeader
           icon='globe'
           active={hasUnread}
diff --git a/app/javascript/flavours/glitch/features/standalone/community_timeline/index.js b/app/javascript/flavours/glitch/features/standalone/community_timeline/index.js
index c488f9541..2b67e836a 100644
--- a/app/javascript/flavours/glitch/features/standalone/community_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/standalone/community_timeline/index.js
@@ -51,7 +51,7 @@ export default class CommunityTimeline extends React.PureComponent {
     const { intl } = this.props;
 
     return (
-      <Column ref={this.setRef}>
+      <Column ref={this.setRef} label={intl.formatMessage(messages.title)}>
         <ColumnHeader
           icon='users'
           title={intl.formatMessage(messages.title)}
diff --git a/app/javascript/flavours/glitch/features/standalone/public_timeline/index.js b/app/javascript/flavours/glitch/features/standalone/public_timeline/index.js
index 0b4238485..907da3992 100644
--- a/app/javascript/flavours/glitch/features/standalone/public_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/standalone/public_timeline/index.js
@@ -51,7 +51,7 @@ export default class PublicTimeline extends React.PureComponent {
     const { intl } = this.props;
 
     return (
-      <Column ref={this.setRef}>
+      <Column ref={this.setRef} label={intl.formatMessage(messages.title)}>
         <ColumnHeader
           icon='globe'
           title={intl.formatMessage(messages.title)}
diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js
index 33a7bd075..5759a575c 100644
--- a/app/javascript/flavours/glitch/features/status/index.js
+++ b/app/javascript/flavours/glitch/features/status/index.js
@@ -39,6 +39,7 @@ import { HotKeys } from 'react-hotkeys';
 import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/util/initial_state';
 import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from 'flavours/glitch/util/fullscreen';
 import { autoUnfoldCW } from 'flavours/glitch/util/content_warning';
+import { textForScreenReader } from 'flavours/glitch/components/status';
 
 const messages = defineMessages({
   deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
@@ -48,6 +49,7 @@ const messages = defineMessages({
   blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
   revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
   hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' },
+  detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' },
 });
 
 const makeMapStateToProps = () => {
@@ -387,7 +389,7 @@ export default class Status extends ImmutablePureComponent {
     };
 
     return (
-      <Column>
+      <Column label={intl.formatMessage(messages.detailedStatus)}>
         <ColumnHeader
           showBackButton
           extraButton={(
@@ -400,7 +402,7 @@ export default class Status extends ImmutablePureComponent {
             {ancestors}
 
             <HotKeys handlers={handlers}>
-              <div className='focusable' tabIndex='0'>
+              <div className='focusable' tabIndex='0' aria-label={textForScreenReader(intl, status, false, !status.get('hidden'))}>
                 <DetailedStatus
                   status={status}
                   settings={settings}