Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[A11Y] Improve accessibility for discussion reply count on post stream #3090

Merged
merged 14 commits into from
Oct 27, 2021
75 changes: 45 additions & 30 deletions js/src/forum/components/DiscussionListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import TerminalPost from './TerminalPost';
import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
import DiscussionControls from '../utils/DiscussionControls';
import slidable from '../utils/slidable';
import extractText from '../../common/utils/extractText';
import classList from '../../common/utils/classList';
import DiscussionPage from './DiscussionPage';
import escapeRegExp from '../../common/utils/escapeRegExp';
Expand Down Expand Up @@ -50,12 +49,11 @@ export default class DiscussionListItem extends Component {

elementAttrs() {
return {
className: classList([
'DiscussionListItem',
this.active() ? 'active' : '',
this.attrs.discussion.isHidden() ? 'DiscussionListItem--hidden' : '',
'ontouchstart' in window ? 'Slidable' : '',
]),
className: classList('DiscussionListItem', {
active: this.active(),
'DiscussionListItem--hidden': this.attrs.discussion.isHidden(),
Slidable: 'ontouchstart' in window,
}),
};
}

Expand All @@ -64,7 +62,7 @@ export default class DiscussionListItem extends Component {
const user = discussion.user();
const isUnread = discussion.isUnread();
const isRead = discussion.isRead();
const showUnread = !this.showRepliesCount() && isUnread;

let jumpTo = 0;
const controls = DiscussionControls.controls(discussion, this).toArray();
const attrs = this.elementAttrs();
Expand All @@ -83,17 +81,16 @@ export default class DiscussionListItem extends Component {

return (
<div {...attrs}>
{controls.length
? Dropdown.component(
{
icon: 'fas fa-ellipsis-v',
className: 'DiscussionListItem-controls',
buttonClassName: 'Button Button--icon Button--flat Slidable-underneath Slidable-underneath--right',
accessibleToggleLabel: app.translator.trans('core.forum.discussion_controls.toggle_dropdown_accessible_label'),
},
controls
)
: ''}
{controls.length > 0 &&
Dropdown.component(
{
icon: 'fas fa-ellipsis-v',
className: 'DiscussionListItem-controls',
buttonClassName: 'Button Button--icon Button--flat Slidable-underneath Slidable-underneath--right',
accessibleToggleLabel: app.translator.trans('core.forum.discussion_controls.toggle_dropdown_accessible_label'),
},
controls
)}

<span
className={'Slidable-underneath Slidable-underneath--left Slidable-underneath--elastic' + (isUnread ? '' : ' disabled')}
Expand All @@ -102,7 +99,7 @@ export default class DiscussionListItem extends Component {
{icon('fas fa-check')}
</span>

<div className={'DiscussionListItem-content Slidable-content' + (isUnread ? ' unread' : '') + (isRead ? ' read' : '')}>
<div className={classList('DiscussionListItem-content', 'Slidable-content', { unread: isUnread, read: isRead })}>
<Tooltip
text={app.translator.trans('core.forum.discussion_list.started_text', { user, ago: humanTime(discussion.createdAt()) })}
position="right"
Expand All @@ -118,16 +115,7 @@ export default class DiscussionListItem extends Component {
<h3 className="DiscussionListItem-title">{highlight(discussion.title(), this.highlightRegExp)}</h3>
<ul className="DiscussionListItem-info">{listItems(this.infoItems().toArray())}</ul>
</Link>

<span
tabindex="0"
role="button"
className="DiscussionListItem-count"
onclick={this.markAsRead.bind(this)}
title={showUnread ? app.translator.trans('core.forum.discussion_list.mark_as_read_tooltip') : ''}
>
{abbreviateNumber(discussion[showUnread ? 'unreadCount' : 'replyCount']())}
</span>
{this.replyCountItem()}
</div>
</div>
);
Expand Down Expand Up @@ -222,4 +210,31 @@ export default class DiscussionListItem extends Component {

return items;
}

replyCountItem() {
const discussion = this.attrs.discussion;
const showUnread = !this.showRepliesCount() && discussion.isUnread();

if (showUnread) {
return (
<button className="Button--ua-reset DiscussionListItem-count" onclick={this.markAsRead.bind(this)}>
<span aria-hidden="true">{abbreviateNumber(discussion.unreadCount())}</span>

<span class="visually-hidden">
{app.translator.trans('core.forum.discussion_list.unread_replies_a11y_label', { count: discussion.replyCount() })}
</span>
</button>
);
}

return (
<span className="DiscussionListItem-count">
<span aria-hidden="true">{abbreviateNumber(discussion.replyCount())}</span>

<span class="visually-hidden">
{app.translator.trans('core.forum.discussion_list.total_replies_a11y_label', { count: discussion.replyCount() })}
</span>
</span>
);
}
}
33 changes: 33 additions & 0 deletions less/common/Button.less
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,36 @@
font-weight: bold;
margin-left: 10px;
}

// Remove all user-agent styles from the Button
.Button--ua-reset {
border: none;
margin: 0;
padding: 0;
width: auto;
overflow: visible;
text-align: inherit;
vertical-align: inherit;

background: transparent;

/* inherit font & color from ancestor */
color: inherit;
font: inherit;

/* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */
line-height: normal;

/* Corrects font smoothing for webkit */
-webkit-font-smoothing: inherit;
-moz-osx-font-smoothing: inherit;

/* Corrects inability to style clickable `input` types in iOS */
-webkit-appearance: none;
appearance: none;

&::-moz-focus-inner {
border: 0;
padding: 0;
}
}
3 changes: 2 additions & 1 deletion locale/core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,10 @@ core:
discussion_list:
empty_text: It looks as though there are no discussions here.
load_more_button: => core.ref.load_more
mark_as_read_tooltip: Mark as Read
replied_text: "{username} replied {ago}"
started_text: "{username} started {ago}"
total_replies_a11y_label: "{count, plural, one {# reply} other {# replies}}"
unread_replies_a11y_label: "{count, plural, one {# unread reply} other {# unread replies}}. Mark unread {count, plural, one {reply} other {replies}} as read."

# These translations are used in the Forgot Password modal dialog.
forgot_password:
Expand Down