diff options
author | David Yip <yipdw@member.fsf.org> | 2018-09-29 19:01:19 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-29 19:01:19 -0500 |
commit | c065717b6765435e7374975ae9d71ebaa224f92c (patch) | |
tree | 603dc9c3b9def7b7a079f9403d3b5f9cc2d507ea /app/javascript/flavours/glitch | |
parent | 2bb3c8c9446dd8cd47e0e0b4d9e899b8a5a546f2 (diff) | |
parent | 530da545a532d7e3cbcc5168e97410bd86d92117 (diff) |
Merge pull request #681 from ThibG/glitch-soc/fixes/accessibility
Port various accessibility improvements from upstream
Diffstat (limited to 'app/javascript/flavours/glitch')
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} |