ソースを参照

WIP Enable js defined theme to be used in SASS

Dominik Prokop 6 年 前
コミット
7626ce9922

+ 1 - 0
package.json

@@ -76,6 +76,7 @@
     "ng-annotate-webpack-plugin": "^0.3.0",
     "ngtemplate-loader": "^2.0.1",
     "node-sass": "^4.11.0",
+    "node-sass-utils": "^1.1.2",
     "npm": "^5.4.2",
     "optimize-css-assets-webpack-plugin": "^4.0.2",
     "phantomjs-prebuilt": "^2.1.15",

+ 1 - 0
packages/grafana-ui/src/index.ts

@@ -1,3 +1,4 @@
 export * from './components';
 export * from './types';
 export * from './utils';
+export * from './theme';

+ 116 - 0
packages/grafana-ui/src/theme.d.ts

@@ -0,0 +1,116 @@
+export interface GrafanaThemeType {
+  name: string;
+  // TODO: not sure if should be a part of theme
+  brakpoints: {
+    xs: string;
+    s: string;
+    m: string;
+    l: string;
+    xl: string;
+  };
+  typography: {
+    fontFamily: {
+      sansSerif: string;
+      serif: string;
+      monospace: string;
+    };
+    size: {
+      base: string;
+      xs: string;
+      s: string;
+      m: string;
+      l: string;
+    };
+    weight: {
+      light: number;
+      normal: number;
+      semibold: number;
+    };
+    lineHeight: {
+      xs: number; //1
+      s: number; //1.1
+      m: number; // 4/3
+      l: number; // 1.5
+    };
+    // TODO: Refactor to use size instead of custom defs
+    heading: {
+      h1: string;
+      h2: string;
+      h3: string;
+      h4: string;
+      h5: string;
+      h6: string;
+    };
+  };
+  spacing: {
+    xs: string;
+    s: string;
+    m: string;
+    l: string;
+    gutter: string;
+  };
+  border: {
+    radius: {
+      xs: string;
+      s: string;
+      m: string;
+    };
+  };
+  colors: {
+    black: string;
+    white: string;
+    dark1: string;
+    dark2: string;
+    dark3: string;
+    dark4: string;
+    dark5: string;
+    gray1: string;
+    gray2: string;
+    gray3: string;
+    gray4: string;
+    gray5: string;
+    gray6: string;
+    gray7: string;
+    grayBlue: string;
+    inputBlack: string;
+
+    // Accent colors
+    blue: string;
+    blueLight: string;
+    blueDark: string;
+    green: string;
+    red: string;
+    yellow: string;
+    pink: string;
+    purple: string;
+    variable: string;
+    orange: string;
+    queryRed: string;
+    queryGreen: string;
+    queryPurple: string;
+    queryKeyword: string;
+    queryOrange: string;
+
+    // Status colors
+    online: string;
+    warn: string;
+    critical: string;
+
+    // TODO: should this be a part of theme?
+    bodyBg: string;
+    pageBg: string;
+    bodyColor: string;
+    textColor: string;
+    textColorStrong: string;
+    textColorWeak: string;
+    textColorFaint: string;
+    textColorEmphasis: string;
+    linkColor: string;
+    linkColorDisabled: string;
+    linkColorHover: string;
+    linkColorExternal: string;
+    headingColor: string;
+  };
+}
+export function getTheme(): GrafanaThemeType
+export function mockTheme(themeMock: Partial<GrafanaThemeType>): () => void

+ 15 - 0
packages/grafana-ui/src/theme.js

@@ -0,0 +1,15 @@
+const darkTheme = require('./themes/dark');
+const lightTheme = require('./themes/light');
+
+const getTheme = name => (name === 'light' ? lightTheme : darkTheme);
+
+const mockTheme = mock => {
+  const originalGetTheme = getTheme;
+  getTheme = () => mock;
+  return () => (getTheme = originalGetTheme);
+};
+
+module.exports = {
+  getTheme,
+  mockTheme,
+};

+ 64 - 0
packages/grafana-ui/src/themes/dark.js

