Sfoglia il codice sorgente

Update types and themes usage in components

Dominik Prokop 6 anni fa
parent
commit
6b1390b972
30 ha cambiato i file con 170 aggiunte e 167 eliminazioni
  1. 6 6
      packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx
  2. 6 5
      packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.test.tsx
  3. 10 18
      packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx
  4. 5 4
      packages/grafana-ui/src/components/ColorPicker/NamedColorsGroup.tsx
  5. 5 4
      packages/grafana-ui/src/components/ColorPicker/NamedColorsPalette.test.tsx
  6. 4 1
      packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx
  7. 2 2
      packages/grafana-ui/src/components/ColorPicker/SpectrumPalette.tsx
  8. 2 2
      packages/grafana-ui/src/components/ColorPicker/SpectrumPalettePointer.tsx
  9. 2 0
      packages/grafana-ui/src/components/Gauge/Gauge.test.tsx
  10. 12 11
      packages/grafana-ui/src/components/Gauge/Gauge.tsx
  11. 33 22
      packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx
  12. 2 2
      packages/grafana-ui/src/components/index.ts
  13. 8 8
      packages/grafana-ui/src/utils/namedColorsPalette.test.ts
  14. 7 7
      packages/grafana-ui/src/utils/namedColorsPalette.ts
  15. 2 2
      public/app/core/angular_wrappers.ts
  16. 12 7
      public/app/core/utils/ConfigProvider.tsx
  17. 2 2
      public/app/core/utils/react2angular.ts
  18. 3 4
      public/app/plugins/panel/gauge/GaugePanel.tsx
  19. 9 17
      public/app/plugins/panel/gauge/GaugePanelOptions.tsx
  20. 12 19
      public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx
  21. 2 2
      public/app/plugins/panel/graph/data_processor.ts
  22. 4 3
      public/app/plugins/panel/graph/graph.ts
  23. 2 2
      public/app/plugins/panel/graph/module.ts
  24. 4 4
      public/app/plugins/panel/graph/time_region_manager.ts
  25. 2 2
      public/app/plugins/panel/heatmap/color_legend.ts
  26. 2 2
      public/app/plugins/panel/heatmap/rendering.ts
  27. 4 4
      public/app/plugins/panel/singlestat/module.ts
  28. 2 2
      public/app/plugins/panel/table/module.ts
  29. 2 2
      public/app/plugins/panel/table/renderer.ts
  30. 2 1
      public/app/routes/ReactContainer.tsx

+ 6 - 6
packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx

@@ -2,11 +2,11 @@ import React, { Component, createRef } from 'react';
 import PopperController from '../Tooltip/PopperController';
 import Popper, { RenderPopperArrowFn } from '../Tooltip/Popper';
 import { ColorPickerPopover } from './ColorPickerPopover';
-import { Themeable, GrafanaTheme } from '../../types';
+import { GrafanaThemeType, Themeable } from '../../types';
 import { getColorFromHexRgbOrName } from '../../utils/namedColorsPalette';
 import { SeriesColorPickerPopover } from './SeriesColorPickerPopover';
 import propDeprecationWarning from '../../utils/propDeprecationWarning';
-
+import { withTheme } from '../../themes/ThemeContext';
 type ColorPickerChangeHandler = (color: string) => void;
 
 export interface ColorPickerProps extends Themeable {
@@ -57,7 +57,7 @@ export const colorPickerFactory = <T extends ColorPickerProps>(
           <div
             {...arrowProps}
             data-placement={placement}
-            className={`ColorPicker__arrow ColorPicker__arrow--${theme === GrafanaTheme.Light ? 'light' : 'dark'}`}
+            className={`ColorPicker__arrow ColorPicker__arrow--${theme.type === GrafanaThemeType.Light ? 'light' : 'dark'}`}
           />
         );
       };
@@ -95,7 +95,7 @@ export const colorPickerFactory = <T extends ColorPickerProps>(
                       <div
                         className="sp-preview-inner"
                         style={{
-                          backgroundColor: getColorFromHexRgbOrName(this.props.color || '#000000', theme),
+                          backgroundColor: getColorFromHexRgbOrName(this.props.color || '#000000', theme.type),
                         }}
                       />
                     </div>
@@ -110,5 +110,5 @@ export const colorPickerFactory = <T extends ColorPickerProps>(
   };
 };
 
-export const ColorPicker = colorPickerFactory(ColorPickerPopover, 'ColorPicker');
-export const SeriesColorPicker = colorPickerFactory(SeriesColorPickerPopover, 'SeriesColorPicker');
+export const ColorPicker = withTheme(colorPickerFactory(ColorPickerPopover, 'ColorPicker'));
+export const SeriesColorPicker = withTheme(colorPickerFactory(SeriesColorPickerPopover, 'SeriesColorPicker'));

+ 6 - 5
packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.test.tsx

@@ -4,7 +4,8 @@ import { ColorPickerPopover } from './ColorPickerPopover';
 import { getColorDefinitionByName, getNamedColorPalette } from '../../utils/namedColorsPalette';
 import { ColorSwatch } from './NamedColorsGroup';
 import { flatten } from 'lodash';
-import { GrafanaTheme } from '../../types';
+import { GrafanaThemeType } from '../../types';
+import { getTheme } from '../../themes';
 
 const allColors = flatten(Array.from(getNamedColorPalette().values()));
 
