Skip to content

Commit

Permalink
Refactors Popovers (elastic#617)
Browse files Browse the repository at this point in the history
* Created popover HOC for EuiPopover. Refactored existing popovers.

Added popover HOC. Refactored refresh_control 

Added paddingSize prop to popover

Added EuiButtonIcon and EuiPopover to arg_add_popover

Added aria-label to euibuttonicon in arg_add_popover

Added ids to all popovers

Fixed position of popovers

* Replaced EUI Popover with bootstrap popover

* Removed comments and unused props

* Fix: popover closes when clicking outside of the popover

* Fixed CSS for arg_form

* Changed div to span in popover

* Fixed button prop type in popover

* Refactored popover to use bootstrap overlay.

* Fixed popover props to match EuiPopover props

* Fixed popover title in refresh_control

* Removed window resize and wheel event listeners

* Added comment to popover

* Fixed prop name in popover
  • Loading branch information
cqliu1 authored Jun 8, 2018
1 parent d9333a8 commit 9554760
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 114 deletions.
45 changes: 19 additions & 26 deletions public/components/arg_add_popover/arg_add_popover.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
import React from 'react';
import { PropTypes } from 'prop-types';
import { Popover, OverlayTrigger } from 'react-bootstrap';
import { get } from 'lodash';
import { EuiButtonIcon } from '@elastic/eui';
import { Popover } from '../popover';
import { ArgAdd } from '../arg_add';
import './arg_add_popover.less';

export const ArgAddPopover = ({ options }) => {
let close;
const linkRef = refNode => {
// TODO: handleHide is a private method, there must be a supported way to do this, I just don't know
// what it is.
close = get(refNode, 'handleHide');
};

const picker = (
<Popover className="canvas__add-arg-popover" id="arg-add-popover">
{options.map(opt => (
<ArgAdd
key={`${opt.arg.name}-add`}
displayName={opt.arg.displayName}
help={opt.arg.help}
onValueAdd={() => {
opt.onValueAdd();
close();
}}
/>
))}
</Popover>
const button = handleClick => (
<EuiButtonIcon iconType="plusInCircle" aria-label="Add Argument" onClick={handleClick} />
);

return (
<OverlayTrigger rootClose overlay={picker} placement="bottom" trigger="click" ref={linkRef}>
<i className="fa fa-plus-circle canvas__add-arg-button" />
</OverlayTrigger>
<Popover id="arg-add-popover" panelClassName="canvas__add-arg-popover" button={button}>
{({ closePopover }) =>
options.map(opt => (
<ArgAdd
key={`${opt.arg.name}-add`}
displayName={opt.arg.displayName}
help={opt.arg.help}
onValueAdd={() => {
opt.onValueAdd();
closePopover();
}}
/>
))
}
</Popover>
);
};

Expand Down
13 changes: 5 additions & 8 deletions public/components/arg_add_popover/arg_add_popover.less
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
@import (reference) "../../style/main";
@import (reference) '../../style/main';

.canvas__add-arg-popover .popover-content {
padding: 0px;
.canvas__add-arg-popover {
width: 200px;
font-size: @textXSmall;
}

.canvas__add-arg-button.fa {
color: @mediumGrey;
margin-left: @spacingXS;
font-size: @textSmall;
.popover-content {
padding: 0;
}
}
2 changes: 1 addition & 1 deletion public/components/arg_form/arg_form.less
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
}

.canvas__arg--controls {
padding: 0 @spacingS @spacingS @spacingS;
padding: @spacingS;

.canvas__arg--controls--submit {
text-align: right;
Expand Down
1 change: 1 addition & 0 deletions public/components/popover/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Popover } from './popover';
87 changes: 87 additions & 0 deletions public/components/popover/popover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { Popover as BootstrapPopover, Overlay } from 'react-bootstrap';

// mapping for EUI popover positions to bootstrap placements
const anchorPositions = {
upCenter: 'top',
upLeft: 'top',
upRight: 'top',
downCenter: 'bottom',
downLeft: 'bottom',
downRight: 'bottom',
leftCenter: 'left',
leftUp: 'left',
leftDown: 'left',
rightCenter: 'right',
rightUp: 'right',
rightDown: 'right',
};

export class Popover extends PureComponent {
static propTypes = {
id: PropTypes.string,
panelClassName: PropTypes.string,
button: PropTypes.func.isRequired,
children: PropTypes.func.isRequired,
title: PropTypes.string,
anchorPosition: PropTypes.string,
style: PropTypes.object,
};

static defaultProps = {
ownFocus: false,
anchorPosition: 'downCenter',
panelPaddingSize: 'm',
};

state = {
isPopoverOpen: false,
};

handleClick = () => {
this.setState({
isPopoverOpen: !this.state.isPopoverOpen,
});
};

closePopover = () => {
this.setState({
isPopoverOpen: false,
});
};

render() {
const { id, button, children, panelClassName, title, anchorPosition, style } = this.props;

const position = anchorPositions[anchorPosition] ? anchorPosition : 'downCenter';

// TODO: replace bootstrap popover with EuiPopover https://github.com/elastic/kibana-canvas/issues/612
// Pending https://github.com/elastic/eui/issues/873
const popover = (
<BootstrapPopover id={id} className={panelClassName} title={title}>
{children({ closePopover: this.closePopover })}
</BootstrapPopover>
);

return (
<div
ref={button => {
this.target = button;
}}
style={style}
>
{button(this.handleClick)}
<Overlay
show={this.state.isPopoverOpen}
onHide={() => this.setState({ isPopoverOpen: false })}
rootClose
placement={anchorPositions[position]}
target={this.target}
>
{popover}
</Overlay>
</div>
);
}
}
15 changes: 4 additions & 11 deletions public/components/refresh_control/auto_refresh_controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
EuiButton,
EuiLink,
EuiFieldText,
EuiTitle,
EuiSpacer,
} from '@elastic/eui';
import { timeDurationString } from '../../lib/time_duration';
Expand All @@ -18,22 +17,16 @@ export const AutoRefreshControls = ({ refreshInterval, setRefresh, disableInterv
return (
<div>
{refreshInterval > 0 ? (
<EuiFlexGroup gutterSize="xs" alignItems="center">
<EuiFlexGroup gutterSize="xs" alignItems="baseline">
<EuiFlexItem grow={false}>
<EuiTitle size="s">
<span>Interval: {timeDurationString(refreshInterval)}</span>
</EuiTitle>
<h5>Interval: {timeDurationString(refreshInterval)}</h5>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiLink size="xs" onClick={disableInterval}>
Disable
</EuiLink>
<EuiLink onClick={disableInterval}>Disable</EuiLink>
</EuiFlexItem>
</EuiFlexGroup>
) : (
<EuiTitle size="s">
<div>Interval: disabled</div>
</EuiTitle>
<h5>Interval: disabled</h5>
)}

<EuiSpacer size="m" />
Expand Down
99 changes: 41 additions & 58 deletions public/components/refresh_control/refresh_control.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { PureComponent } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { EuiIcon, EuiButtonIcon, EuiPopover, EuiPopoverTitle } from '@elastic/eui';
import { EuiIcon, EuiButtonIcon } from '@elastic/eui';
import { Popover } from '../popover';
import { AutoRefreshControls } from './auto_refresh_controls';
import './refresh_control.less';

Expand Down Expand Up @@ -38,69 +39,51 @@ const getRefreshInterval = (val = '') => {
}
};

export class RefreshControl extends PureComponent {
state = {
isPopoverOpen: false,
};
export const RefreshControl = ({ inFlight, doRefresh, setRefreshInterval, refreshInterval }) => {
const setRefresh = val => setRefreshInterval(getRefreshInterval(val));

handleClick = () => {
this.setState({
isPopoverOpen: !this.state.isPopoverOpen,
});
};
const popoverButton = handleClick => (
<EuiButtonIcon
iconType="arrowDown"
size="m"
className={autoClass(refreshInterval)}
aria-label="Auto Refresh Popover"
onClick={handleClick}
/>
);

closePopover = () => {
this.setState({
isPopoverOpen: false,
});
};

render() {
const { inFlight, doRefresh, setRefreshInterval, refreshInterval } = this.props;
const setRefresh = val => setRefreshInterval(getRefreshInterval(val));

const popoverButton = (
<EuiButtonIcon
iconType="arrowDown"
size="m"
className={autoClass(refreshInterval)}
onClick={this.handleClick}
aria-label="Auto Refresh Popover"
/>
);

const autoRefreshControls = (
<EuiPopover
id="auto-refresh-popover"
ownFocus
button={popoverButton}
isOpen={this.state.isPopoverOpen}
closePopover={this.closePopover}
withTitle
panelClassName="canvas__refresh_control--popover"
>
<EuiPopoverTitle>Workpad Auto Refresh</EuiPopoverTitle>
const autoRefreshControls = (
<Popover
id="auto-refresh-popover"
button={popoverButton}
title="Workpad Auto Refresh"
panelClassName="canvas__refresh_control--popover"
>
{({ closePopover }) => (
<AutoRefreshControls
refreshInterval={refreshInterval}
setRefresh={setRefresh}
disableInterval={() => setRefresh(0)}
disableInterval={() => {
setRefresh(0);
closePopover();
}}
/>
</EuiPopover>
);
)}
</Popover>
);

return (
<span className={`canvas__refresh_control`}>
<EuiIcon
type="refresh"
size="xl"
className={`${refreshClass(inFlight)}`}
onClick={doRefresh}
/>
{autoRefreshControls}
</span>
);
}
}
return (
<span className={`canvas__refresh_control`}>
<EuiIcon
type="refresh"
size="xl"
className={`${refreshClass(inFlight)}`}
onClick={doRefresh}
/>
{autoRefreshControls}
</span>
);
};

RefreshControl.propTypes = {
inFlight: PropTypes.bool.isRequired,
Expand Down
14 changes: 5 additions & 9 deletions public/components/refresh_control/refresh_control.less
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
@import (reference) '../../style/main';

.canvas__refresh_control {
.canvas__refresh_control--popover {
min-width: 250px;
}
display: flex;
align-items: center;

.canvas__auto_refresh {
color: #93c83d;
Expand All @@ -13,16 +12,13 @@
-webkit-animation: refreshInFlight 3s 0s linear infinite;
animation: refreshInFlight 3s linear 0s infinite;
}
}

.canvas__refresh_control--popover {
width: 250px;
.canvas__refresh_control--auto-refresh--submit {
min-width: @spacingXXXL;
}

.canvas__refresh_control--auto-refresh--preset-intervals {
.items > * {
width: 100%;
}
}
}

@-webkit-keyframes refreshInFlight {
Expand Down
4 changes: 3 additions & 1 deletion public/components/sidebar/sidebar.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import (reference) "../../style/main";
@import (reference) '../../style/main';

.canvas__sidebar {
padding: @spacingS;
Expand All @@ -7,6 +7,8 @@
.canvas__sidebar-section-title {
font-size: @textMedium;
font-weight: 200;
display: flex;
align-items: center;
}

.canvas__sidebar-section-tip {
Expand Down

0 comments on commit 9554760

Please sign in to comment.