@@ -0,0 +1,64 @@
+
+
+const defaultTheme = require('./default');
+const tinycolor = require('tinycolor2');
+
+const basicColors = {
+  black: '#00ff00',
+  white: '#ffffff',
+  dark1: '#141414',
+  dark2: '#1f1f20',
+  dark3: '#262628',
+  dark4: '#333333',
+  dark5: '#444444',
+  gray1: '#555555',
+  gray2: '#8e8e8e',
+  gray3: '#b3b3b3',
+  gray4: '#d8d9da',
+  gray5: '#ececec',
+  gray6: '#f4f5f8',
+  gray7: '#fbfbfb',
+  grayBlue: '#212327',
+  blue: '#33b5e5',
+  blueDark: '#005f81',
+  blueLight: '#00a8e6', // not used in dark theme
+  green: '#299c46',
+  red: '#d44a3a',
+  yellow: '#ecbb13',
+  pink: '#ff4444',
+  purple: '#9933cc',
+  variable: '#32d1df',
+  orange: '#eb7b18',
+};
+
+const darkTheme = {
+  ...defaultTheme,
+  name: 'Grafana Dark',
+  colors:  {
+    ...basicColors,
+    inputBlack: '#09090b',
+    queryRed: '#e24d42',
+    queryGreen: '#74e680',
+    queryPurple: '#fe85fc',
+    queryKeyword: '#66d9ef',
+    queryOrange: 'eb7b18',
+    online: '#10a345',
+    warn: '#f79520',
+    critical: '#ed2e18',
+    bodyBg: '#171819',
+    pageBg: '#161719',
+    bodyColor: basicColors.gray4,
+    textColor: basicColors.gray4,
+    textColorStrong: basicColors.white,
+    textColorWeak: basicColors.gray2,
+    textColorEmphasis: basicColors.gray5,
+    textColorFaint: basicColors.dark5,
+    linkColor: new tinycolor(basicColors.white).darken(11).toString(),
+    linkColorDisabled: new tinycolor(basicColors.white).darken(11).toString(),
+    linkColorHover: basicColors.white,
+    linkColorExternal: basicColors.blue,
+    headingColor: new tinycolor(basicColors.white).darken(11).toString(),
+  }
+}
+
+module.exports = darkTheme;

+ 47 - 0
packages/grafana-ui/src/themes/default.js

@@ -0,0 +1,47 @@
+
+
+const theme = {
+  name: 'Grafana Default',
+  typography: {
+    fontFamily: {
+      sansSerif: "'Roboto', Helvetica, Arial, sans-serif;",
+      serif: "Georgia, 'Times New Roman', Times, serif;",
+      monospace: "Menlo, Monaco, Consolas, 'Courier New', monospace;"
+    },
+    size: {
+      base: '13px',
+      xs: '10px',
+      s: '12px',
+      m: '14px',
+      l: '18px',
+    },
+    heading: {
+      h1: '2rem',
+      h2: '1.75rem',
+      h3: '1.5rem',
+      h4: '1.3rem',
+      h5: '1.2rem',
+      h6: '1rem',
+    },
+    weight: {
+      light: 300,
+      normal: 400,
+      semibold: 500,
+    },
+    lineHeight: {
+      xs: 1,
+      s: 1.1,
+      m: 4/3,
+      l: 1.5
+    }
+  },
+  brakpoints: {
+    xs: '0',
+    s: '544px',
+    m: '768px',
+    l: '992px',
+    xl: '1200px'
+  }
+};
+
+module.exports = theme;

+ 65 - 0
packages/grafana-ui/src/themes/light.js

@@ -0,0 +1,65 @@
+// import { GrafanaThemeType } from "../theme";
+
+const defaultTheme = require('./default');
+const tinycolor = require('tinycolor2');
+
+const basicColors = {
+  black: '#000000',
+  white: '#ffffff',
+  dark1: '#13161d',
+  dark2: '#1e2028',
+  dark3: '#303133',
+  dark4: '#35373f',
+  dark5: '#41444b',
+  gray1: '#52545c',
+  gray2: '#767980',
+  gray3: '#acb6bf',
+  gray4: '#c7d0d9',
+  gray5: '#dde4ed',
+  gray6: '#e9edf2',
+  gray7: '#f7f8fa',
+  grayBlue: '#212327', // not used in light theme
+  blue: '#0083b3',
+  blueDark: '#005f81',
+  blueLight: '#00a8e6',
+  green: '#3aa655',
+  red: '#d44939',
+  yellow: '#ff851b',
+  pink: '#e671b8',
+  purple: '#9954bb',
+  variable: '#0083b3',
+  orange: '#ff7941',
+};
+
+const lightTheme/*: GrafanaThemeType*/ = {
+  ...defaultTheme,
+  name: 'Grafana Light',
+  colors:  {
+    ...basicColors,
+    variable: basicColors.blue,
+    inputBlack: '#09090b',
+    queryRed: basicColors.red,
+    queryGreen: basicColors.green,
+    queryPurple: basicColors.purple,
+    queryKeyword: basicColors.blue,
+    queryOrange: basicColors.orange,
+    online: '#01a64f',
+    warn: '#f79520',
+    critical: '#ec2128',
+    bodyBg: basicColors.gray7,
+    pageBg: basicColors.gray7,
+    bodyColor: basicColors.gray1,
+    textColor: basicColors.gray1,
+    textColorStrong: basicColors.dark2,
+    textColorWeak: basicColors.gray2,
+    textColorEmphasis: basicColors.gray5,
+    textColorFaint: basicColors.dark4,
+    linkColor: basicColors.gray1,
+    linkColorDisabled: new tinycolor(basicColors.gray1).lighten(30).toString(),
+    linkColorHover: new tinycolor(basicColors.gray1).darken(20).toString(),
+    linkColorExternal: basicColors.blueLight,
+    headingColor: basicColors.gray1,
+  }
+}
+
+module.exports = lightTheme;

+ 51 - 54
public/sass/_variables.dark.scss

@@ -3,73 +3,69 @@
 
 $theme-name: dark;
 
-// Grays
 // -------------------------
-$black: #000;
-
-// -------------------------
-$black: #000;
-$dark-1: #141414;
-$dark-2: #1f1f20;
-$dark-3: #262628;
-$dark-4: #333333;
-$dark-5: #444444;
-$gray-1: #555555;
-$gray-2: #8e8e8e;
-$gray-3: #b3b3b3;
-$gray-4: #d8d9da;
-$gray-5: #ececec;
-$gray-6: #f4f5f8;
-$gray-7: #fbfbfb;
-
-$gray-blue: #212327;
-$input-black: #09090b;
-
-$white: #fff;
+$black: getThemeVariable('colors.black', $theme-name);
+$dark-1: getThemeVariable('colors.dark1', $theme-name);
+$dark-2: getThemeVariable('colors.dark2', $theme-name);
+$dark-3: getThemeVariable('colors.dark3', $theme-name);
+$dark-4: getThemeVariable('colors.dark4', $theme-name);
+$dark-5: getThemeVariable('colors.dark5', $theme-name);
+$gray-1: getThemeVariable('colors.gray1', $theme-name);
+$gray-2: getThemeVariable('colors.gray2', $theme-name);
+$gray-3: getThemeVariable('colors.gray3', $theme-name);
+$gray-4: getThemeVariable('colors.gray4', $theme-name);
+$gray-5: getThemeVariable('colors.gray5', $theme-name);
+$gray-6: getThemeVariable('colors.gray6', $theme-name);
+$gray-7: getThemeVariable('colors.gray7', $theme-name);
+
+$gray-blue: getThemeVariable('colors.grayBlue', $theme-name);
+$input-black: getThemeVariable('colors.inputBlack', $theme-name);
+
+$white: getThemeVariable('colors.white', $theme-name);
 
 // Accent colors
 // -------------------------
-$blue: #33b5e5;
-$blue-dark: #005f81;
-$green: #299c46;
-$red: #d44a3a;
-$yellow: #ecbb13;
-$pink: #ff4444;
-$purple: #9933cc;
-$variable: #32d1df;
-$orange: #eb7b18;
+$blue: getThemeVariable('colors.blue', $theme-name);
+$blue-dark: getThemeVariable('colors.blueDark', $theme-name);
+$green: getThemeVariable('colors.green', $theme-name);
+$red: getThemeVariable('colors.red', $theme-name);
+$yellow: getThemeVariable('colors.yellow', $theme-name);
+$pink: getThemeVariable('colors.pink', $theme-name);
+$purple: getThemeVariable('colors.purple', $theme-name);
+$variable: getThemeVariable('colors.variable', $theme-name);
+$orange: getThemeVariable('colors.orange', $theme-name);
 
 $brand-primary: $orange;
 $brand-success: $green;
 $brand-warning: $brand-primary;
 $brand-danger: $red;
 
