Convert Connect settings menu div to nav (#12578)

* Fix typo in alt text

* Convert unsemantic div into nav

* Remove commented CSS

* Refactor connect config menu to be more usable

* Remove unused prop

* Return focus to button when config menu collapses

* Fix aria-label

* Add aria-expanded and fix aria-label text

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>

* Add transparent background-color to config menu button

Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
This commit is contained in:
Jacob Herrington 2021-02-08 14:56:35 -06:00 committed by GitHub
parent 9bbc738dc3
commit 2c0bbe317b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 33 deletions

View file

@ -12,14 +12,11 @@
}
.live-chat {
/* height: calc(100vh - 56px); */
&.live-chat--iossafari {
height: calc(100vh - 56px);
}
overflow-y: hidden;
/* height: calc(100 * var(--vh) - var(--header-height)); */
}
.live-chat {
@ -552,8 +549,17 @@
font-weight: bold;
cursor: pointer;
img {
button {
opacity: 0.6;
border: none;
height: 18px;
width: 18px;
background-size: cover;
background-color: transparent;
}
ul {
padding: 12px 10px;
}
&:hover {
@ -564,10 +570,8 @@
}
.chatchannels__configmenu {
display: none;
position: absolute;
bottom: 42px;
padding: 12px 10px;
min-width: 150px;
left: 0;
right: 0;
@ -575,10 +579,13 @@
border-top: 1px solid $light-medium-gray;
font-size: 13px;
a {
color: $dark-gray;
display: block;
padding: 5px 0px;
li {
list-style: none;
a {
color: $dark-gray;
display: block;
padding: 5px 0px;
}
}
}

View file

@ -1,5 +1,5 @@
import { h } from 'preact';
import { render } from '@testing-library/preact';
import { render, fireEvent } from '@testing-library/preact';
import { JSDOM } from 'jsdom';
import { axe } from 'jest-axe';
import { Channels } from '../channels';
@ -107,7 +107,9 @@ describe('<Channels />', () => {
expect(queryByRole('alert')).toBeNull();
// configFooter should exist
getByRole('menu');
fireEvent.click(
getByRole('button', { name: /configuration navigation menu/i }),
);
const settings = getByText('Settings');
expect(settings.getAttribute('href')).toEqual('/settings');
@ -121,7 +123,9 @@ describe('<Channels />', () => {
// should show "Welcome to Connect message....."
getByRole('alert');
getByRole('menu');
fireEvent.click(
getByRole('button', { name: /configuration navigation menu/i }),
);
const settings = getByText('Settings');
expect(settings.getAttribute('href')).toEqual('/settings');

View file

@ -1,8 +1,7 @@
import { h } from 'preact';
import PropTypes from 'prop-types';
// eslint-disable-next-line import/no-unresolved
import ConfigImage from 'images/overflow-horizontal.svg';
import { ChannelButton } from './components/ChannelButton';
import { ConfigMenu } from './configMenu';
import { channelSorter } from './util';
export const Channels = ({
@ -78,23 +77,6 @@ export const Channels = ({
<div className="chatchannels__channelslistfooter">...</div>
);
}
let configFooter = '';
if (expanded) {
// TODO: The <div /> below should be converted into a real menu or <nav />
configFooter = (
<div className="chatchannels__config">
<img alt="configration" src={ConfigImage} style={{ height: '18px' }} />
<div className="chatchannels__configmenu" role="menu">
<a href="/settings" role="menuitem">
Settings
</a>
<a href="/report-abuse" role="menuitem">
Report Abuse
</a>
</div>
</div>
);
}
return (
<div className="chatchannels">
<div
@ -116,7 +98,8 @@ export const Channels = ({
)}
{channelsListFooter}
</div>
{configFooter}
<ConfigMenu />
</div>
);
};

View file

@ -0,0 +1,53 @@
import { h, Component, createRef } from 'preact';
// eslint-disable-next-line import/no-unresolved
import ConfigImage from 'images/overflow-horizontal.svg';
export class ConfigMenu extends Component {
constructor() {
super();
this.state = { visible: false };
this.firstNavLink = createRef();
this.configMenuButton = createRef();
}
handleClick = () => {
this.setState(
(prevState) => ({ visible: !prevState.visible }),
() => {
this.state.visible
? this.firstNavLink.current.focus()
: this.configMenuButton.current.focus();
},
);
};
render() {
const { visible } = this.state;
return (
<div className="chatchannels__config">
<button
onClick={this.handleClick}
aria-expanded={visible}
aria-label="configuration navigation menu"
style={{ backgroundImage: `url(${ConfigImage})` }}
ref={this.configMenuButton}
/>
{visible && (
<nav aria-label="configuration menu">
<ul className="chatchannels__configmenu">
<li>
<a href="/settings" ref={this.firstNavLink}>
Settings
</a>
</li>
<li>
<a href="/report-abuse">Report Abuse</a>
</li>
</ul>
</nav>
)}
</div>
);
}
}