@@ -14,7 +15,7 @@ describe('ColorPickerPopover', () => {
 
   describe('rendering', () => {
     it('should render provided color as selected if color provided by name', () => {
-      const wrapper = mount(<ColorPickerPopover color={BasicGreen.name} onChange={() => {}} />);
+      const wrapper = mount(<ColorPickerPopover color={BasicGreen.name} onChange={() => {}} theme={getTheme()}/>);
       const selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicGreen.name);
       const notSelectedSwatches = wrapper.find(ColorSwatch).filterWhere(node => node.prop('isSelected') === false);
 
@@ -24,7 +25,7 @@ describe('ColorPickerPopover', () => {
     });
 
     it('should render provided color as selected if color provided by hex', () => {
-      const wrapper = mount(<ColorPickerPopover color={BasicGreen.variants.dark} onChange={() => {}} />);
+      const wrapper = mount(<ColorPickerPopover color={BasicGreen.variants.dark} onChange={() => {}} theme={getTheme()} />);
       const selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicGreen.name);
       const notSelectedSwatches = wrapper.find(ColorSwatch).filterWhere(node => node.prop('isSelected') === false);
 
@@ -45,7 +46,7 @@ describe('ColorPickerPopover', () => {
 
     it('should pass hex color value to onChange prop by default', () => {
       wrapper = mount(
-        <ColorPickerPopover color={BasicGreen.variants.dark} onChange={onChangeSpy} theme={GrafanaTheme.Light} />
+        <ColorPickerPopover color={BasicGreen.variants.dark} onChange={onChangeSpy} theme={getTheme(GrafanaThemeType.Light)} />
       );
       const basicBlueSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicBlue.name);
 
@@ -61,7 +62,7 @@ describe('ColorPickerPopover', () => {
           enableNamedColors
           color={BasicGreen.variants.dark}
           onChange={onChangeSpy}
-          theme={GrafanaTheme.Light}
+          theme={getTheme(GrafanaThemeType.Light)}
         />
       );
       const basicBlueSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicBlue.name);

+ 10 - 18
packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx

@@ -2,9 +2,9 @@ import React from 'react';
 import { NamedColorsPalette } from './NamedColorsPalette';
 import { getColorName, getColorFromHexRgbOrName } from '../../utils/namedColorsPalette';
 import { ColorPickerProps, warnAboutColorPickerPropsDeprecation } from './ColorPicker';
-import { GrafanaTheme } from '../../types';
 import { PopperContentProps } from '../Tooltip/PopperController';
 import SpectrumPalette from './SpectrumPalette';
+import { GrafanaThemeType } from '@grafana/ui';
 
 export interface Props<T> extends ColorPickerProps, PopperContentProps {
   customPickers?: T;
@@ -43,7 +43,7 @@ export class ColorPickerPopover<T extends CustomPickersDescriptor> extends React
     if (enableNamedColors) {
       return changeHandler(color);
     }
-    changeHandler(getColorFromHexRgbOrName(color, theme));
+    changeHandler(getColorFromHexRgbOrName(color, theme.type));
   };
 
   handleTabChange = (tab: PickerType | keyof T) => {
@@ -58,7 +58,9 @@ export class ColorPickerPopover<T extends CustomPickersDescriptor> extends React
       case 'spectrum':
         return <SpectrumPalette color={color} onChange={this.handleChange} theme={theme} />;
       case 'palette':
-        return <NamedColorsPalette color={getColorName(color, theme)} onChange={this.handleChange} theme={theme} />;
+        return (
+          <NamedColorsPalette color={getColorName(color, theme.type)} onChange={this.handleChange} theme={theme} />
+        );
       default:
         return this.renderCustomPicker(activePicker);
     }
@@ -88,11 +90,7 @@ export class ColorPickerPopover<T extends CustomPickersDescriptor> extends React
       <>
         {Object.keys(customPickers).map(key => {
           return (
-            <div
-              className={this.getTabClassName(key)}
-              onClick={this.handleTabChange(key)}
-              key={key}
-            >
+            <div className={this.getTabClassName(key)} onClick={this.handleTabChange(key)} key={key}>
               {customPickers[key].name}
             </div>
           );
@@ -103,21 +101,14 @@ export class ColorPickerPopover<T extends CustomPickersDescriptor> extends React
 
   render() {
     const { theme } = this.props;
-    const colorPickerTheme = theme || GrafanaTheme.Dark;
-
+    const colorPickerTheme = theme.type || GrafanaThemeType.Dark;
     return (
       <div className={`ColorPickerPopover ColorPickerPopover--${colorPickerTheme}`}>
         <div className="ColorPickerPopover__tabs">
-          <div
-            className={this.getTabClassName('palette')}
-            onClick={this.handleTabChange('palette')}
-          >
+          <div className={this.getTabClassName('palette')} onClick={this.handleTabChange('palette')}>
             Colors
           </div>
-          <div
-            className={this.getTabClassName('spectrum')}
-            onClick={this.handleTabChange('spectrum')}
-          >
+          <div className={this.getTabClassName('spectrum')} onClick={this.handleTabChange('spectrum')}>
             Custom
           </div>
           {this.renderCustomPickerTabs()}
@@ -128,3 +119,4 @@ export class ColorPickerPopover<T extends CustomPickersDescriptor> extends React
     );
   }
 }
+

+ 5 - 4
packages/grafana-ui/src/components/ColorPicker/NamedColorsGroup.tsx

@@ -1,5 +1,5 @@
 import React, { FunctionComponent } from 'react';
-import { Themeable, GrafanaTheme } from '../../types';
+import { Themeable, GrafanaThemeType } from '../../types';
 import { ColorDefinition, getColorForTheme } from '../../utils/namedColorsPalette';
 import { Color } from 'csstype';
 import { find, upperFirst } from 'lodash';
@@ -28,7 +28,8 @@ export const ColorSwatch: FunctionComponent<ColorSwatchProps> = ({
 }) => {
   const isSmall = variant === ColorSwatchVariant.Small;
   const swatchSize = isSmall ? '16px' : '32px';
-  const selectedSwatchBorder = theme === GrafanaTheme.Light ? '#ffffff' : '#1A1B1F';
+  const selectedSwatchBorder = theme.type === GrafanaThemeType.Light ? '#ffffff' : '#1A1B1F';
+
   const swatchStyles = {
     width: swatchSize,
     height: swatchSize,
@@ -76,7 +77,7 @@ const NamedColorsGroup: FunctionComponent<NamedColorsGroupProps> = ({
           key={primaryColor.name}
           isSelected={primaryColor.name === selectedColor}
           variant={ColorSwatchVariant.Large}
-          color={getColorForTheme(primaryColor, theme)}
+          color={getColorForTheme(primaryColor, theme.type)}
           label={upperFirst(primaryColor.hue)}
           onClick={() => onColorSelect(primaryColor)}
           theme={theme}
@@ -95,7 +96,7 @@ const NamedColorsGroup: FunctionComponent<NamedColorsGroupProps> = ({
                 <ColorSwatch
                   key={color.name}
                   isSelected={color.name === selectedColor}
-                  color={getColorForTheme(color, theme)}
+                  color={getColorForTheme(color, theme.type)}
                   onClick={() => onColorSelect(color)}
                   theme={theme}
                 />

+ 5 - 4
packages/grafana-ui/src/components/ColorPicker/NamedColorsPalette.test.tsx

@@ -3,7 +3,8 @@ import { mount, ReactWrapper } from 'enzyme';
 import { NamedColorsPalette } from './NamedColorsPalette';
 import { ColorSwatch } from './NamedColorsGroup';
 import { getColorDefinitionByName } from '../../utils';
-import { GrafanaTheme } from '../../types';
+import { getTheme } from '../../themes';
+import { GrafanaThemeType } from '../../types';
 
 describe('NamedColorsPalette', () => {
 
@@ -17,18 +18,18 @@ describe('NamedColorsPalette', () => {
     });
 
     it('should render provided color variant specific for theme', () => {
-      wrapper = mount(<NamedColorsPalette color={BasicGreen.name} theme={GrafanaTheme.Dark} onChange={() => {}} />);
+      wrapper = mount(<NamedColorsPalette color={BasicGreen.name} theme={getTheme()} onChange={() => {}} />);
       selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicGreen.name);
       expect(selectedSwatch.prop('color')).toBe(BasicGreen.variants.dark);
 
       wrapper.unmount();
-      wrapper = mount(<NamedColorsPalette color={BasicGreen.name} theme={GrafanaTheme.Light} onChange={() => {}} />);
+      wrapper = mount(<NamedColorsPalette color={BasicGreen.name} theme={getTheme(GrafanaThemeType.Light)} onChange={() => {}} />);
       selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicGreen.name);
       expect(selectedSwatch.prop('color')).toBe(BasicGreen.variants.light);
     });
 
     it('should render dar variant of provided color when theme not provided', () => {
-      wrapper = mount(<NamedColorsPalette color={BasicGreen.name} onChange={() => {}} />);
+      wrapper = mount(<NamedColorsPalette color={BasicGreen.name} onChange={() => {}} theme={getTheme()}/>);
       selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicGreen.name);
       expect(selectedSwatch.prop('color')).toBe(BasicGreen.variants.dark);
     });

+ 4 - 1
packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx

@@ -4,6 +4,7 @@ import { ColorPickerPopover } from './ColorPickerPopover';
 import { ColorPickerProps } from './ColorPicker';
 import { PopperContentProps } from '../Tooltip/PopperController';
 import { Switch } from '../Switch/Switch';
+import { withTheme } from '../../themes/ThemeContext';
 
 export interface SeriesColorPickerPopoverProps extends ColorPickerProps, PopperContentProps {
   yaxis?: number;
@@ -12,7 +13,6 @@ export interface SeriesColorPickerPopoverProps extends ColorPickerProps, PopperC
 
 export const SeriesColorPickerPopover: FunctionComponent<SeriesColorPickerPopoverProps> = props => {
   const { yaxis, onToggleAxis, color, ...colorPickerProps } = props;
-
   return (
     <ColorPickerPopover
       {...colorPickerProps}
@@ -85,3 +85,6 @@ export class AxisSelector extends React.PureComponent<AxisSelectorProps, AxisSel
     );
   }
 }
+
+// This component is to enable SeriecColorPickerPopover usage via series-color-picker-popover directive
+export const SeriesColorPickerPopoverWithTheme = withTheme(SeriesColorPickerPopover);

+ 2 - 2
packages/grafana-ui/src/components/ColorPicker/SpectrumPalette.tsx

@@ -13,7 +13,7 @@ export interface SpectrumPaletteProps extends Themeable {
   onChange: (color: string) => void;
 }
 
-const renderPointer = (theme?: GrafanaTheme) => (props: SpectrumPalettePointerProps) => (
+const renderPointer = (theme: GrafanaTheme) => (props: SpectrumPalettePointerProps) => (
   <SpectrumPalettePointer {...props} theme={theme} />
 );
 
@@ -92,7 +92,7 @@ const SpectrumPalette: React.FunctionComponent<SpectrumPaletteProps> = ({ color,
         }}
         theme={theme}
       />
-      <ColorInput color={color} onChange={onChange} style={{ marginTop: '16px' }} />
+      <ColorInput theme={theme} color={color} onChange={onChange} style={{ marginTop: '16px' }} />
     </div>
   );
 };

+ 2 - 2
packages/grafana-ui/src/components/ColorPicker/SpectrumPalettePointer.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { GrafanaTheme, Themeable } from '../../types';
+import { GrafanaThemeType, Themeable } from '../../types';
 
 export interface SpectrumPalettePointerProps extends Themeable {
   direction?: string;
@@ -17,7 +17,7 @@ const SpectrumPalettePointer: React.FunctionComponent<SpectrumPalettePointerProp
     },
   };
 
-  const pointerColor = theme === GrafanaTheme.Light ? '#3F444D' : '#8E8E8E';
+  const pointerColor = theme.type === GrafanaThemeType.Light ? '#3F444D' : '#8E8E8E';
 
   let pointerStyles: React.CSSProperties = {
     position: 'absolute',

+ 2 - 0
packages/grafana-ui/src/components/Gauge/Gauge.test.tsx

@@ -3,6 +3,7 @@ import { shallow } from 'enzyme';
 
 import { Gauge, Props } from './Gauge';
 import { ValueMapping, MappingType } from '../../types';
+import { getTheme } from '../../themes';
 
 jest.mock('jquery', () => ({
   plot: jest.fn(),
@@ -24,6 +25,7 @@ const setup = (propOverrides?: object) => {
     width: 300,
     value: 25,
     decimals: 0,
+    theme: getTheme()
   };
 
   Object.assign(props, propOverrides);

+ 12 - 11
packages/grafana-ui/src/components/Gauge/Gauge.tsx

@@ -1,13 +1,14 @@
 import React, { PureComponent } from 'react';
 import $ from 'jquery';
 
-import { ValueMapping, Threshold, BasicGaugeColor, GrafanaTheme } from '../../types';
+import { ValueMapping, Threshold, BasicGaugeColor, GrafanaThemeType } from '../../types';
 import { getMappedValue } from '../../utils/valueMappings';
 import { getColorFromHexRgbOrName, getValueFormat } from '../../utils';
+import { Themeable } from '../../index';
 
 type TimeSeriesValue = string | number | null;
 
-export interface Props {
+export interface Props extends Themeable {
   decimals: number;
   height: number;
   valueMappings: ValueMapping[];
@@ -22,7 +23,6 @@ export interface Props {
   unit: string;
   width: number;
   value: number;
-  theme?: GrafanaTheme;
 }
 
 const FONT_SCALE = 1;
@@ -41,7 +41,7 @@ export class Gauge extends PureComponent<Props> {
     thresholds: [],
     unit: 'none',
     stat: 'avg',
-    theme: GrafanaTheme.Dark,
+    theme: GrafanaThemeType.Dark,
   };
 
   componentDidMount() {
@@ -77,19 +77,19 @@ export class Gauge extends PureComponent<Props> {
     const { thresholds, theme } = this.props;
 
     if (thresholds.length === 1) {
-      return getColorFromHexRgbOrName(thresholds[0].color, theme);
+      return getColorFromHexRgbOrName(thresholds[0].color, theme.type);
     }
 
     const atThreshold = thresholds.filter(threshold => (value as number) === threshold.value)[0];
     if (atThreshold) {
-      return getColorFromHexRgbOrName(atThreshold.color, theme);
+      return getColorFromHexRgbOrName(atThreshold.color, theme.type);
     }
 
     const belowThreshold = thresholds.filter(threshold => (value as number) > threshold.value);
 
     if (belowThreshold.length > 0) {
       const nearestThreshold = belowThreshold.sort((t1, t2) => t2.value - t1.value)[0];
-      return getColorFromHexRgbOrName(nearestThreshold.color, theme);
+      return getColorFromHexRgbOrName(nearestThreshold.color, theme.type);
     }
 
     return BasicGaugeColor.Red;
@@ -104,13 +104,13 @@ export class Gauge extends PureComponent<Props> {
     return [
       ...thresholdsSortedByIndex.map(threshold => {
         if (threshold.index === 0) {
-          return { value: minValue, color: getColorFromHexRgbOrName(threshold.color, theme) };
+          return { value: minValue, color: getColorFromHexRgbOrName(threshold.color, theme.type) };
         }
 
         const previousThreshold = thresholdsSortedByIndex[threshold.index - 1];
-        return { value: threshold.value, color: getColorFromHexRgbOrName(previousThreshold.color, theme) };
+        return { value: threshold.value, color: getColorFromHexRgbOrName(previousThreshold.color, theme.type) };
       }),
-      { value: maxValue, color: getColorFromHexRgbOrName(lastThreshold.color, theme) },
+      { value: maxValue, color: getColorFromHexRgbOrName(lastThreshold.color, theme.type) },
     ];
   }
 
@@ -126,7 +126,8 @@ export class Gauge extends PureComponent<Props> {
 
     const formattedValue = this.formatValue(value) as string;
     const dimension = Math.min(width, height * 1.3);
-    const backgroundColor = theme === GrafanaTheme.Light ? 'rgb(230,230,230)' : 'rgb(38,38,38)';
+    const backgroundColor = theme.type === GrafanaThemeType.Light ? 'rgb(230,230,230)' : theme.colors.dark3;
+
     const gaugeWidthReduceRatio = showThresholdLabels ? 1.5 : 1;
     const gaugeWidth = Math.min(dimension / 6, 60) / gaugeWidthReduceRatio;
     const thresholdMarkersWidth = gaugeWidth / 5;

+ 33 - 22
packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx

@@ -1,11 +1,11 @@
 import React, { PureComponent } from 'react';
-import { Threshold, Themeable } from '../../types';
+import { Threshold } from '../../types';
 import { ColorPicker } from '../ColorPicker/ColorPicker';
 import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup';
 import { colors } from '../../utils';
-import { getColorFromHexRgbOrName } from '@grafana/ui';
+import { getColorFromHexRgbOrName, ThemeContext } from '@grafana/ui';
 
-export interface Props extends Themeable {
+export interface Props {
   thresholds: Threshold[];
   onChange: (thresholds: Threshold[]) => void;
 }
@@ -164,7 +164,10 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
         <div className="thresholds-row-input-inner-color">
           {threshold.color && (
             <div className="thresholds-row-input-inner-color-colorpicker">
-              <ColorPicker color={threshold.color} onChange={color => this.onChangeThresholdColor(threshold, color)} />
+              <ColorPicker
+                color={threshold.color}
+                onChange={color => this.onChangeThresholdColor(threshold, color)}
+              />
             </div>
           )}
         </div>
@@ -188,27 +191,35 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
 
   render() {
     const { thresholds } = this.state;
-    const { theme } = this.props;
 
     return (
-      <PanelOptionsGroup title="Thresholds">
-        <div className="thresholds">
-          {thresholds.map((threshold, index) => {
-            return (
-              <div className="thresholds-row" key={`${threshold.index}-${index}`}>
-                <div className="thresholds-row-add-button" onClick={() => this.onAddThreshold(threshold.index + 1)}>
-                  <i className="fa fa-plus" />
-                </div>
-                <div
-                  className="thresholds-row-color-indicator"
-                  style={{ backgroundColor: getColorFromHexRgbOrName(threshold.color, theme) }}
-                />
-                <div className="thresholds-row-input">{this.renderInput(threshold)}</div>
+      <ThemeContext.Consumer>
+        {theme => {
+          return (
+            <PanelOptionsGroup title="Thresholds">
+              <div className="thresholds">
+                {thresholds.map((threshold, index) => {
+                  return (
+                    <div className="thresholds-row" key={`${threshold.index}-${index}`}>
+                      <div
+                        className="thresholds-row-add-button"
+                        onClick={() => this.onAddThreshold(threshold.index + 1)}
+                      >
+                        <i className="fa fa-plus" />
+                      </div>
+                      <div
+                        className="thresholds-row-color-indicator"
+                        style={{ backgroundColor: getColorFromHexRgbOrName(threshold.color, theme.type) }}
+                      />
+                      <div className="thresholds-row-input">{this.renderInput(threshold)}</div>
+                    </div>
+                  );
+                })}
               </div>
-            );
-          })}
-        </div>
-      </PanelOptionsGroup>
+            </PanelOptionsGroup>
+          );
+        }}
+      </ThemeContext.Consumer>
     );
   }
 }

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

@@ -14,8 +14,8 @@ export { FormLabel } from './FormLabel/FormLabel';
 export { FormField } from './FormField/FormField';
 
 export { LoadingPlaceholder } from './LoadingPlaceholder/LoadingPlaceholder';
-export {  ColorPicker, SeriesColorPicker } from './ColorPicker/ColorPicker';
-export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover';
+export { ColorPicker, SeriesColorPicker } from './ColorPicker/ColorPicker';
+export { SeriesColorPickerPopover, SeriesColorPickerPopoverWithTheme } from './ColorPicker/SeriesColorPickerPopover';
 export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor';
 export { Graph } from './Graph/Graph';
 export { PanelOptionsGroup } from './PanelOptionsGroup/PanelOptionsGroup';

+ 8 - 8
packages/grafana-ui/src/utils/namedColorsPalette.test.ts

@@ -5,20 +5,20 @@ import {
   getColorFromHexRgbOrName,
   getColorDefinitionByName,
 } from './namedColorsPalette';
-import { GrafanaTheme } from '../types/index';
+import { GrafanaThemeType } from '../types/index';
 
 describe('colors', () => {
   const SemiDarkBlue = getColorDefinitionByName('semi-dark-blue');
 
   describe('getColorDefinition', () => {
     it('returns undefined for unknown hex', () => {
-      expect(getColorDefinition('#ff0000', GrafanaTheme.Light)).toBeUndefined();
-      expect(getColorDefinition('#ff0000', GrafanaTheme.Dark)).toBeUndefined();
+      expect(getColorDefinition('#ff0000', GrafanaThemeType.Light)).toBeUndefined();
+      expect(getColorDefinition('#ff0000', GrafanaThemeType.Dark)).toBeUndefined();
     });
 
     it('returns definition for known hex', () => {
-      expect(getColorDefinition(SemiDarkBlue.variants.light, GrafanaTheme.Light)).toEqual(SemiDarkBlue);
-      expect(getColorDefinition(SemiDarkBlue.variants.dark, GrafanaTheme.Dark)).toEqual(SemiDarkBlue);
+      expect(getColorDefinition(SemiDarkBlue.variants.light, GrafanaThemeType.Light)).toEqual(SemiDarkBlue);
+      expect(getColorDefinition(SemiDarkBlue.variants.dark, GrafanaThemeType.Dark)).toEqual(SemiDarkBlue);
     });
   });
 
@@ -28,8 +28,8 @@ describe('colors', () => {
     });
 
     it('returns name for known hex', () => {
-      expect(getColorName(SemiDarkBlue.variants.light, GrafanaTheme.Light)).toEqual(SemiDarkBlue.name);
-      expect(getColorName(SemiDarkBlue.variants.dark, GrafanaTheme.Dark)).toEqual(SemiDarkBlue.name);
+      expect(getColorName(SemiDarkBlue.variants.light, GrafanaThemeType.Light)).toEqual(SemiDarkBlue.name);
+      expect(getColorName(SemiDarkBlue.variants.dark, GrafanaThemeType.Dark)).toEqual(SemiDarkBlue.name);
     });
   });
 
@@ -53,7 +53,7 @@ describe('colors', () => {
     });
 
     it("returns correct variant's hex for known color if theme specified", () => {
-      expect(getColorFromHexRgbOrName(SemiDarkBlue.name, GrafanaTheme.Light)).toBe(SemiDarkBlue.variants.light);
+      expect(getColorFromHexRgbOrName(SemiDarkBlue.name, GrafanaThemeType.Light)).toBe(SemiDarkBlue.variants.light);
     });
 
     it('returns color if specified as hex or rgb/a', () => {

+ 7 - 7
packages/grafana-ui/src/utils/namedColorsPalette.ts

@@ -1,5 +1,5 @@
 import { flatten } from 'lodash';
-import { GrafanaTheme } from '../types';
+import { GrafanaThemeType } from '../types';
 
 type Hue = 'green' | 'yellow' | 'red' | 'blue' | 'orange' | 'purple';
 
@@ -68,7 +68,7 @@ export const getColorDefinitionByName = (name: Color): ColorDefinition => {
   return flatten(Array.from(getNamedColorPalette().values())).filter(definition => definition.name === name)[0];
 };
 
-export const getColorDefinition = (hex: string, theme: GrafanaTheme): ColorDefinition | undefined => {
+export const getColorDefinition = (hex: string, theme: GrafanaThemeType): ColorDefinition | undefined => {
   return flatten(Array.from(getNamedColorPalette().values())).filter(definition => definition.variants[theme] === hex)[0];
 };
 
@@ -77,7 +77,7 @@ const isHex = (color: string) => {
   return hexRegex.test(color);
 };
 
-export const getColorName = (color?: string, theme?: GrafanaTheme): Color | undefined => {
+export const getColorName = (color?: string, theme?: GrafanaThemeType): Color | undefined => {
   if (!color) {
     return undefined;
   }
@@ -86,7 +86,7 @@ export const getColorName = (color?: string, theme?: GrafanaTheme): Color | unde
     return undefined;
   }
   if (isHex(color)) {
-    const definition = getColorDefinition(color, theme || GrafanaTheme.Dark);
+    const definition = getColorDefinition(color, theme || GrafanaThemeType.Dark);
     return definition ? definition.name : undefined;
   }
 
@@ -98,7 +98,7 @@ export const getColorByName = (colorName: string) => {
   return definition.length > 0 ? definition[0] : undefined;
 };
 
-export const getColorFromHexRgbOrName = (color: string, theme?: GrafanaTheme): string => {
+export const getColorFromHexRgbOrName = (color: string, theme?: GrafanaThemeType): string => {
   if (color.indexOf('rgb') > -1 || isHex(color)) {
     return color;
   }
@@ -112,14 +112,14 @@ export const getColorFromHexRgbOrName = (color: string, theme?: GrafanaTheme): s
   return theme ? colorDefinition.variants[theme] : colorDefinition.variants.dark;
 };
 
-export const getColorForTheme = (color: ColorDefinition, theme?: GrafanaTheme) => {
+export const getColorForTheme = (color: ColorDefinition, theme?: GrafanaThemeType) => {
   return theme ? color.variants[theme] : color.variants.dark;
 };
 
 const buildNamedColorsPalette = () => {
   const palette = new Map<Hue, ColorDefinition[]>();
 
-    const BasicGreen = buildColorDefinition('green', 'green', ['#56A64B', '#73BF69'], true);
+  const BasicGreen = buildColorDefinition('green', 'green', ['#56A64B', '#73BF69'], true);
   const DarkGreen = buildColorDefinition('green', 'dark-green', ['#19730E', '#37872D']);
   const SemiDarkGreen = buildColorDefinition('green', 'semi-dark-green', ['#37872D', '#56A64B']);
   const LightGreen = buildColorDefinition('green', 'light-green', ['#73BF69', '#96D98D']);

+ 2 - 2
public/app/core/angular_wrappers.ts

@@ -9,7 +9,7 @@ import { TagFilter } from './components/TagFilter/TagFilter';
 import { SideMenu } from './components/sidemenu/SideMenu';
 import { MetricSelect } from './components/Select/MetricSelect';
 import AppNotificationList from './components/AppNotifications/AppNotificationList';
-import { ColorPicker, SeriesColorPickerPopover } from '@grafana/ui';
+import { ColorPicker, SeriesColorPickerPopoverWithTheme } from '@grafana/ui';
 
 export function registerAngularDirectives() {
   react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
@@ -27,7 +27,7 @@ export function registerAngularDirectives() {
     'color',
     ['onChange', { watchDepth: 'reference', wrapApply: true }],
   ]);
-  react2AngularDirective('seriesColorPickerPopover', SeriesColorPickerPopover, [
+  react2AngularDirective('seriesColorPickerPopover', SeriesColorPickerPopoverWithTheme, [
     'color',
     'series',
     'onColorChange',

+ 12 - 7
public/app/core/utils/ConfigProvider.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import config, { Settings } from 'app/core/config';
-import { GrafanaTheme } from '@grafana/ui';
+import { GrafanaThemeType, ThemeContext, getTheme } from '@grafana/ui';
 
 export const ConfigContext = React.createContext<Settings>(config);
 export const ConfigConsumer = ConfigContext.Consumer;
@@ -13,16 +13,21 @@ export const provideConfig = (component: React.ComponentType<any>) => {
   return ConfigProvider;
 };
 
-interface ThemeProviderProps {
-  children: (theme: GrafanaTheme) => JSX.Element;
-}
+export const getCurrentThemeName = () =>
+  config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark;
+export const getCurrentTheme = () => getTheme(getCurrentThemeName());
 
-export const ThemeProvider = ({ children }: ThemeProviderProps) => {
+export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
   return (
     <ConfigConsumer>
-      {({ bootData }) => {
-        return children(bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark);
+      {config => {
+        const currentTheme = getCurrentThemeName();
+        return <ThemeContext.Provider value={getTheme(currentTheme)}>{children}</ThemeContext.Provider>;
       }}
     </ConfigConsumer>
   );
 };
+
+export const provideTheme = (component: React.ComponentType<any>) => {
+  return provideConfig((props: any) => <ThemeProvider>{React.createElement(component, { ...props })}</ThemeProvider>);
+};

+ 2 - 2
public/app/core/utils/react2angular.ts

@@ -1,11 +1,11 @@
 import coreModule from 'app/core/core_module';
-import { provideConfig } from 'app/core/utils/ConfigProvider';
+import { provideTheme } from 'app/core/utils/ConfigProvider';
 
 export function react2AngularDirective(name: string, component: any, options: any) {
   coreModule.directive(name, [
     'reactDirective',
     reactDirective => {
-      return reactDirective(provideConfig(component), options);
+      return reactDirective(provideTheme(component), options);
     },
   ]);
 }

+ 3 - 4
public/app/plugins/panel/gauge/GaugePanel.tsx

@@ -2,7 +2,7 @@
 import React, { PureComponent } from 'react';
 
 // Services & Utils
-import { processTimeSeries } from '@grafana/ui';
+import { processTimeSeries, ThemeContext } from '@grafana/ui';
 
 // Components
 import { Gauge } from '@grafana/ui';
@@ -10,7 +10,6 @@ import { Gauge } from '@grafana/ui';
 // Types
 import { GaugeOptions } from './types';
 import { PanelProps, NullValueMode, TimeSeriesValue } from '@grafana/ui/src/types';
-import { ThemeProvider } from 'app/core/utils/ConfigProvider';
 
 interface Props extends PanelProps<GaugeOptions> {}
 
@@ -38,7 +37,7 @@ export class GaugePanel extends PureComponent<Props> {
     }
 
     return (
-      <ThemeProvider>
+      <ThemeContext.Consumer>
         {theme => (
           <Gauge
             value={value}
@@ -50,7 +49,7 @@ export class GaugePanel extends PureComponent<Props> {
             theme={theme}
           />
         )}
-      </ThemeProvider>
+      </ThemeContext.Consumer>
     );
   }
 }

+ 9 - 17
public/app/plugins/panel/gauge/GaugePanelOptions.tsx

@@ -11,7 +11,6 @@ import {
 import ValueOptions from 'app/plugins/panel/gauge/ValueOptions';
 import GaugeOptionsEditor from './GaugeOptionsEditor';
 import { GaugeOptions } from './types';
-import { ThemeProvider } from 'app/core/utils/ConfigProvider';
 
 export const defaultProps = {
   options: {
@@ -46,24 +45,17 @@ export default class GaugePanelOptions extends PureComponent<PanelOptionsProps<G
 
   render() {
     const { onChange, options } = this.props;
+
     return (
-      <ThemeProvider>
-        {(theme) => (
-          <>
-            <PanelOptionsGrid>
-              <ValueOptions onChange={onChange} options={options} />
-              <GaugeOptionsEditor onChange={onChange} options={options} />
-              <ThresholdsEditor
-                onChange={this.onThresholdsChanged}
-                thresholds={options.thresholds}
-                theme={theme}
-              />
-            </PanelOptionsGrid>
+      <>
+        <PanelOptionsGrid>
+          <ValueOptions onChange={onChange} options={options} />
+          <GaugeOptionsEditor onChange={onChange} options={options} />
+          <ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
+        </PanelOptionsGrid>
 
-            <ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={options.valueMappings} />
-          </>
-        )}
-      </ThemeProvider>
+        <ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={options.valueMappings} />
+      </>
     );
   }
 }

+ 12 - 19
public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx

@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
 import classNames from 'classnames';
 import { TimeSeries } from 'app/core/core';
 import { SeriesColorPicker } from '@grafana/ui';
-import { ThemeProvider } from 'app/core/utils/ConfigProvider';
+// import { ThemeProvider } from 'app/core/utils/ConfigProvider';
 
 export const LEGEND_STATS = ['min', 'max', 'avg', 'current', 'total'];
 
@@ -168,24 +168,17 @@ class LegendSeriesIcon extends PureComponent<LegendSeriesIconProps, LegendSeries
 
   render() {
     return (
-      <ThemeProvider>
-        {theme => {
-          return (
-            <SeriesColorPicker
-              yaxis={this.props.yaxis}
-              color={this.props.color}
-              onChange={this.props.onColorChange}
-              onToggleAxis={this.props.onToggleAxis}
-              theme={theme}
-              enableNamedColors
-            >
-              <span className="graph-legend-icon">
-                <SeriesIcon color={this.props.color} />
-              </span>
-            </SeriesColorPicker>
-          );
-        }}
-      </ThemeProvider>
+      <SeriesColorPicker
+        yaxis={this.props.yaxis}
+        color={this.props.color}
+        onChange={this.props.onColorChange}
+        onToggleAxis={this.props.onToggleAxis}
+        enableNamedColors
+      >
+        <span className="graph-legend-icon">
+          <SeriesIcon color={this.props.color} />
+        </span>
+      </SeriesColorPicker>
     );
   }
 }

+ 2 - 2
public/app/plugins/panel/graph/data_processor.ts

@@ -1,5 +1,5 @@
 import _ from 'lodash';
-import { colors, GrafanaTheme, getColorFromHexRgbOrName } from '@grafana/ui';
+import { colors, GrafanaThemeType, getColorFromHexRgbOrName } from '@grafana/ui';
 import TimeSeries from 'app/core/time_series2';
 import config from 'app/core/config';
 
@@ -113,7 +113,7 @@ export class DataProcessor {
     const series = new TimeSeries({
       datapoints: datapoints,
       alias: alias,
-      color: getColorFromHexRgbOrName(color, config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark),
+      color: getColorFromHexRgbOrName(color, config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark),
       unit: seriesData.unit,
     });
 

+ 4 - 3
public/app/plugins/panel/graph/graph.ts

@@ -25,7 +25,8 @@ import ReactDOM from 'react-dom';
 import { Legend, GraphLegendProps } from './Legend/Legend';
 
 import { GraphCtrl } from './module';
-import { GrafanaTheme, getValueFormat } from '@grafana/ui';
+import { GrafanaThemeType, getValueFormat } from '@grafana/ui';
+import { provideTheme } from 'app/core/utils/ConfigProvider';
 
 class GraphElement {
   ctrl: GraphCtrl;
@@ -53,7 +54,7 @@ class GraphElement {
     this.thresholdManager = new ThresholdManager(this.ctrl);
     this.timeRegionManager = new TimeRegionManager(
       this.ctrl,
-      config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark
+      config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark
     );
     this.tooltip = new GraphTooltip(this.elem, this.ctrl.dashboard, this.scope, () => {
       return this.sortedSeries;
@@ -109,7 +110,7 @@ class GraphElement {
       onToggleAxis: this.ctrl.onToggleAxis,
     };
 
-    const legendReactElem = React.createElement(Legend, legendProps);
+    const legendReactElem = React.createElement(provideTheme(Legend), legendProps);
     ReactDOM.render(legendReactElem, this.legendElem, () => this.renderPanel());
   }
 

+ 2 - 2
public/app/plugins/panel/graph/module.ts

@@ -10,7 +10,7 @@ import { MetricsPanelCtrl } from 'app/plugins/sdk';
 import { DataProcessor } from './data_processor';
 import { axesEditorComponent } from './axes_editor';
 import config from 'app/core/config';
-import { GrafanaTheme, getColorFromHexRgbOrName } from '@grafana/ui';
+import { GrafanaThemeType, getColorFromHexRgbOrName } from '@grafana/ui';
 
 class GraphCtrl extends MetricsPanelCtrl {
   static template = template;
@@ -244,7 +244,7 @@ class GraphCtrl extends MetricsPanelCtrl {
   }
 
   onColorChange = (series, color) => {
-    series.setColor(getColorFromHexRgbOrName(color, config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark));
+    series.setColor(getColorFromHexRgbOrName(color, config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark));
     this.panel.aliasColors[series.alias] = color;
     this.render();
   };

+ 4 - 4
public/app/plugins/panel/graph/time_region_manager.ts

@@ -1,7 +1,7 @@
 import 'vendor/flot/jquery.flot';
 import _ from 'lodash';
 import moment from 'moment';
-import { GrafanaTheme, getColorFromHexRgbOrName } from '@grafana/ui';
+import { GrafanaThemeType, getColorFromHexRgbOrName } from '@grafana/ui';
 
 type TimeRegionColorDefinition = {
   fill: string;
@@ -43,7 +43,7 @@ export function getColorModes() {
   });
 }
 
-function getColor(timeRegion, theme: GrafanaTheme): TimeRegionColorDefinition {
+function getColor(timeRegion, theme: GrafanaThemeType): TimeRegionColorDefinition {
   if (Object.keys(colorModes).indexOf(timeRegion.colorMode) === -1) {
     timeRegion.colorMode = 'red';
   }
@@ -58,7 +58,7 @@ function getColor(timeRegion, theme: GrafanaTheme): TimeRegionColorDefinition {
   const colorMode = colorModes[timeRegion.colorMode];
 
   if (colorMode.themeDependent === true) {
-    return theme === GrafanaTheme.Light ? colorMode.lightColor : colorMode.darkColor;
+    return theme === GrafanaThemeType.Light ? colorMode.lightColor : colorMode.darkColor;
   }
 
   return {
@@ -71,7 +71,7 @@ export class TimeRegionManager {
   plot: any;
   timeRegions: any;
 
-  constructor(private panelCtrl, private theme: GrafanaTheme = GrafanaTheme.Dark) {}
+  constructor(private panelCtrl, private theme: GrafanaThemeType = GrafanaThemeType.Dark) {}
 
   draw(plot) {
     this.timeRegions = this.panelCtrl.panel.timeRegions;

+ 2 - 2
public/app/plugins/panel/heatmap/color_legend.ts

@@ -5,7 +5,7 @@ import { contextSrv } from 'app/core/core';
 import { tickStep } from 'app/core/utils/ticks';
 import { getColorScale, getOpacityScale } from './color_scale';
 import coreModule from 'app/core/core_module';
-import { GrafanaTheme, getColorFromHexRgbOrName } from '@grafana/ui';
+import { GrafanaThemeType, getColorFromHexRgbOrName } from '@grafana/ui';
 
 const LEGEND_HEIGHT_PX = 6;
 const LEGEND_WIDTH_PX = 100;
@@ -250,7 +250,7 @@ function drawSimpleOpacityLegend(elem, options) {
       .attr('stroke-width', 0)
       .attr(
         'fill',
-        getColorFromHexRgbOrName(options.cardColor, contextSrv.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark)
+        getColorFromHexRgbOrName(options.cardColor, contextSrv.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark)
       )
       .style('opacity', d => legendOpacityScale(d));
   }

+ 2 - 2
public/app/plugins/panel/heatmap/rendering.ts

@@ -7,7 +7,7 @@ import * as ticksUtils from 'app/core/utils/ticks';
 import { HeatmapTooltip } from './heatmap_tooltip';
 import { mergeZeroBuckets } from './heatmap_data_converter';
 import { getColorScale, getOpacityScale } from './color_scale';
-import { GrafanaTheme, getColorFromHexRgbOrName, getValueFormat } from '@grafana/ui';
+import { GrafanaThemeType, getColorFromHexRgbOrName, getValueFormat } from '@grafana/ui';
 
 const MIN_CARD_SIZE = 1,
   CARD_PADDING = 1,
@@ -663,7 +663,7 @@ export class HeatmapRenderer {
     if (this.panel.color.mode === 'opacity') {
       return getColorFromHexRgbOrName(
         this.panel.color.cardColor,
-        contextSrv.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark
+        contextSrv.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark
       );
     } else {
       return this.colorScale(d.count);

+ 4 - 4
public/app/plugins/panel/singlestat/module.ts

@@ -8,7 +8,7 @@ import kbn from 'app/core/utils/kbn';
 import config from 'app/core/config';
 import TimeSeries from 'app/core/time_series2';
 import { MetricsPanelCtrl } from 'app/plugins/sdk';
-import { GrafanaTheme, getValueFormat, getColorFromHexRgbOrName } from '@grafana/ui';
+import { GrafanaThemeType, getValueFormat, getColorFromHexRgbOrName } from '@grafana/ui';
 
 class SingleStatCtrl extends MetricsPanelCtrl {
   static templateUrl = 'module.html';
@@ -590,7 +590,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
             lineWidth: 1,
             fillColor: getColorFromHexRgbOrName(
               panel.sparkline.fillColor,
-              config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark
+              config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark
             ),
           },
         },
@@ -610,7 +610,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
         data: data.flotpairs,
         color: getColorFromHexRgbOrName(
           panel.sparkline.lineColor,
-          config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark
+          config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark
         ),
       };
 
@@ -630,7 +630,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
 
       // Map panel colors to hex or rgb/a values
       data.colorMap = panel.colors.map(color =>
-        getColorFromHexRgbOrName(color, config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark)
+        getColorFromHexRgbOrName(color, config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark)
       );
 
       const body = panel.gauge.show ? '' : getBigValueHtml();

+ 2 - 2
public/app/plugins/panel/table/module.ts

@@ -6,7 +6,7 @@ import { transformDataToTable } from './transformers';
 import { tablePanelEditor } from './editor';
 import { columnOptionsTab } from './column_options';
 import { TableRenderer } from './renderer';
-import { GrafanaTheme } from '@grafana/ui';
+import { GrafanaThemeType } from '@grafana/ui';
 
 class TablePanelCtrl extends MetricsPanelCtrl {
   static templateUrl = 'module.html';
@@ -131,7 +131,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
       this.dashboard.isTimezoneUtc(),
       this.$sanitize,
       this.templateSrv,
-      config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark,
+      config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark,
     );
 
     return super.render(this.table);

+ 2 - 2
public/app/plugins/panel/table/renderer.ts

@@ -1,7 +1,7 @@
 import _ from 'lodash';
 import moment from 'moment';
 import kbn from 'app/core/utils/kbn';
-import { GrafanaTheme, getValueFormat, getColorFromHexRgbOrName } from '@grafana/ui';
+import { getValueFormat, getColorFromHexRgbOrName, GrafanaThemeType } from '@grafana/ui';
 
 export class TableRenderer {
   formatters: any[];
@@ -13,7 +13,7 @@ export class TableRenderer {
     private isUtc,
     private sanitize,
     private templateSrv,
-    private theme?: GrafanaTheme
+    private theme?: GrafanaThemeType
   ) {
     this.initColumns();
   }

+ 2 - 1
public/app/routes/ReactContainer.tsx

@@ -5,6 +5,7 @@ import { Provider } from 'react-redux';
 import coreModule from 'app/core/core_module';
 import { store } from 'app/store/store';
 import { ContextSrv } from 'app/core/services/context_srv';
+import { provideTheme } from 'app/core/utils/ConfigProvider';
 
 function WrapInProvider(store, Component, props) {
   return (
@@ -46,7 +47,7 @@ export function reactContainer(
         $scope: scope,
       };
 
-      ReactDOM.render(WrapInProvider(store, component, props), elem[0]);
+      ReactDOM.render(WrapInProvider(store, provideTheme(component), props), elem[0]);
 
       scope.$on('$destroy', () => {
         ReactDOM.unmountComponentAtNode(elem[0]);