-$query-red: #e24d42;
-$query-green: #74e680;
-$query-purple: #fe85fc;
-$query-keyword: #66d9ef;
-$query-orange: $orange;
+$query-red: getThemeVariable('colors.queryRed', $theme-name);
+$query-green: getThemeVariable('colors.queryGreen', $theme-name);
+$query-purple: getThemeVariable('colors.queryPurple', $theme-name);
+$query-keyword: getThemeVariable('colors.queryKeyword', $theme-name);
+$query-orange: getThemeVariable('colors.queryOrange', $theme-name);
 
 // Status colors
 // -------------------------
-$online: #10a345;
-$warn: #f79520;
-$critical: #ed2e18;
+$online: getThemeVariable('colors.online', $theme-name);
+$warn: getThemeVariable('colors.warn', $theme-name);
+$critical: getThemeVariable('colors.critical', $theme-name);
 
 // Scaffolding
 // -------------------------
-$body-bg: rgb(23, 24, 25);
-$page-bg: rgb(22, 23, 25);
+$body-bg: getThemeVariable('colors.bodyBg', $theme-name);
+$page-bg: getThemeVariable('colors.pageBg', $theme-name);
 
-$body-color: $gray-4;
-$text-color: $gray-4;
-$text-color-strong: $white;
-$text-color-weak: $gray-2;
-$text-color-faint: $dark-5;
-$text-color-emphasis: $gray-5;
+$body-color: getThemeVariable('colors.bodyColor', $theme-name);
+$text-color: getThemeVariable('colors.textColor', $theme-name);
+$text-color-strong: getThemeVariable('colors.textColorStrong', $theme-name);
+$text-color-weak: getThemeVariable('colors.textColorWeak', $theme-name);
+$text-color-faint: getThemeVariable('colors.textColorFaint', $theme-name);
+$text-color-emphasis: getThemeVariable('colors.textColorEmphasis', $theme-name);
 
-$text-shadow-strong: 1px 1px 4px $black;
-$text-shadow-faint: 1px 1px 4px rgb(45, 45, 45);
+$text-shadow-strong: 1px 1px 4px getThemeVariable('colors.black', $theme-name);
+$text-shadow-faint: 1px 1px 4px #2d2d2d;
 
 // gradients
 $brand-gradient: linear-gradient(
@@ -84,10 +80,11 @@ $edit-gradient: linear-gradient(180deg, rgb(22, 23, 25) 50%, #090909);
 
 // Links
 // -------------------------
-$link-color: darken($white, 11%);
-$link-color-disabled: darken($link-color, 30%);
-$link-hover-color: $white;
-$external-link-color: $blue;
+$link-color: getThemeVariable('colors.linkColor', $theme-name);
+$link-color-disabled: getThemeVariable('colors.linkColorDisabled', $theme-name);
+$link-hover-color: getThemeVariable('colors.linkColorHover', $theme-name);
+
+$external-link-color: getThemeVariable('colors.linkColorExternal', $theme-name);
 
 // Typography
 // -------------------------
@@ -135,7 +132,7 @@ $list-item-shadow: $card-shadow;
 $empty-list-cta-bg: $gray-blue;
 
 // Scrollbars
-$scrollbarBackground: #404357;
+$scrollbarBackground: #aeb5df;
 $scrollbarBackground2: #3a3a3a;
 
 $scrollbarBorder: black;

+ 49 - 47
public/sass/_variables.light.scss

@@ -12,83 +12,85 @@ $theme-name: light;
 $black: #000;
 
 // -------------------------
-$black: #000;
-$dark-1: #13161d;
-$dark-2: #1e2028;
-$dark-3: #303133;
-$dark-4: #35373f;
-$dark-5: #41444b;
-$gray-1: #52545c;
-$gray-2: #767980;
-$gray-3: #acb6bf;
-$gray-4: #c7d0d9;
-$gray-5: #dde4ed;
-$gray-6: #e9edf2;
-$gray-7: #f7f8fa;
-
-$white: #fff;
+$black: getThemeVariable('colors.black', $theme-name);
+$dark-1: getThemeVariable('colors.dark1', $theme-name);
+$dark-2: getThemeVariable('colors.dark2', $theme-name);
+$dark-3: getThemeVariable('colors.dark3', $theme-name);
+$dark-4: getThemeVariable('colors.dark4', $theme-name);
+$dark-5: getThemeVariable('colors.dark5', $theme-name);
+$gray-1: getThemeVariable('colors.gray1', $theme-name);
+$gray-2: getThemeVariable('colors.gray2', $theme-name);
+$gray-3: getThemeVariable('colors.gray3', $theme-name);
+$gray-4: getThemeVariable('colors.gray4', $theme-name);
+$gray-5: getThemeVariable('colors.gray5', $theme-name);
+$gray-6: getThemeVariable('colors.gray6', $theme-name);
+$gray-7: getThemeVariable('colors.gray7', $theme-name);
+
+$white: getThemeVariable('colors.white', $theme-name);
 
 // Accent colors
 // -------------------------
-$blue: #0083b3;
-$blue-dark: #005f81;
-$blue-light: #00a8e6;
-$green: #3aa655;
-$red: #d44939;
-$yellow: #ff851b;
-$orange: #ff7941;
-$pink: #e671b8;
-$purple: #9954bb;
-$variable: $blue;
+$blue: getThemeVariable('colors.blue', $theme-name);
+$blue-dark: getThemeVariable('colors.blueDark', $theme-name);
+$blue-light: getThemeVariable('colors.blueLight', $theme-name);
+$green: getThemeVariable('colors.green', $theme-name);
+$red: getThemeVariable('colors.red', $theme-name);
+$yellow: getThemeVariable('colors.yellow', $theme-name);
+$orange: getThemeVariable('colors.orange', $theme-name);
+$pink: getThemeVariable('colors.pink', $theme-name);
+$purple: getThemeVariable('colors.purple', $theme-name);
+$variable: getThemeVariable('colors.variable', $theme-name);
 
 $brand-primary: $orange;
 $brand-success: $green;
 $brand-warning: $orange;
 $brand-danger: $red;
 
-$query-red: $red;
-$query-green: $green;
-$query-purple: $purple;
-$query-orange: $orange;
-$query-keyword: $blue;
+$query-red: getThemeVariable('colors.queryRed', $theme-name);
+$query-green: getThemeVariable('colors.queryGreen', $theme-name);
+$query-purple: getThemeVariable('colors.queryPurple', $theme-name);
+$query-keyword: getThemeVariable('colors.queryKeyword', $theme-name);
+$query-orange: getThemeVariable('colors.queryOrange', $theme-name);
 
 // Status colors
 // -------------------------
-$online: #01a64f;
-$warn: #f79520;
-$critical: #ec2128;
+$online: getThemeVariable('colors.online', $theme-name);
+$warn: getThemeVariable('colors.warn', $theme-name);
+$critical: getThemeVariable('colors.critical', $theme-name);
 
 // Scaffolding
 // -------------------------
 
-$body-bg: $gray-7;
-$page-bg: $gray-7;
-$body-color: $gray-1;
-$text-color: $gray-1;
-$text-color-strong: $dark-2;
-$text-color-weak: $gray-2;
-$text-color-faint: $gray-4;
-$text-color-emphasis: $dark-5;
+$body-bg: getThemeVariable('colors.bodyBg', $theme-name);
+$page-bg: getThemeVariable('colors.pageBg', $theme-name);
+
+$body-color: getThemeVariable('colors.bodyColor', $theme-name);
+$text-color: getThemeVariable('colors.textColor', $theme-name);
+$text-color-strong: getThemeVariable('colors.textColorStrong', $theme-name);
+$text-color-weak: getThemeVariable('colors.textColorWeak', $theme-name);
+$text-color-faint: getThemeVariable('colors.textColorFaint', $theme-name);
+$text-color-emphasis: getThemeVariable('colors.textColorEmphasis', $theme-name);
 
 $text-shadow-strong: none;
 $text-shadow-faint: none;
 $textShadow: none;
 
 // gradients
-$brand-gradient: linear-gradient(to right, rgba(255, 213, 0, 1) 0%, rgba(255, 68, 0, 1) 99%, rgba(255, 68, 0, 1) 100%);
+$brand-gradient: linear-gradient(to right, hsl(50, 100%, 50%) 0%, rgba(255, 68, 0, 1) 99%, rgba(255, 68, 0, 1) 100%);
 $page-gradient: linear-gradient(180deg, $white 10px, $gray-7 100px);
 $edit-gradient: linear-gradient(-60deg, $gray-7, #f5f6f9 70%, $gray-7 98%);
 
 // Links
 // -------------------------
-$link-color: $gray-1;
-$link-color-disabled: lighten($link-color, 30%);
-$link-hover-color: darken($link-color, 20%);
-$external-link-color: $blue-light;
+$link-color: getThemeVariable('colors.linkColor', $theme-name);
+$link-color-disabled: getThemeVariable('colors.linkColorDisabled', $theme-name);
+$link-hover-color: getThemeVariable('colors.linkColorHover', $theme-name);
+
+$external-link-color: getThemeVariable('colors.linkColorExternal', $theme-name);
 
 // Typography
 // -------------------------
-$headings-color: $text-color;
+$headings-color: getThemeVariable('colors.headingColor', $theme-name);
 $abbr-border-color: $gray-2 !default;
 $text-muted: $text-color-weak;
 

+ 22 - 22
public/sass/_variables.scss

@@ -47,45 +47,45 @@ $enable-flex: true;
 // Typography
 // -------------------------
 
-$font-family-sans-serif: 'Roboto', Helvetica, Arial, sans-serif;
-$font-family-serif: Georgia, 'Times New Roman', Times, serif;
-$font-family-monospace: Menlo, Monaco, Consolas, 'Courier New', monospace;
+$font-family-sans-serif: getThemeVariable('typography.fontFamily.sansSerif');
+$font-family-serif: getThemeVariable('typography.fontFamily.serif');
+$font-family-monospace: getThemeVariable('typography.fontFamily.monospace');
 $font-family-base: $font-family-sans-serif !default;
 
-$font-size-root: 14px !default;
-$font-size-base: 13px !default;
+$font-size-root: getThemeVariable('typography.size.m') !default;
+$font-size-base: getThemeVariable('typography.size.base') !default;
 
-$font-size-lg: 18px !default;
-$font-size-md: 14px !default;
-$font-size-sm: 12px !default;
-$font-size-xs: 10px !default;
+$font-size-lg: getThemeVariable('typography.size.l') !default;
+$font-size-md: getThemeVariable('typography.size.m') !default;
+$font-size-sm: getThemeVariable('typography.size.s') !default;
+$font-size-xs: getThemeVariable('typography.size.xs') !default;
 
-$line-height-base: 1.5 !default;
-$font-weight-semi-bold: 500;
+$line-height-base: getThemeVariable('typography.lineHeight.l')  !default;
+$font-weight-semi-bold: getThemeVariable('typography.weight.semibold');
 
-$font-size-h1: 2rem !default;
-$font-size-h2: 1.75rem !default;
-$font-size-h3: 1.5rem !default;
-$font-size-h4: 1.3rem !default;
-$font-size-h5: 1.2rem !default;
-$font-size-h6: 1rem !default;
+$font-size-h1: getThemeVariable('typography.heading.h1') !default;
+$font-size-h2: getThemeVariable('typography.heading.h2') !default;
+$font-size-h3: getThemeVariable('typography.heading.h3') !default;
+$font-size-h4: getThemeVariable('typography.heading.h4') !default;
+$font-size-h5: getThemeVariable('typography.heading.h5') !default;
+$font-size-h6: getThemeVariable('typography.heading.h6') !default;
 
 $display1-size: 6rem !default;
 $display2-size: 5.5rem !default;
 $display3-size: 4.5rem !default;
 $display4-size: 3.5rem !default;
 
-$display1-weight: 400 !default;
-$display2-weight: 400 !default;
-$display3-weight: 400 !default;
-$display4-weight: 400 !default;
+$display1-weight: getThemeVariable('typography.weight.normal') !default;
+$display2-weight: getThemeVariable('typography.weight.normal') !default;
+$display3-weight: getThemeVariable('typography.weight.normal') !default;
+$display4-weight: getThe1meVariable('typography.weight.normal') !default;
 
 $lead-font-size: 1.25rem !default;
 $lead-font-weight: 300 !default;
 
 $headings-margin-bottom: ($spacer / 2) !default;
 $headings-font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;
-$headings-font-weight: 400 !default;
+$headings-font-weight: getThemeVariable('typography.weight.normal') !default;
 $headings-line-height: 1.1 !default;
 
 $hr-border-width: $border-width !default;

+ 53 - 0
scripts/webpack/getThemeVariable.js

@@ -0,0 +1,53 @@
+const sass = require('node-sass');
+const sassUtils = require('node-sass-utils')(sass);
+const { getTheme } = require('../../packages/grafana-ui/src/theme');
+const { get } = require('lodash');
+const tinycolor = require('tinycolor2');
+
+const units = ['rem', 'em', 'vh', 'vw', 'vmin', 'vmax', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch'];
+const matchDimension = value => value.match(/[a-zA-Z]+|[0-9]+/g);
+
+const isHex = value => {
+  const hexRegex = /^((0x){0,1}|#{0,1})([0-9A-F]{8}|[0-9A-F]{6})$/gi;
+  return hexRegex.test(value);
+};
+
+const isDimension = value => {
+  if( typeof value !== "string") {
+    return false;
+  }
+
+  const [val, unit] = matchDimension(value);
+  return units.indexOf(unit) > -1
+};
+
+/**
+ * @param {SassString} variablePath
+ * @param {"dark"|"light"} themeName
+ */
+function getThemeVariable(variablePath, themeName) {
+  const theme = getTheme(themeName.getValue());
+  const variable = get(theme, variablePath.getValue());
+
+  if (!variable) {
+    throw new Error(`${variablePath} is not defined fo ${themeName}`);
+  }
+
+  if (isHex(variable)) {
+    const rgb = new tinycolor(variable).toRgb();
+    const color = sass.types.Color(rgb.r, rgb.g, rgb.b);
+    return color;
+  }
+
+  if (isDimension(variable)) {
+    const [value, unit] = matchDimension(variable)
+
+    const tmp = new sassUtils.SassDimension(parseInt(value,10), unit);
+    // debugger
+    return sassUtils.castToSass(tmp)
+  }
+
+  return sassUtils.castToSass(variable);
+}
+
+module.exports = getThemeVariable;

+ 11 - 2
scripts/webpack/sass.rule.js

@@ -1,6 +1,7 @@
 'use strict';
 
-const MiniCssExtractPlugin = require("mini-css-extract-plugin");
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const getThemeVariable = require('./getThemeVariable');
 
 module.exports = function(options) {
   return {
@@ -23,7 +24,15 @@ module.exports = function(options) {
           config: { path: __dirname + '/postcss.config.js' },
         },
       },
-      { loader: 'sass-loader', options: { sourceMap: options.sourceMap } },
+      {
+        loader: 'sass-loader',
+        options: {
+          sourceMap: options.sourceMap,
+          functions: {
+            'getThemeVariable($themeVar, $themeName: dark)': getThemeVariable,
+          },
+        },
+      },
     ],
   };
 };

+ 9 - 1
scripts/webpack/webpack.hot.js

@@ -8,6 +8,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
 const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
 const CleanWebpackPlugin = require('clean-webpack-plugin');
 const IgnoreNotFoundExportPlugin = require("./IgnoreNotFoundExportPlugin.js");
+const getThemeVariable = require("./getThemeVariable");
 
 module.exports = merge(common, {
   entry: {
@@ -85,7 +86,14 @@ module.exports = merge(common, {
               config: { path: __dirname + '/postcss.config.js' },
             },
           },
-          'sass-loader', // compiles Sass to CSS
+          {
+            loader: 'sass-loader',
+            options: {
+              functions: {
+                "getThemeVariable($themeVar, $themeName: dark)": getThemeVariable
+              }
+            }
+          }
         ],
       },
       {

+ 5 - 0
yarn.lock

@@ -11910,6 +11910,11 @@ node-releases@^1.0.0-alpha.11, node-releases@^1.1.3:
   dependencies:
     semver "^5.3.0"
 
+node-sass-utils@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/node-sass-utils/-/node-sass-utils-1.1.2.tgz#d03639cfa4fc962398ba3648ab466f0db7cc2131"
+  integrity sha1-0DY5z6T8liOYujZIq0ZvDbfMITE=
+
 node-sass@^4.11.0:
   version "4.11.0"
   resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.11.0.tgz#183faec398e9cbe93ba43362e2768ca988a6369a"