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:
parent
9bbc738dc3
commit
2c0bbe317b
4 changed files with 80 additions and 33 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
53
app/javascript/chat/configMenu.jsx
Normal file
53
app/javascript/chat/configMenu.jsx
Normal 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>
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue