Skip to content
Snippets Groups Projects
Commit da75107d authored by Tom Robinson's avatar Tom Robinson
Browse files

Make Tooltip work with components directly rather than having to wrap in a DOM element

parent 9703d8dc
No related branches found
No related tags found
No related merge requests found
......@@ -16,7 +16,7 @@ export default class Popover extends Component {
static propTypes = {
isOpen: PropTypes.bool,
hasArrow: PropTypes.bool,
getTarget: PropTypes.func,
// target: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
tetherOptions: PropTypes.object
};
......@@ -152,9 +152,11 @@ export default class Popover extends Component {
tetherOptions.target.style.left = (this.props.targetEvent.clientX - 3) + "px";
tetherOptions.target.style.top = (this.props.targetEvent.clientY - 3) + "px";
} else if (this.props.target) {
tetherOptions.target = ReactDOM.findDOMNode(this.props.target);
} else if (this.props.getTarget) {
tetherOptions.target = ReactDOM.findDOMNode(this.props.getTarget());
if (typeof this.props.target === "function") {
tetherOptions.target = ReactDOM.findDOMNode(this.props.target());
} else {
tetherOptions.target = ReactDOM.findDOMNode(this.props.target);
}
}
if (tetherOptions.target == null) {
tetherOptions.target = ReactDOM.findDOMNode(this).parentNode;
......
import React, { Component, PropTypes } from "react";
import ReactDOM from "react-dom";
import TooltipPopover from "./TooltipPopover.jsx";
export default class Tooltip extends Component {
constructor(props, context) {
super(props, context);
this.state = {
isOpen: false
};
this._onMouseEnter = this._onMouseEnter.bind(this);
this._onMouseLeave = this._onMouseLeave.bind(this);
}
static propTypes = {
......@@ -22,16 +27,43 @@ export default class Tooltip extends Component {
verticalAttachments: ["top", "bottom"]
};
render() {
const { isEnabled, onMouseEnter, onMouseLeave, children } = this.props;
componentDidMount() {
let elem = ReactDOM.findDOMNode(this);
elem.addEventListener("mouseenter", this._onMouseEnter, false);
elem.addEventListener("mouseleave", this._onMouseLeave, false);
this._element = document.createElement('div');
this.componentDidUpdate();
}
componentDidUpdate() {
const { isEnabled } = this.props;
const { isOpen } = this.state;
const child = React.Children.only(children);
return React.cloneElement(child, {
onMouseEnter: (...args) => { this.setState({ isOpen: true }); onMouseEnter && onMouseEnter(...args); },
onMouseLeave: (...args) => { this.setState({ isOpen: false }); onMouseLeave && onMouseLeave(...args); },
children: React.Children.toArray(child.props.children).concat(
isEnabled ? [<TooltipPopover isOpen={isOpen} {...this.props} children={this.props.tooltip} />] : []
)
});
if (isEnabled && isOpen) {
ReactDOM.render(
<TooltipPopover isOpen={true} target={this} {...this.props} children={this.props.tooltip} />,
this._element
);
} else {
ReactDOM.unmountComponentAtNode(this._element);
}
}
componentWillUnmount() {
let elem = ReactDOM.findDOMNode(this);
elem.removeEventListener("mouseenter", this._onMouseEnter, false);
elem.removeEventListener("mouseleave", this._onMouseLeave, false);
ReactDOM.unmountComponentAtNode(this._element);
}
_onMouseEnter(e) {
this.setState({ isOpen: true });
}
_onMouseLeave(e) {
this.setState({ isOpen: false });
}
render() {
return React.Children.only(this.props.children);
}
}
......@@ -35,9 +35,9 @@ export default ComposedComponent => class extends Component {
this.close();
}
getTarget() {
if (this.props.getTarget) {
return this.props.getTarget();
target() {
if (this.props.target) {
return this.props.target();
} else {
return this.refs.trigger;
}
......@@ -51,7 +51,7 @@ export default ComposedComponent => class extends Component {
{...this.props}
isOpen={this.state.isOpen}
onClose={this.onClose.bind(this)}
getTarget={() => this.getTarget()}
target={() => this.target()}
/>
</a>
);
......
......@@ -249,9 +249,7 @@ export default class AddSeriesModal extends Component {
</span>
{ card.dataset_query.type !== "query" &&
<Tooltip tooltip="We're not sure if this question is compatible">
<span className="px1 flex-align-right">
<Icon className="text-grey-2 text-grey-4-hover cursor-pointer" name="warning" width={20} height={20} />
</span>
<Icon className="px1 flex-align-right text-grey-2 text-grey-4-hover cursor-pointer" name="warning" width={20} height={20} />
</Tooltip>
}
</li>
......
......@@ -28,15 +28,11 @@ export default class RefreshWidget extends Component {
ref="popover"
triggerElement={elapsed == null ?
<Tooltip tooltip="Auto-refresh">
<span>
<ClockIcon width={18} height={18} className={className} />
</span>
<ClockIcon width={18} height={18} className={className} />
</Tooltip>
:
<Tooltip tooltip={"Refreshing in " + Math.floor(remaining / 60) + ":" + (remaining % 60 < 10 ? "0" : "") + Math.round(remaining % 60)}>
<span>
<CountdownIcon width={18} height={18} className="text-green" percent={Math.min(0.95, (period - elapsed) / period)}/>
</span>
<CountdownIcon width={18} height={18} className="text-green" percent={Math.min(0.95, (period - elapsed) / period)}/>
</Tooltip>
}
targetOffsetY={10}
......
......@@ -222,7 +222,7 @@ export default class GuiQueryEditor extends Component {
<PopoverWithTrigger ref="filterPopover"
triggerElement={addFilterButton}
triggerClasses="flex align-center"
getTarget={() => this.refs.addFilterTarget}
target={() => this.refs.addFilterTarget}
>
<FilterPopover
isNew={true}
......
......@@ -3,6 +3,7 @@ import S from "./ActionHeader.css";
import StackedCheckBox from "metabase/components/StackedCheckBox.jsx";
import Icon from "metabase/components/Icon.jsx";
import Tooltip from "metabase/components/Tooltip.jsx";
import LabelPopover from "../containers/LabelPopover.jsx";
......@@ -10,13 +11,15 @@ import cx from "classnames";
const ActionHeader = ({ selectedCount, allAreSelected, setAllSelected, setArchived, labels }) =>
<div className={S.actionHeader}>
<StackedCheckBox
checked={allAreSelected}
onChange={(e) => setAllSelected(e.target.checked)}
className={cx(S.allCheckbox, { [S.selected]: allAreSelected })}
size={20} padding={3} borderColor="currentColor"
invertChecked
/>
<Tooltip tooltip="Select all" isEnabled={!allAreSelected}>
<StackedCheckBox
checked={allAreSelected}
onChange={(e) => setAllSelected(e.target.checked)}
className={cx(S.allCheckbox, { [S.selected]: allAreSelected })}
size={20} padding={3} borderColor="currentColor"
invertChecked
/>
</Tooltip>
<span className={S.selectedCount}>
{selectedCount} selected
</span>
......
......@@ -7,6 +7,7 @@ import LabelPopover from "../containers/LabelPopover.jsx";
import Icon from "metabase/components/Icon.jsx";
import CheckBox from "metabase/components/CheckBox.jsx";
import Tooltip from "metabase/components/Tooltip.jsx";
import Urls from "metabase/lib/urls";
......@@ -36,7 +37,9 @@ const Item = ({ id, name, created, by, selected, favorite, archived, icon, label
<Icon className={S.favoriteIcon} name="star" width={20} height={20} onClick={() => setFavorited(id, !favorite) }/>
</div>
<div className={S.extraIcons}>
<Icon className={S.archiveIcon} name="grid" width={20} height={20} onClick={() => setArchived(id, !archived)} />
<Tooltip tooltip="Archive">
<Icon className={S.archiveIcon} name="grid" width={20} height={20} onClick={() => setArchived(id, !archived)} />
</Tooltip>
</div>
</div>
......
......@@ -226,7 +226,7 @@ export default class Tutorial extends Component {
<Portal className="z2" target={portalTarget} />
}
<Modal isOpen={!!(modal && !step.getModalTarget)} style={{ backgroundColor: "transparent" }} className="Modal TutorialModal" onClose={onClose}>{modal}</Modal>
<Popover isOpen={!!(modal && step.getModalTarget && modalTarget)} getTarget={step.getModalTarget} targetOffsetY={25} onClose={onClose} className="TutorialModal">{modal}</Popover>
<Popover isOpen={!!(modal && step.getModalTarget && modalTarget)} target={step.getModalTarget} targetOffsetY={25} onClose={onClose} className="TutorialModal">{modal}</Popover>
</div>
);
}
......
......@@ -75,9 +75,7 @@ export default class LegendVertical extends Component {
{overflowCount > 0 ?
<li key="extra">
<Tooltip tooltip={<LegendVertical className="p2" titles={extraItems} colors={extraColors} />}>
<span className="inline-block">
<LegendItem title={(overflowCount + 1) + " more"} color="gray" showTooltip={false} />
</span>
<LegendItem className="inline-block" title={(overflowCount + 1) + " more"} color="gray" showTooltip={false} />
</Tooltip>
</li>
: null }
......
......@@ -102,9 +102,7 @@ export default class Visualization extends Component {
{ error ?
<div className="flex-full px1 pb1 text-centered text-slate-light flex flex-column layout-centered">
<Tooltip tooltip={isDashboard ? ERROR_MESSAGE_GENERIC : error} isEnabled={small}>
<div className="mb2">
<Icon name="warning" width={50} height={50} />
</div>
<Icon className="mb2" name="warning" width={50} height={50} />
</Tooltip>
{ !small &&
<span className="h4 text-bold">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment