Browse Source

Merge pull request #14766 from grafana/fix-toggle-button-group-corners

Fix toggle button group corners
Torkel Ödegaard 7 years ago
parent
commit
2d16c29a1a
29 changed files with 232 additions and 249 deletions
  1. 2 0
      packages/grafana-ui/package.json
  2. 2 2
      packages/grafana-ui/src/components/Portal/Portal.tsx
  3. 11 15
      packages/grafana-ui/src/components/Tooltip/Popper.tsx
  4. 99 0
      packages/grafana-ui/src/components/Tooltip/PopperController.tsx
  5. 5 3
      packages/grafana-ui/src/components/Tooltip/Tooltip.test.tsx
  6. 32 0
      packages/grafana-ui/src/components/Tooltip/Tooltip.tsx
  7. 0 0
      packages/grafana-ui/src/components/Tooltip/_Tooltip.scss
  8. 12 0
      packages/grafana-ui/src/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap
  9. 1 0
      packages/grafana-ui/src/components/index.scss
  10. 2 0
      packages/grafana-ui/src/components/index.ts
  11. 5 3
      public/app/core/components/Label/Label.tsx
  12. 1 1
      public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx
  13. 0 16
      public/app/core/components/Tooltip/Popover.test.tsx
  14. 0 19
      public/app/core/components/Tooltip/Popover.tsx
  15. 0 17
      public/app/core/components/Tooltip/Tooltip.tsx
  16. 0 16
      public/app/core/components/Tooltip/__snapshots__/Popover.test.tsx.snap
  17. 0 19
      public/app/core/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap
  18. 0 89
      public/app/core/components/Tooltip/withPopper.tsx
  19. 11 14
      public/app/features/dashboard/dashgrid/DataPanel.tsx
  20. 1 1
      public/app/features/dashboard/dashgrid/DataSourceOption.tsx
  21. 2 2
      public/app/features/dashboard/dashgrid/PanelEditor.tsx
  22. 8 6
      public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx
  23. 5 3
      public/app/features/dashboard/permissions/DashboardPermissions.tsx
  24. 5 3
      public/app/features/folders/FolderPermissions.tsx
  25. 5 3
      public/app/features/teams/TeamGroupSync.tsx
  26. 1 0
      public/app/features/teams/TeamSettings.tsx
  27. 18 12
      public/app/features/teams/__snapshots__/TeamGroupSync.test.tsx.snap
  28. 0 1
      public/sass/_grafana.scss
  29. 4 4
      yarn.lock

+ 2 - 0
packages/grafana-ui/package.json

@@ -11,6 +11,8 @@
   "license": "ISC",
   "dependencies": {
     "@torkelo/react-select": "2.1.1",
+    "@types/react-test-renderer": "^16.0.3",
+    "@types/react-transition-group": "^2.0.15",
     "classnames": "^2.2.5",
     "jquery": "^3.2.1",
     "lodash": "^4.17.10",

+ 2 - 2
public/app/core/components/Portal/Portal.tsx → packages/grafana-ui/src/components/Portal/Portal.tsx

@@ -6,11 +6,11 @@ interface Props {
   root?: HTMLElement;
 }
 
-export default class BodyPortal extends PureComponent<Props> {
+export class Portal extends PureComponent<Props> {
   node: HTMLElement = document.createElement('div');
   portalRoot: HTMLElement;
 
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     const {
       className,

+ 11 - 15
public/app/core/components/Tooltip/Popper.tsx → packages/grafana-ui/src/components/Tooltip/Popper.tsx

@@ -1,6 +1,7 @@
 import React, { PureComponent } from 'react';
-import Portal from 'app/core/components/Portal/Portal';
-import { Manager, Popper as ReactPopper, Reference } from 'react-popper';
+import * as PopperJS from 'popper.js';
+import { Manager, Popper as ReactPopper } from 'react-popper';
+import { Portal } from '@grafana/ui';
 import Transition from 'react-transition-group/Transition';
 
 export enum Themes {
@@ -13,45 +14,40 @@ const defaultTransitionStyles = {
   opacity: 0,
 };
 
-const transitionStyles = {
+const transitionStyles: {[key: string]: object} = {
   exited: { opacity: 0 },
   entering: { opacity: 0 },
   entered: { opacity: 1 },
   exiting: { opacity: 0 },
 };
 
-interface Props {
+interface Props extends React.DOMAttributes<HTMLDivElement> {
   renderContent: (content: any) => any;
   show: boolean;
-  placement?: any;
+  placement?: PopperJS.Placement;
   content: string | ((props: any) => JSX.Element);
-  refClassName?: string;
+  referenceElement: PopperJS.ReferenceObject;
   theme?: Themes;
 }
 
 class Popper extends PureComponent<Props> {
   render() {
-    const { children, renderContent, show, placement, refClassName, theme } = this.props;
+    const { renderContent, show, placement, onMouseEnter, onMouseLeave, theme } = this.props;
     const { content } = this.props;
 
     const popperBackgroundClassName = 'popper__background' + (theme ? ' ' + theme : '');
 
     return (
       <Manager>
-        <Reference>
-          {({ ref }) => (
-            <div className={`popper_ref ${refClassName || ''}`} ref={ref}>
-              {children}
-            </div>
-          )}
-        </Reference>
         <Transition in={show} timeout={100} mountOnEnter={true} unmountOnExit={true}>
           {transitionState => (
             <Portal>
-              <ReactPopper placement={placement}>
+              <ReactPopper placement={placement} referenceElement={this.props.referenceElement}>
                 {({ ref, style, placement, arrowProps }) => {
                   return (
                     <div
+                      onMouseEnter={onMouseEnter}
+                      onMouseLeave={onMouseLeave}
                       ref={ref}
                       style={{
                         ...style,

+ 99 - 0
packages/grafana-ui/src/components/Tooltip/PopperController.tsx

@@ -0,0 +1,99 @@
+import React from 'react';
+import * as PopperJS from 'popper.js';
+import { Themes } from './Popper';
+
+type PopperContent = string | (() => JSX.Element);
+
+export interface UsingPopperProps {
+  show?: boolean;
+  placement?: PopperJS.Placement;
+  content: PopperContent;
+  children: JSX.Element;
+  renderContent?: (content: PopperContent) => JSX.Element;
+  theme?: Themes;
+}
+
+type PopperControllerRenderProp = (
+  showPopper: () => void,
+  hidePopper: () => void,
+  popperProps: {
+    show: boolean;
+    placement: PopperJS.Placement;
+    content: string | ((props: any) => JSX.Element);
+    renderContent: (content: any) => any;
+    theme?: Themes;
+  }
+) => JSX.Element;
+
+interface Props {
+  placement?: PopperJS.Placement;
+  content: PopperContent;
+  className?: string;
+  children: PopperControllerRenderProp;
+  theme?: Themes;
+}
+
+interface State {
+  placement: PopperJS.Placement;
+  show: boolean;
+}
+
+class PopperController extends React.Component<Props, State> {
+  constructor(props: Props) {
+    super(props);
+
+    this.state = {
+      placement: this.props.placement || 'auto',
+      show: false,
+    };
+  }
+
+  componentWillReceiveProps(nextProps: Props) {
+    if (nextProps.placement && nextProps.placement !== this.state.placement) {
+      this.setState((prevState: State) => {
+        return {
+          ...prevState,
+          placement: nextProps.placement || 'auto',
+        };
+      });
+    }
+  }
+
+  showPopper = () => {
+    this.setState(prevState => ({
+      ...prevState,
+      show: true,
+    }));
+  };
+
+  hidePopper = () => {
+    this.setState(prevState => ({
+      ...prevState,
+      show: false,
+    }));
+  };
+
+  renderContent(content: PopperContent) {
+    if (typeof content === 'function') {
+      // If it's a function we assume it's a React component
+      const ReactComponent = content;
+      return <ReactComponent />;
+    }
+    return content;
+  }
+
+  render() {
+    const { children, content, theme } = this.props;
+    const { show, placement } = this.state;
+
+    return children(this.showPopper, this.hidePopper, {
+      show,
+      placement,
+      content,
+      renderContent: this.renderContent,
+      theme,
+    });
+  }
+}
+
+export default PopperController;

+ 5 - 3
public/app/core/components/Tooltip/Tooltip.test.tsx → packages/grafana-ui/src/components/Tooltip/Tooltip.test.tsx

@@ -1,13 +1,15 @@
 import React from 'react';
 import renderer from 'react-test-renderer';
-import Tooltip from './Tooltip';
+import { Tooltip } from './Tooltip';
 
 describe('Tooltip', () => {
   it('renders correctly', () => {
     const tree = renderer
       .create(
-        <Tooltip className="test-class" placement="auto" content="Tooltip text">
-          <a href="http://www.grafana.com">Link with tooltip</a>
+        <Tooltip placement="auto" content="Tooltip text">
+          <a className="test-class" href="http://www.grafana.com">
+            Link with tooltip
+          </a>
         </Tooltip>
       )
       .toJSON();

+ 32 - 0
packages/grafana-ui/src/components/Tooltip/Tooltip.tsx

@@ -0,0 +1,32 @@
+import React, { createRef } from 'react';
+import * as PopperJS from 'popper.js';
+import Popper from './Popper';
+import PopperController, { UsingPopperProps } from './PopperController';
+
+export const Tooltip = ({ children, renderContent, ...controllerProps }: UsingPopperProps) => {
+  const tooltipTriggerRef = createRef<PopperJS.ReferenceObject>();
+
+  return (
+    <PopperController {...controllerProps}>
+      {(showPopper, hidePopper, popperProps) => {
+        return (
+          <>
+            {tooltipTriggerRef.current && (
+              <Popper
+                {...popperProps}
+                onMouseEnter={showPopper}
+                onMouseLeave={hidePopper}
+                referenceElement={tooltipTriggerRef.current}
+              />
+            )}
+            {React.cloneElement(children, {
+              ref: tooltipTriggerRef,
+              onMouseEnter: showPopper,
+              onMouseLeave: hidePopper,
+            })}
+          </>
+        );
+      }}
+    </PopperController>
+  );
+};

+ 0 - 0
public/sass/components/_popper.scss → packages/grafana-ui/src/components/Tooltip/_Tooltip.scss


+ 12 - 0
packages/grafana-ui/src/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap

@@ -0,0 +1,12 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Tooltip renders correctly 1`] = `
+<a
+  className="test-class"
+  href="http://www.grafana.com"
+  onMouseEnter={[Function]}
+  onMouseLeave={[Function]}
+>
+  Link with tooltip
+</a>
+`;

+ 1 - 0
packages/grafana-ui/src/components/index.scss

@@ -1,2 +1,3 @@
 @import 'CustomScrollbar/CustomScrollbar';
 @import 'DeleteButton/DeleteButton';
+@import 'Tooltip/Tooltip';

+ 2 - 0
packages/grafana-ui/src/components/index.ts

@@ -1,2 +1,4 @@
 export { DeleteButton } from './DeleteButton/DeleteButton';
+export { Tooltip } from './Tooltip/Tooltip';
+export { Portal } from './Portal/Portal';
 export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar';

+ 5 - 3
public/app/core/components/Label/Label.tsx

@@ -1,5 +1,5 @@
 import React, { SFC, ReactNode } from 'react';
-import Tooltip from '../Tooltip/Tooltip';
+import { Tooltip } from '@grafana/ui';
 
 interface Props {
   tooltip?: string;
@@ -14,8 +14,10 @@ export const Label: SFC<Props> = props => {
     <span className={`gf-form-label width-${props.width ? props.width : '10'}`}>
       <span>{props.children}</span>
       {props.tooltip && (
-        <Tooltip className="gf-form-help-icon--right-normal" placement="auto" content={props.tooltip}>
-          <i className="gicon gicon-question gicon--has-hover" />
+        <Tooltip placement="auto" content={props.tooltip}>
+          <div className="gf-form-help-icon--right-normal">
+            <i className="gicon gicon-question gicon--has-hover" />
+          </div>
         </Tooltip>
       )}
     </span>

+ 1 - 1
public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx

@@ -1,5 +1,5 @@
 import React, { SFC, ReactNode, PureComponent } from 'react';
-import Tooltip from 'app/core/components/Tooltip/Tooltip';
+import { Tooltip } from '@grafana/ui';
 
 interface ToggleButtonGroupProps {
   label?: string;

+ 0 - 16
public/app/core/components/Tooltip/Popover.test.tsx

@@ -1,16 +0,0 @@
-import React from 'react';
-import renderer from 'react-test-renderer';
-import Popover from './Popover';
-
-describe('Popover', () => {
-  it('renders correctly', () => {
-    const tree = renderer
-      .create(
-        <Popover className="test-class" placement="auto" content="Popover text">
-          <button>Button with Popover</button>
-        </Popover>
-      )
-      .toJSON();
-    expect(tree).toMatchSnapshot();
-  });
-});

+ 0 - 19
public/app/core/components/Tooltip/Popover.tsx

@@ -1,19 +0,0 @@
-import React, { PureComponent } from 'react';
-import Popper from './Popper';
-import withPopper, { UsingPopperProps } from './withPopper';
-
-class Popover extends PureComponent<UsingPopperProps> {
-  render() {
-    const { children, hidePopper, showPopper, className, ...restProps } = this.props;
-
-    const togglePopper = restProps.show ? hidePopper : showPopper;
-
-    return (
-      <div className={`popper__manager ${className}`} onClick={togglePopper}>
-        <Popper {...restProps}>{children}</Popper>
-      </div>
-    );
-  }
-}
-
-export default withPopper(Popover);

+ 0 - 17
public/app/core/components/Tooltip/Tooltip.tsx

@@ -1,17 +0,0 @@
-import React, { PureComponent } from 'react';
-import Popper from './Popper';
-import withPopper, { UsingPopperProps } from './withPopper';
-
-class Tooltip extends PureComponent<UsingPopperProps> {
-  render() {
-    const { children, hidePopper, showPopper, className, ...restProps } = this.props;
-
-    return (
-      <div className={`popper__manager ${className}`} onMouseEnter={showPopper} onMouseLeave={hidePopper}>
-        <Popper {...restProps}>{children}</Popper>
-      </div>
-    );
-  }
-}
-
-export default withPopper(Tooltip);

+ 0 - 16
public/app/core/components/Tooltip/__snapshots__/Popover.test.tsx.snap

@@ -1,16 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Popover renders correctly 1`] = `
-<div
-  className="popper__manager test-class"
-  onClick={[Function]}
->
-  <div
-    className="popper_ref "
-  >
-    <button>
-      Button with Popover
-    </button>
-  </div>
-</div>
-`;

+ 0 - 19
public/app/core/components/Tooltip/__snapshots__/Tooltip.test.tsx.snap

@@ -1,19 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Tooltip renders correctly 1`] = `
-<div
-  className="popper__manager test-class"
-  onMouseEnter={[Function]}
-  onMouseLeave={[Function]}
->
-  <div
-    className="popper_ref "
-  >
-    <a
-      href="http://www.grafana.com"
-    >
-      Link with tooltip
-    </a>
-  </div>
-</div>
-`;

+ 0 - 89
public/app/core/components/Tooltip/withPopper.tsx

@@ -1,89 +0,0 @@
-import React from 'react';
-import { Themes } from './Popper';
-export interface UsingPopperProps {
-  showPopper: (prevState: object) => void;
-  hidePopper: (prevState: object) => void;
-  renderContent: (content: any) => any;
-  show: boolean;
-  placement?: string;
-  content: string | ((props: any) => JSX.Element);
-  className?: string;
-  refClassName?: string;
-  theme?: Themes;
-}
-
-interface Props {
-  placement?: string;
-  className?: string;
-  refClassName?: string;
-  content: string | ((props: any) => JSX.Element);
-  theme?: Themes;
-}
-
-interface State {
-  placement: string;
-  show: boolean;
-}
-
-export default function withPopper(WrappedComponent) {
-  return class extends React.Component<Props, State> {
-    constructor(props) {
-      super(props);
-      this.setState = this.setState.bind(this);
-      this.state = {
-        placement: this.props.placement || 'auto',
-        show: false,
-      };
-    }
-
-    componentWillReceiveProps(nextProps) {
-      if (nextProps.placement && nextProps.placement !== this.state.placement) {
-        this.setState(prevState => {
-          return {
-            ...prevState,
-            placement: nextProps.placement,
-          };
-        });
-      }
-    }
-
-    showPopper = () => {
-      this.setState(prevState => ({
-        ...prevState,
-        show: true,
-      }));
-    };
-
-    hidePopper = () => {
-      this.setState(prevState => ({
-        ...prevState,
-        show: false,
-      }));
-    };
-
-    renderContent(content) {
-      if (typeof content === 'function') {
-        // If it's a function we assume it's a React component
-        const ReactComponent = content;
-        return <ReactComponent />;
-      }
-      return content;
-    }
-
-    render() {
-      const { show, placement } = this.state;
-      const className = this.props.className || '';
-      return (
-        <WrappedComponent
-          {...this.props}
-          showPopper={this.showPopper}
-          hidePopper={this.hidePopper}
-          renderContent={this.renderContent}
-          show={show}
-          placement={placement}
-          className={className}
-        />
-      );
-    }
-  };
-}

+ 11 - 14
public/app/features/dashboard/dashgrid/DataPanel.tsx

@@ -1,6 +1,8 @@
 // Library
 import React, { Component } from 'react';
-import Tooltip from 'app/core/components/Tooltip/Tooltip';
+import { Tooltip } from '@grafana/ui';
+import { Themes } from '@grafana/ui/src/components/Tooltip/Popper';
+
 import ErrorBoundary from 'app/core/components/ErrorBoundary/ErrorBoundary';
 
 // Services
@@ -12,7 +14,6 @@ import kbn from 'app/core/utils/kbn';
 // Types
 import { DataQueryOptions, DataQueryResponse } from 'app/types';
 import { TimeRange, TimeSeries, LoadingState } from '@grafana/ui';
-import { Themes } from 'app/core/components/Tooltip/Popper';
 
 const DEFAULT_PLUGIN_ERROR = 'Error in plugin';
 
@@ -144,10 +145,10 @@ export class DataPanel extends Component<Props, State> {
       this.setState({
         loading: LoadingState.Error,
         isFirstLoad: false,
-        errorMessage: errorMessage
+        errorMessage: errorMessage,
       });
     }
-  }
+  };
 
   render() {
     const { queries } = this.props;
@@ -171,7 +172,7 @@ export class DataPanel extends Component<Props, State> {
       <>
         {this.renderLoadingStates()}
         <ErrorBoundary>
-          {({error, errorInfo}) => {
+          {({ error, errorInfo }) => {
             if (errorInfo) {
               this.onError(error.message || DEFAULT_PLUGIN_ERROR);
               return null;
@@ -200,15 +201,11 @@ export class DataPanel extends Component<Props, State> {
       );
     } else if (loading === LoadingState.Error) {
       return (
-        <Tooltip
-          content={errorMessage}
-          className="popper__manager--block"
-          refClassName={`panel-info-corner panel-info-corner--error`}
-          placement="bottom-start"
-          theme={Themes.Error}
-        >
-          <i className="fa" />
-          <span className="panel-info-corner-inner" />
+        <Tooltip content={errorMessage} placement="bottom-start" theme={Themes.Error}>
+          <div className="panel-info-corner panel-info-corner--error">
+            <i className="fa" />
+            <span className="panel-info-corner-inner" />
+          </div>
         </Tooltip>
       );
     }

+ 1 - 1
public/app/features/dashboard/dashgrid/DataSourceOption.tsx

@@ -1,5 +1,5 @@
 import React, { SFC } from 'react';
-import Tooltip from 'app/core/components/Tooltip/Tooltip';
+import { Tooltip } from '@grafana/ui';
 
 interface Props {
   label: string;

+ 2 - 2
public/app/features/dashboard/dashgrid/PanelEditor.tsx

@@ -15,7 +15,7 @@ import { PanelModel } from '../panel_model';
 import { DashboardModel } from '../dashboard_model';
 import { PanelPlugin } from 'app/types/plugins';
 
-import Tooltip from 'app/core/components/Tooltip/Tooltip';
+import { Tooltip } from '@grafana/ui';
 
 interface PanelEditorProps {
   panel: PanelModel;
@@ -138,7 +138,7 @@ function TabItem({ tab, activeTab, onClick }: TabItemParams) {
   return (
     <div className="panel-editor-tabs__item" onClick={() => onClick(tab)}>
       <a className={tabClasses}>
-        <Tooltip content={`${tab.text}`} className="popper__manager--block" placement="auto">
+        <Tooltip content={`${tab.text}`} placement="auto">
           <i className={`gicon gicon-${tab.id}${activeTab === tab.id ? '-active' : ''}`} />
         </Tooltip>
       </a>

+ 8 - 6
public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx

@@ -1,10 +1,10 @@
 import React, { Component } from 'react';
+import Remarkable from 'remarkable';
+import { Tooltip } from '@grafana/ui';
 import { PanelModel } from 'app/features/dashboard/panel_model';
-import Tooltip from 'app/core/components/Tooltip/Tooltip';
 import templateSrv from 'app/features/templating/template_srv';
 import { LinkSrv } from 'app/features/dashboard/panellinks/link_srv';
 import { getTimeSrv, TimeSrv } from 'app/features/dashboard/time_srv';
-import Remarkable from 'remarkable';
 
 enum InfoModes {
   Error = 'Error',
@@ -78,12 +78,14 @@ export class PanelHeaderCorner extends Component<Props> {
         {infoMode === InfoModes.Info || infoMode === InfoModes.Links ? (
           <Tooltip
             content={this.getInfoContent}
-            className="popper__manager--block"
-            refClassName={`panel-info-corner panel-info-corner--${infoMode.toLowerCase()}`}
             placement="bottom-start"
           >
-            <i className="fa" />
-            <span className="panel-info-corner-inner" />
+            <div
+              className={`panel-info-corner panel-info-corner--${infoMode.toLowerCase()}`}
+            >
+              <i className="fa" />
+              <span className="panel-info-corner-inner" />
+            </div>
           </Tooltip>
         ) : null}
       </>

+ 5 - 3
public/app/features/dashboard/permissions/DashboardPermissions.tsx

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import Tooltip from 'app/core/components/Tooltip/Tooltip';
+import { Tooltip } from '@grafana/ui';
 import SlideDown from 'app/core/components/Animations/SlideDown';
 import { StoreState, FolderInfo } from 'app/types';
 import { DashboardAcl, PermissionLevel, NewDashboardAclItem } from 'app/types/acl';
@@ -70,8 +70,10 @@ export class DashboardPermissions extends PureComponent<Props, State> {
         <div className="dashboard-settings__header">
           <div className="page-action-bar">
             <h3 className="d-inline-block">Permissions</h3>
-            <Tooltip className="page-sub-heading-icon" placement="auto" content={PermissionsInfo}>
-              <i className="gicon gicon-question gicon--has-hover" />
+            <Tooltip placement="auto" content={PermissionsInfo}>
+              <div className="page-sub-heading-icon">
+                <i className="gicon gicon-question gicon--has-hover" />
+              </div>
             </Tooltip>
             <div className="page-action-bar__spacer" />
             <button className="btn btn-success pull-right" onClick={this.onOpenAddPermissions} disabled={isAdding}>

+ 5 - 3
public/app/features/folders/FolderPermissions.tsx

@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
 import { hot } from 'react-hot-loader';
 import { connect } from 'react-redux';
 import PageHeader from 'app/core/components/PageHeader/PageHeader';
-import Tooltip from 'app/core/components/Tooltip/Tooltip';
+import { Tooltip } from '@grafana/ui';
 import SlideDown from 'app/core/components/Animations/SlideDown';
 import { getNavModel } from 'app/core/selectors/navModel';
 import { NavModel, StoreState, FolderState } from 'app/types';
@@ -84,8 +84,10 @@ export class FolderPermissions extends PureComponent<Props, State> {
         <div className="page-container page-body">
           <div className="page-action-bar">
             <h3 className="page-sub-heading">Folder Permissions</h3>
-            <Tooltip className="page-sub-heading-icon" placement="auto" content={PermissionsInfo}>
-              <i className="gicon gicon-question gicon--has-hover" />
+            <Tooltip placement="auto" content={PermissionsInfo}>
+              <div className="page-sub-heading-icon">
+                <i className="gicon gicon-question gicon--has-hover" />
+              </div>
             </Tooltip>
             <div className="page-action-bar__spacer" />
             <button className="btn btn-success pull-right" onClick={this.onOpenAddPermissions} disabled={isAdding}>

+ 5 - 3
public/app/features/teams/TeamGroupSync.tsx

@@ -1,7 +1,7 @@
 import React, { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import SlideDown from 'app/core/components/Animations/SlideDown';
-import Tooltip from 'app/core/components/Tooltip/Tooltip';
+import { Tooltip } from '@grafana/ui';
 import { TeamGroup } from '../../types';
 import { addTeamGroup, loadTeamGroups, removeTeamGroup } from './state/actions';
 import { getTeamGroups } from './state/selectors';
@@ -77,8 +77,10 @@ export class TeamGroupSync extends PureComponent<Props, State> {
       <div>
         <div className="page-action-bar">
           <h3 className="page-sub-heading">External group sync</h3>
-          <Tooltip className="page-sub-heading-icon" placement="auto" content={headerTooltip}>
-            <i className="gicon gicon-question gicon--has-hover" />
+          <Tooltip placement="auto" content={headerTooltip}>
+            <div className="page-sub-heading-icon">
+              <i className="gicon gicon-question gicon--has-hover" />
+            </div>
           </Tooltip>
           <div className="page-action-bar__spacer" />
           {groups.length > 0 && (

+ 1 - 0
public/app/features/teams/TeamSettings.tsx

@@ -60,6 +60,7 @@ export class TeamSettings extends React.Component<Props, State> {
               onChange={this.onChangeName}
             />
           </div>
+
           <div className="gf-form max-width-30">
             <Label tooltip="This is optional and is primarily used to set the team profile avatar (via gravatar service)">
               Email

+ 18 - 12
public/app/features/teams/__snapshots__/TeamGroupSync.test.tsx.snap

@@ -10,15 +10,18 @@ exports[`Render should render component 1`] = `
     >
       External group sync
     </h3>
-    <class_1
-      className="page-sub-heading-icon"
+    <Component
       content="Sync LDAP or OAuth groups with your Grafana teams."
       placement="auto"
     >
-      <i
-        className="gicon gicon-question gicon--has-hover"
-      />
-    </class_1>
+      <div
+        className="page-sub-heading-icon"
+      >
+        <i
+          className="gicon gicon-question gicon--has-hover"
+        />
+      </div>
+    </Component>
     <div
       className="page-action-bar__spacer"
     />
@@ -116,15 +119,18 @@ exports[`Render should render groups table 1`] = `
     >
       External group sync
     </h3>
-    <class_1
-      className="page-sub-heading-icon"
+    <Component
       content="Sync LDAP or OAuth groups with your Grafana teams."
       placement="auto"
     >
-      <i
-        className="gicon gicon-question gicon--has-hover"
-      />
-    </class_1>
+      <div
+        className="page-sub-heading-icon"
+      >
+        <i
+          className="gicon gicon-question gicon--has-hover"
+        />
+      </div>
+    </Component>
     <div
       className="page-action-bar__spacer"
     />

+ 0 - 1
public/sass/_grafana.scss

@@ -97,7 +97,6 @@
 @import 'components/page_header';
 @import 'components/dashboard_settings';
 @import 'components/empty_list_cta';
-@import 'components/popper';
 @import 'components/form_select_box';
 @import 'components/panel_editor';
 @import 'components/toolbar';

+ 4 - 4
yarn.lock

@@ -1098,10 +1098,10 @@
   dependencies:
     "@types/react" "*"
 
-"@types/react-transition-group@*":
-  version "2.0.14"
-  resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.0.14.tgz#afd0cd785a97f070b55765e9f9d76ff568269001"
-  integrity sha512-pa7qB0/mkhwWMBFoXhX8BcntK8G4eQl4sIfSrJCxnivTYRQWjOWf2ClR9bWdm0EUFBDHzMbKYS+QYfDtBzkY4w==
+"@types/react-transition-group@^2.0.15":
+  version "2.0.15"
+  resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.0.15.tgz#e5ee3fe558832e141cc6041bdd54caea7b787af8"
+  integrity sha512-S0QnNzbHoWXDbKBl/xk5dxA4FT+BNlBcI3hku991cl8Cz3ytOkUMcCRtzdX11eb86E131bSsQqy5WrPCdJYblw==
   dependencies:
     "@types/react" "*"