fix: accessibility fixes (#236)
This commit is contained in:
@@ -6,6 +6,7 @@ module.exports = createConfig('eslint',
|
||||
"rules": {
|
||||
'import/no-extraneous-dependencies': 'off',
|
||||
'react-hooks/exhaustive-deps': 'off',
|
||||
'jsx-a11y/no-noninteractive-element-interactions': 'off',
|
||||
'simple-import-sort/imports': [
|
||||
'error', {
|
||||
groups: [
|
||||
|
||||
@@ -54,8 +54,7 @@ function LearnerPostsView({ intl }) {
|
||||
// Add a spacing after the group of pinned posts
|
||||
return (
|
||||
<React.Fragment key={post.id}>
|
||||
<div className="p-1 bg-light-400" />
|
||||
<PostLink post={post} key={post.id} isSelected={checkIsSelected} learnerTab />
|
||||
<PostLink post={post} key={post.id} isSelected={checkIsSelected} learnerTab showDivider />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,10 @@ const ActionItem = ({
|
||||
}) => (
|
||||
<label
|
||||
htmlFor={id}
|
||||
className="focus border-bottom-0 d-flex align-items-center w-100 py-2 m-0 font-weight-500"
|
||||
className="focus border-bottom-0 d-flex align-items-center w-100 py-2 m-0 font-weight-500 filter-menu"
|
||||
data-testid={value === selected ? 'selected' : null}
|
||||
style={{ cursor: 'pointer' }}
|
||||
aria-checked={value === selected}
|
||||
>
|
||||
<Icon src={Check} className={classNames('text-success mr-2', { invisible: value !== selected })} />
|
||||
<Form.Radio id={id} className="sr-only sr-only-focusable" value={value} tabIndex={0}>
|
||||
@@ -56,7 +58,6 @@ function LearnerFilterBar({
|
||||
if (name === 'sort') {
|
||||
dispatch(setSortedBy(value));
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -62,12 +62,11 @@ function PostsList({ posts, topics, intl }) {
|
||||
// Add a spacing after the group of pinned posts
|
||||
return (
|
||||
<React.Fragment key={post.id}>
|
||||
<div className="p-1 bg-light-400" />
|
||||
<PostLink post={post} key={post.id} isSelected={checkIsSelected} />
|
||||
<PostLink post={post} key={post.id} isSelected={checkIsSelected} showDivider idx={idx} />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
return (<PostLink post={post} key={post.id} isSelected={checkIsSelected} />);
|
||||
return (<PostLink post={post} key={post.id} isSelected={checkIsSelected} idx={idx} />);
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -59,13 +59,27 @@ function PostsView() {
|
||||
postsListComponent = <AllPostsList />;
|
||||
}
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
const { key } = event;
|
||||
if (key !== 'ArrowDown' && key !== 'ArrowUp') { return; }
|
||||
const option = event.target;
|
||||
|
||||
let selectedOption;
|
||||
if (key === 'ArrowDown') { selectedOption = option.nextElementSibling; }
|
||||
if (key === 'ArrowUp') { selectedOption = option.previousElementSibling; }
|
||||
|
||||
if (selectedOption) {
|
||||
selectedOption.focus();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="discussion-posts d-flex flex-column">
|
||||
{
|
||||
searchString && <SearchInfo count={resultsFound} text={searchString} onClear={() => dispatch(setSearchQuery(''))} />
|
||||
}
|
||||
<PostFilterBar filterSelfPosts={showOwnPosts} />
|
||||
<div className="list-group list-group-flush" role="list">
|
||||
<div className="list-group list-group-flush" role="list" onKeyDown={e => handleKeyDown(e)}>
|
||||
{postsListComponent}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,8 +33,10 @@ const ActionItem = ({
|
||||
}) => (
|
||||
<label
|
||||
htmlFor={id}
|
||||
className="focus border-bottom-0 d-flex align-items-center w-100 py-2 m-0 font-weight-500"
|
||||
className="focus border-bottom-0 d-flex align-items-center w-100 py-2 m-0 font-weight-500 filter-menu"
|
||||
data-testid={value === selected ? 'selected' : null}
|
||||
style={{ cursor: 'pointer' }}
|
||||
aria-checked={value === selected}
|
||||
>
|
||||
<Icon src={Check} className={classNames('text-success mr-2', { invisible: value !== selected })} />
|
||||
<Form.Radio id={id} className="sr-only sr-only-focusable" value={value} tabIndex={0}>
|
||||
@@ -101,7 +103,6 @@ function PostFilterBar({
|
||||
if (name === 'cohort') {
|
||||
dispatch(setCohortFilter(value));
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -22,6 +22,8 @@ function PostLink({
|
||||
isSelected,
|
||||
intl,
|
||||
learnerTab,
|
||||
showDivider,
|
||||
idx,
|
||||
}) {
|
||||
const {
|
||||
page,
|
||||
@@ -41,20 +43,24 @@ function PostLink({
|
||||
const showAnsweredBadge = post.hasEndorsed && post.type === ThreadType.QUESTION;
|
||||
const authorLabelColor = AvatarOutlineAndLabelColors[post.authorLabel];
|
||||
const postReported = post.abuseFlagged || post.abuseFlaggedCount;
|
||||
|
||||
return (
|
||||
|
||||
<Link
|
||||
className="discussion-post list-group-item list-group-item-action p-0 text-decoration-none text-gray-900"
|
||||
to={linkUrl}
|
||||
aria-current={isSelected(post.id) ? 'page' : undefined}
|
||||
onClick={() => isSelected(post.id)}
|
||||
style={{ lineHeight: '21px' }}
|
||||
role="listitem"
|
||||
aria-current={isSelected(post.id) ? 'page' : undefined}
|
||||
role="option"
|
||||
tabindex={(isSelected(post.id) || idx === 0) ? 0 : -1}
|
||||
>
|
||||
{showDivider && <div className="p-1 bg-light-400" /> }
|
||||
<div
|
||||
className={
|
||||
classNames('d-flex flex-row pt-2.5 pb-2 px-4 border-primary-500',
|
||||
{ 'bg-light-300': post.read })
|
||||
}
|
||||
classNames('d-flex flex-row pt-2.5 pb-2 px-4 border-primary-500',
|
||||
{ 'bg-light-300': post.read })
|
||||
}
|
||||
style={post.id === postId ? {
|
||||
borderRightWidth: '4px',
|
||||
borderRightStyle: 'solid',
|
||||
@@ -66,33 +72,33 @@ function PostLink({
|
||||
<div className="d-flex align-items-center pb-0 mb-0 flex-fill font-weight-500">
|
||||
<div
|
||||
className={
|
||||
classNames('text-truncate font-weight-500 font-size-14 text-primary-500 font-style-normal font-family-inter',
|
||||
{ 'font-weight-bolder': !post.read })
|
||||
classNames('text-truncate font-weight-500 font-size-14 text-primary-500 font-style-normal font-family-inter',
|
||||
{ 'font-weight-bolder': !post.read })
|
||||
}
|
||||
>
|
||||
{post.title}
|
||||
</div>
|
||||
|
||||
{showAnsweredBadge && (
|
||||
<Badge variant="success" className="font-weight-500 ml-auto badge-padding">
|
||||
{intl.formatMessage(messages.answered)}
|
||||
<span className="sr-only">{' '}answered</span>
|
||||
</Badge>
|
||||
<Badge variant="success" className="font-weight-500 ml-auto badge-padding">
|
||||
{intl.formatMessage(messages.answered)}
|
||||
<span className="sr-only">{' '}answered</span>
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
{postReported && (
|
||||
<Badge
|
||||
variant="danger"
|
||||
data-testid="reported-post"
|
||||
className={`font-weight-500 badge-padding ${showAnsweredBadge ? 'ml-2' : 'ml-auto'}`}
|
||||
>
|
||||
{intl.formatMessage(messages.contentReported)}
|
||||
<span className="sr-only">{' '}reported</span>
|
||||
</Badge>
|
||||
<Badge
|
||||
variant="danger"
|
||||
data-testid="reported-post"
|
||||
className={`font-weight-500 badge-padding ${showAnsweredBadge ? 'ml-2' : 'ml-auto'}`}
|
||||
>
|
||||
{intl.formatMessage(messages.contentReported)}
|
||||
<span className="sr-only">{' '}reported</span>
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
{post.pinned && (
|
||||
<Icon src={PushPin} className={`icon-size ${postReported || showAnsweredBadge ? 'ml-2' : 'ml-auto'}`} />
|
||||
<Icon src={PushPin} className={`icon-size ${postReported || showAnsweredBadge ? 'ml-2' : 'ml-auto'}`} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -124,10 +130,14 @@ PostLink.propTypes = {
|
||||
isSelected: PropTypes.func.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
learnerTab: PropTypes.bool,
|
||||
showDivider: PropTypes.bool,
|
||||
idx: PropTypes.number,
|
||||
};
|
||||
|
||||
PostLink.defaultProps = {
|
||||
learnerTab: false,
|
||||
showDivider: false,
|
||||
idx: -1,
|
||||
};
|
||||
|
||||
export default injectIntl(PostLink);
|
||||
|
||||
@@ -126,3 +126,7 @@ header nav.nav.secondary-menu-container {
|
||||
.sidebar-XL-width {
|
||||
min-width: 29rem;
|
||||
}
|
||||
|
||||
.filter-menu:focus-within {
|
||||
background-color: #e9e6e4 !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user