refactor, aria props
This commit is contained in:
@ -11,6 +11,7 @@ import { fadeAndScaleIn } from 'shared/styles/animations';
|
|||||||
import NudeButton from 'components/NudeButton';
|
import NudeButton from 'components/NudeButton';
|
||||||
|
|
||||||
let previousClosePortal;
|
let previousClosePortal;
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
type Children =
|
type Children =
|
||||||
| React.Node
|
| React.Node
|
||||||
@ -28,6 +29,8 @@ type Props = {
|
|||||||
|
|
||||||
@observer
|
@observer
|
||||||
class DropdownMenu extends React.Component<Props> {
|
class DropdownMenu extends React.Component<Props> {
|
||||||
|
id: number = `menu${counter++}`;
|
||||||
|
|
||||||
@observable top: ?number;
|
@observable top: ?number;
|
||||||
@observable bottom: ?number;
|
@observable bottom: ?number;
|
||||||
@observable right: ?number;
|
@observable right: ?number;
|
||||||
@ -37,6 +40,7 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
@observable bodyRect: ClientRect;
|
@observable bodyRect: ClientRect;
|
||||||
@observable labelRect: ClientRect;
|
@observable labelRect: ClientRect;
|
||||||
@observable dropdownRef: { current: null | HTMLElement } = React.createRef();
|
@observable dropdownRef: { current: null | HTMLElement } = React.createRef();
|
||||||
|
@observable menuRef: { current: null | HTMLElement } = React.createRef();
|
||||||
|
|
||||||
handleOpen = (
|
handleOpen = (
|
||||||
openPortal: (SyntheticEvent<>) => void,
|
openPortal: (SyntheticEvent<>) => void,
|
||||||
@ -88,12 +92,12 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpen(originalFunction?: () => void) {
|
onOpen = () => {
|
||||||
if (typeof originalFunction === 'function') {
|
if (typeof this.props.onOpen === 'function') {
|
||||||
originalFunction();
|
this.props.onOpen();
|
||||||
}
|
}
|
||||||
this.fitOnTheScreen();
|
this.fitOnTheScreen();
|
||||||
}
|
};
|
||||||
|
|
||||||
fitOnTheScreen() {
|
fitOnTheScreen() {
|
||||||
if (!this.dropdownRef || !this.dropdownRef.current) return;
|
if (!this.dropdownRef || !this.dropdownRef.current) return;
|
||||||
@ -135,16 +139,21 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<PortalWithState
|
<PortalWithState
|
||||||
onOpen={this.onOpen.bind(this, this.props.onOpen)}
|
onOpen={this.onOpen}
|
||||||
onClose={this.props.onClose}
|
onClose={this.props.onClose}
|
||||||
closeOnOutsideClick
|
closeOnOutsideClick
|
||||||
closeOnEsc
|
closeOnEsc
|
||||||
>
|
>
|
||||||
{({ closePortal, openPortal, portal }) => (
|
{({ closePortal, openPortal, isOpen, portal }) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Label onClick={this.handleOpen(openPortal, closePortal)}>
|
<Label onClick={this.handleOpen(openPortal, closePortal)}>
|
||||||
{label || (
|
{label || (
|
||||||
<NudeButton>
|
<NudeButton
|
||||||
|
id={`${this.id}button`}
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded={isOpen ? 'true' : 'false'}
|
||||||
|
aria-controls={this.id}
|
||||||
|
>
|
||||||
<MoreIcon />
|
<MoreIcon />
|
||||||
</NudeButton>
|
</NudeButton>
|
||||||
)}
|
)}
|
||||||
@ -160,6 +169,7 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
right={this.right}
|
right={this.right}
|
||||||
>
|
>
|
||||||
<Menu
|
<Menu
|
||||||
|
ref={this.menuRef}
|
||||||
onClick={
|
onClick={
|
||||||
typeof children === 'function'
|
typeof children === 'function'
|
||||||
? undefined
|
? undefined
|
||||||
@ -169,6 +179,9 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
style={this.props.style}
|
style={this.props.style}
|
||||||
|
id={this.id}
|
||||||
|
aria-labelledby={`${this.id}button`}
|
||||||
|
role="menu"
|
||||||
>
|
>
|
||||||
{typeof children === 'function'
|
{typeof children === 'function'
|
||||||
? children({ closePortal })
|
? children({ closePortal })
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { lighten } from 'polished';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClick?: (SyntheticEvent<>) => void | Promise<void>,
|
onClick?: (SyntheticEvent<>) => void | Promise<void>,
|
||||||
@ -13,6 +14,8 @@ const DropdownMenuItem = ({ onClick, children, disabled, ...rest }: Props) => {
|
|||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={disabled ? undefined : onClick}
|
onClick={disabled ? undefined : onClick}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
role="menuitem"
|
||||||
|
tabIndex="-1"
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
@ -32,6 +35,7 @@ const MenuItem = styled.a`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
svg:not(:last-child) {
|
svg:not(:last-child) {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
@ -49,6 +53,7 @@ const MenuItem = styled.a`
|
|||||||
&:hover {
|
&:hover {
|
||||||
color: ${props.theme.white};
|
color: ${props.theme.white};
|
||||||
background: ${props.theme.primary};
|
background: ${props.theme.primary};
|
||||||
|
box-shadow: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
|
Reference in New Issue
Block a user