mirror of
https://github.com/flarum/core.git
synced 2025-08-01 14:10:37 +02:00
[A11Y] Improve accessibility for discussion reply count on post stream (#3090)
* Add class to remove all UA styles from a button * Improve classList utilisation * Simplify JSX * Use classlist instead of concatenation * Fix reply count focusable when not acting as a button * Add SR only class * Add new reply count translations * Use cleaner translations * Remove unused import * Add missing new line * Delete Accessibility.less * Use existing `.visually-hidden` class * Format * Fix locale formatting
This commit is contained in:
@@ -13,7 +13,6 @@ import TerminalPost from './TerminalPost';
|
|||||||
import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
|
import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
|
||||||
import DiscussionControls from '../utils/DiscussionControls';
|
import DiscussionControls from '../utils/DiscussionControls';
|
||||||
import slidable from '../utils/slidable';
|
import slidable from '../utils/slidable';
|
||||||
import extractText from '../../common/utils/extractText';
|
|
||||||
import classList from '../../common/utils/classList';
|
import classList from '../../common/utils/classList';
|
||||||
import DiscussionPage from './DiscussionPage';
|
import DiscussionPage from './DiscussionPage';
|
||||||
import escapeRegExp from '../../common/utils/escapeRegExp';
|
import escapeRegExp from '../../common/utils/escapeRegExp';
|
||||||
@@ -50,12 +49,11 @@ export default class DiscussionListItem extends Component {
|
|||||||
|
|
||||||
elementAttrs() {
|
elementAttrs() {
|
||||||
return {
|
return {
|
||||||
className: classList([
|
className: classList('DiscussionListItem', {
|
||||||
'DiscussionListItem',
|
active: this.active(),
|
||||||
this.active() ? 'active' : '',
|
'DiscussionListItem--hidden': this.attrs.discussion.isHidden(),
|
||||||
this.attrs.discussion.isHidden() ? 'DiscussionListItem--hidden' : '',
|
Slidable: 'ontouchstart' in window,
|
||||||
'ontouchstart' in window ? 'Slidable' : '',
|
}),
|
||||||
]),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +62,7 @@ export default class DiscussionListItem extends Component {
|
|||||||
const user = discussion.user();
|
const user = discussion.user();
|
||||||
const isUnread = discussion.isUnread();
|
const isUnread = discussion.isUnread();
|
||||||
const isRead = discussion.isRead();
|
const isRead = discussion.isRead();
|
||||||
const showUnread = !this.showRepliesCount() && isUnread;
|
|
||||||
let jumpTo = 0;
|
let jumpTo = 0;
|
||||||
const controls = DiscussionControls.controls(discussion, this).toArray();
|
const controls = DiscussionControls.controls(discussion, this).toArray();
|
||||||
const attrs = this.elementAttrs();
|
const attrs = this.elementAttrs();
|
||||||
@@ -83,17 +81,16 @@ export default class DiscussionListItem extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...attrs}>
|
<div {...attrs}>
|
||||||
{controls.length
|
{controls.length > 0 &&
|
||||||
? Dropdown.component(
|
Dropdown.component(
|
||||||
{
|
{
|
||||||
icon: 'fas fa-ellipsis-v',
|
icon: 'fas fa-ellipsis-v',
|
||||||
className: 'DiscussionListItem-controls',
|
className: 'DiscussionListItem-controls',
|
||||||
buttonClassName: 'Button Button--icon Button--flat Slidable-underneath Slidable-underneath--right',
|
buttonClassName: 'Button Button--icon Button--flat Slidable-underneath Slidable-underneath--right',
|
||||||
accessibleToggleLabel: app.translator.trans('core.forum.discussion_controls.toggle_dropdown_accessible_label'),
|
accessibleToggleLabel: app.translator.trans('core.forum.discussion_controls.toggle_dropdown_accessible_label'),
|
||||||
},
|
},
|
||||||
controls
|
controls
|
||||||
)
|
)}
|
||||||
: ''}
|
|
||||||
|
|
||||||
<span
|
<span
|
||||||
className={'Slidable-underneath Slidable-underneath--left Slidable-underneath--elastic' + (isUnread ? '' : ' disabled')}
|
className={'Slidable-underneath Slidable-underneath--left Slidable-underneath--elastic' + (isUnread ? '' : ' disabled')}
|
||||||
@@ -102,7 +99,7 @@ export default class DiscussionListItem extends Component {
|
|||||||
{icon('fas fa-check')}
|
{icon('fas fa-check')}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div className={'DiscussionListItem-content Slidable-content' + (isUnread ? ' unread' : '') + (isRead ? ' read' : '')}>
|
<div className={classList('DiscussionListItem-content', 'Slidable-content', { unread: isUnread, read: isRead })}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
text={app.translator.trans('core.forum.discussion_list.started_text', { user, ago: humanTime(discussion.createdAt()) })}
|
text={app.translator.trans('core.forum.discussion_list.started_text', { user, ago: humanTime(discussion.createdAt()) })}
|
||||||
position="right"
|
position="right"
|
||||||
@@ -118,16 +115,7 @@ export default class DiscussionListItem extends Component {
|
|||||||
<h3 className="DiscussionListItem-title">{highlight(discussion.title(), this.highlightRegExp)}</h3>
|
<h3 className="DiscussionListItem-title">{highlight(discussion.title(), this.highlightRegExp)}</h3>
|
||||||
<ul className="DiscussionListItem-info">{listItems(this.infoItems().toArray())}</ul>
|
<ul className="DiscussionListItem-info">{listItems(this.infoItems().toArray())}</ul>
|
||||||
</Link>
|
</Link>
|
||||||
|
{this.replyCountItem()}
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -222,4 +210,31 @@ export default class DiscussionListItem extends Component {
|
|||||||
|
|
||||||
return items;
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -231,3 +231,36 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-left: 10px;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -326,9 +326,10 @@ core:
|
|||||||
discussion_list:
|
discussion_list:
|
||||||
empty_text: It looks as though there are no discussions here.
|
empty_text: It looks as though there are no discussions here.
|
||||||
load_more_button: => core.ref.load_more
|
load_more_button: => core.ref.load_more
|
||||||
mark_as_read_tooltip: Mark as Read
|
|
||||||
replied_text: "{username} replied {ago}"
|
replied_text: "{username} replied {ago}"
|
||||||
started_text: "{username} started {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.
|
# These translations are used in the Forgot Password modal dialog.
|
||||||
forgot_password:
|
forgot_password:
|
||||||
|
Reference in New Issue
Block a user