Theming: Updates to select styles and theme model progress (#32797)

* Theming: Updates to select styles and theme model progress

* Progress

* Update menu

* Updated menu group

* Improving button styles

* Added transitions to theme

* solving the hover & selected, focus issues

* Updated snapshot

* adding some colors from figma, but waiting to use them as not enough components use new layer colors

* Updates

* Updates

* Progress

* Renames

* Improvements to theme overview

* updated test

* demo update

* More new theme colors

* Wip new card styles

* Card tweaks hover is not working

* Updates more colors from figma

* Progress

* Progress

* Updated radio button styles

* Progress on new colors

* Progress

* New page toolbar and toolbar button design

* New toolbar button design

* Reverted to older toolbar and button look

* Updated snapshot

* Updated generated files

* Updated design

* Updates

* Added card hover

* Fixed button group

* Updates
This commit is contained in:
Torkel Ödegaard 2021-04-12 14:23:00 +02:00 committed by GitHub
parent 44b6c896ae
commit 629603dd92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 955 additions and 945 deletions

View File

@ -8,4 +8,5 @@ vendor/
data/
e2e/tmp
public/build/
public/sass/*.generated.scss
devenv/

View File

@ -2,48 +2,52 @@ export const colors = {
white: '#fff',
black: '#000',
// New greys palette used by next-gen form elements
// old
gray98: '#f7f8fa',
gray97: '#f1f5f9',
gray95: '#e9edf2',
gray90: '#dce1e6',
//gray90: '#dce1e6',
gray85: '#c7d0d9',
gray70: '#9fa7b3',
gray60: '#7b8087',
gray33: '#464c54',
gray25: '#2c3235',
gray15: '#202226',
gray10: '#141619',
gray05: '#0b0c0e',
gray15: '#22252b', //'#202226',
gray10: '#181b1f', // old '#141619',
gray05: '#0d0f16', // old '#0b0c0e',
blueDark1: '#3658E2',
blueDark2: '#5B93FF',
// new from figma,
darkLayer0: '#18181A',
darkLayer1: '#212124',
darkLayer2: '#2a2a2f', // figma used #34343B but a bit too bright
blueLight1: '#276EF1',
blueLight2: '#93BDFE',
blueLight3: '#1F62E0',
darkBorder1: '#34343B',
darkBorder2: '#64646B',
redDark1: '#D10E5C',
redDark2: '#FF5286',
// Dashboard bg / layer 0 (light theme)
gray90: '#F4F5F5',
// Card bg / layer 1
gray100: '#F7F7F8',
// divider line
gray80: '#D0D1D3',
// from figma
lightBorder1: '#E4E7E7',
redLight1: '#CF0E5B',
redLight2: '#FF5286',
blueDarkMain: '#4165F5',
blueDarkText: '#5790FF',
redDarkMain: '#D10E5C',
redDarkText: '#FF5286',
greenDarkMain: '#1A7F4B',
greenDarkText: '#6CCF8E',
orangeDarkMain: '#F5B73D',
orangeDarkText: '#F8D06B',
green1: '#13875D',
green2: '#6CCF8E',
// New reds palette used by next-gen form elements
red88: '#e02f44', // redBase
// below taken from dark theme
redShade: '#c4162a',
redBase: '#e02f44',
greenBase: '#299c46',
greenShade: '#23843b',
red: '#d44a3a',
yellow: '#ecbb13',
purple: '#9933cc',
variable: '#32d1df',
orange: '#eb7b18',
orangeDark: '#ff780a',
blueLightMain: '#3871DC',
blueLightText: '#1F62E0',
redLightMain: '#E0226E',
redLightText: '#CF0E5B',
greenLightMain: '#1A7F4B',
greenLightText: '#1A7F4B',
orangeLightMain: '#E56F00',
orangeLightText: '#BD4B00',
};

View File

@ -1,3 +1,6 @@
import { ThemePalette } from './createPalette';
import { ThemeShadows } from './createShadows';
/** @beta */
export interface ThemeComponents {
/** Applies to normal buttons, inputs, radio buttons, etc */
@ -6,22 +9,58 @@ export interface ThemeComponents {
md: number;
lg: number;
};
form: {
background: string;
border: string;
borderHover: string;
text: string;
};
panel: {
padding: number;
headerHeight: number;
border: string;
boxShadow: string;
background: string;
};
dashboard: {
background: string;
padding: number;
};
}
export function createComponents(): ThemeComponents {
export function createComponents(palette: ThemePalette, shadows: ThemeShadows): ThemeComponents {
const panel = {
padding: 1,
headerHeight: 4,
background: palette.layer1,
border: palette.border0,
boxShadow: shadows.z0,
};
return {
height: {
sm: 3,
md: 4,
lg: 6,
},
panel: {
form:
palette.mode === 'dark'
? {
background: palette.layer0,
border: palette.border1,
borderHover: palette.border2,
text: palette.text.primary,
}
: {
background: palette.layer1,
border: palette.border1,
borderHover: palette.border2,
text: palette.text.primary,
},
panel,
dashboard: {
background: palette.layer0,
padding: 1,
headerHeight: 4,
},
};
}

View File

@ -1,5 +1,5 @@
import { merge } from 'lodash';
import { emphasize, getContrastRatio } from './colorManipulator';
import { darken, emphasize, getContrastRatio, lighten } from './colorManipulator';
import { colors } from './colors';
import { DeepPartial, ThemePaletteColor } from './types';
@ -30,16 +30,27 @@ export interface ThemePaletteBase<TColor> {
layer1: string;
layer2: string;
divider: string;
border0: string;
border1: string;
border2: string;
formComponent: {
background: string;
text: string;
border: string;
action: {
/** Used for selected menu item / select option */
selected: string;
/** Used for hovered menu item / select option */
hover: string;
/** Used for button/colored background hover opacity */
hoverOpacity: number;
/** Used focused menu item / select option */
focus: string;
/** Used for disabled buttons and inputs */
disabledBackground: string;
/** Disabled text */
disabledText: string;
/** Disablerd opacity */
disabledOpacity: number;
};
hoverFactor: number;
@ -47,12 +58,14 @@ export interface ThemePaletteBase<TColor> {
tonalOffset: number;
}
export interface ThemeHoverStrengh {}
/** @beta */
export interface ThemePalette extends ThemePaletteBase<ThemePaletteColor> {
/** Returns a text color for the background */
getContrastText(background: string): string;
/* Retruns a hover color for any default color */
getHoverColor(defaultColor: string): string;
/* Return a hover color for any color */
getHoverColor(color: string, hoverFactor?: number): string;
}
/** @internal */
@ -64,116 +77,129 @@ class DarkPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
text = {
primary: 'rgba(255, 255, 255, 0.75)',
secondary: 'rgba(255, 255, 255, 0.50)',
disabled: 'rgba(255, 255, 255, 0.3)',
link: colors.blueDark2,
disabled: 'rgba(255, 255, 255, 0.35)',
link: colors.blueDarkText,
maxContrast: colors.white,
};
primary = {
main: colors.blueDark1,
border: colors.blueDark2,
text: colors.blueDark2,
main: colors.blueDarkMain,
text: colors.blueDarkText,
border: colors.blueDarkText,
};
secondary = {
main: 'rgba(255,255,255,0.1)',
shade: 'rgba(255,255,255,0.15)',
text: 'rgba(255,255,255,0.13)',
contrastText: 'rgba(255, 255, 255, 0.8)',
};
info = this.primary;
error = {
main: colors.redDark1,
border: colors.redDark2,
text: colors.redDark2,
main: colors.redDarkMain,
text: colors.redDarkText,
};
success = {
main: colors.green1,
text: colors.green2,
border: colors.green2,
main: colors.greenDarkMain,
text: colors.greenDarkText,
};
warning = {
main: colors.orange,
main: colors.orangeDarkMain,
text: colors.orangeDarkText,
};
layer0 = colors.gray05;
layer1 = colors.gray10;
layer2 = colors.gray15;
border0 = colors.gray15;
border1 = colors.gray25;
border2 = colors.gray33;
divider = 'rgba(218,224,254,0.06)';
formComponent = {
background: this.layer0,
border: this.border1,
text: this.text.primary,
border0 = this.layer1;
border1 = 'rgba(218,224,254,0.15)';
border2 = 'rgba(218,224,254,0.20)';
action = {
hover: 'rgba(255, 255, 255, 0.08)',
selected: 'rgba(255, 255, 255, 0.12)',
focus: 'rgba(255, 255, 255, 0.16)',
hoverOpacity: 0.08,
disabledText: this.text.disabled,
disabledBackground: 'rgba(255, 255, 255, 0.04)',
disabledBackground: 'rgba(255,255,255,0.07)',
disabledOpacity: 0.38,
};
contrastThreshold = 3;
hoverFactor = 0.15;
tonalOffset = 0.1;
tonalOffset = 0.15;
}
class LightPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
mode: ThemePaletteMode = 'light';
primary = {
main: colors.blueLight1,
border: colors.blueLight3,
text: colors.blueLight3,
main: colors.blueLightMain,
border: colors.blueLightText,
text: colors.blueLightText,
};
secondary = {
main: 'rgba(0,0,0,0.18)',
main: 'rgba(0,0,0,0.11)',
shade: 'rgba(0,0,0,0.16)',
contrastText: 'rgba(0, 0, 0, 0.75)',
};
info = {
main: colors.blueLight1,
text: colors.blueLight3,
main: colors.blueLightMain,
text: colors.blueLightText,
};
error = {
main: colors.redLight1,
text: colors.redLight2,
border: colors.redLight2,
main: colors.redLightMain,
text: colors.redLightText,
border: colors.redLightText,
};
success = {
main: colors.greenBase,
main: colors.greenLightMain,
text: colors.greenLightText,
};
warning = {
main: colors.orange,
main: colors.orangeLightMain,
text: colors.orangeLightText,
};
text = {
primary: 'rgba(0, 0, 0, 0.87)',
secondary: 'rgba(0, 0, 0, 0.54)',
disabled: 'rgba(0, 0, 0, 0.38)',
secondary: 'rgba(0, 0, 0, 0.55)',
disabled: 'rgba(0, 0, 0, 0.40)',
link: this.primary.text,
maxContrast: colors.black,
};
layer0 = colors.gray98;
layer0 = colors.gray90;
layer1 = colors.white;
layer2 = colors.gray97;
layer2 = colors.gray100;
border0 = colors.gray90;
border1 = colors.gray85;
border2 = colors.gray70;
divider = 'rgba(0, 2, 78, 0.07)';
formComponent = {
background: this.layer1,
border: this.border1,
text: this.text.primary,
disabledBackground: colors.gray95,
border0 = this.layer1;
border1 = 'rgba(0, 2, 78, 0.20)';
border2 = 'rgba(0, 2, 78, 0.30)';
action = {
hover: 'rgba(0, 0, 0, 0.04)',
selected: 'rgba(0, 0, 0, 0.08)',
hoverOpacity: 0.08,
focus: 'rgba(0, 0, 0, 0.12)',
disabledBackground: 'rgba(0,0,0,0.07)',
disabledText: this.text.disabled,
disabledOpacity: 0.38,
};
contrastThreshold = 3;
@ -207,8 +233,8 @@ export function createPalette(palette: ThemePaletteInput): ThemePalette {
return contrastText;
}
function getHoverColor(color: string) {
return emphasize(color, hoverFactor);
function getHoverColor(color: string, factorOverride?: number) {
return emphasize(color, factorOverride ?? hoverFactor);
}
const getRichColor = ({ color, name }: GetRichColorProps): ThemePaletteColor => {
@ -216,12 +242,15 @@ export function createPalette(palette: ThemePaletteInput): ThemePalette {
if (!color.main) {
throw new Error(`Missing main color for ${name}`);
}
if (!color.border) {
color.border = color.main;
}
if (!color.text) {
color.text = color.main;
}
if (!color.border) {
color.text = color.text;
}
if (!color.shade) {
color.shade = base.mode === 'light' ? darken(color.main, tonalOffset) : lighten(color.main, tonalOffset);
}
if (!color.contrastText) {
color.contrastText = getContrastText(color.main);
}

View File

@ -2,15 +2,17 @@ import { ThemePalette } from './createPalette';
/** @beta */
export interface ThemeShadows {
z0: string;
z1: string;
z2: string;
z3: string;
z4: string;
}
function createDarkShadow(...px: number[]) {
const shadowKeyUmbraOpacity = 0.2;
const shadowKeyPenumbraOpacity = 0.14;
const shadowAmbientShadowOpacity = 0.12;
const shadowKeyUmbraOpacity = 0.5;
const shadowKeyPenumbraOpacity = 0.4;
const shadowAmbientShadowOpacity = 0.3;
return [
`${px[0]}px ${px[1]}px ${px[2]}px ${px[3]}px rgba(0,0,0,${shadowKeyUmbraOpacity})`,
@ -35,15 +37,19 @@ function createLightShadow(...px: number[]) {
export function createShadows(palette: ThemePalette): ThemeShadows {
if (palette.mode === 'dark') {
return {
z0: createDarkShadow(0, 1, 1, -1, 0, 1, 1, 0, 0, 1, 3, 0),
z1: createDarkShadow(0, 2, 1, -1, 0, 1, 1, 0, 0, 1, 3, 0),
z2: createDarkShadow(0, 3, 1, -2, 0, 2, 2, 0, 0, 1, 5, 0),
z3: createDarkShadow(0, 3, 3, -2, 0, 3, 4, 0, 0, 1, 8, 0),
z3: createDarkShadow(0, 2, 4, -1, 0, 4, 5, 0, 0, 1, 10, 0),
z4: createDarkShadow(0, 5, 5, -3, 0, 8, 10, 1, 0, 3, 14, 2),
};
}
return {
z1: createLightShadow(0, 2, 1, -1, 0, 1, 1, 0, 0, 1, 3, 0),
z2: createLightShadow(0, 3, 1, -2, 0, 2, 2, 0, 0, 1, 5, 0),
z3: createLightShadow(0, 3, 3, -2, 0, 3, 4, 0, 0, 1, 8, 0),
z0: createLightShadow(0, 1, 1, -1, 0, 0, 0, 0, 0, 1, 3, 0),
z1: createLightShadow(0, 1, 1, -1, 0, 1, 2, 0, 0, 1, 3, 0),
z2: createLightShadow(0, 2, 1, -2, 0, 2, 2, 0, 0, 1, 5, 0),
z3: createLightShadow(0, 2, 4, -1, 0, 4, 5, 0, 0, 1, 10, 0),
z4: createLightShadow(0, 5, 5, -3, 0, 8, 10, 1, 0, 3, 14, 2),
};
}

View File

@ -1,201 +1,24 @@
import { createTheme } from './createTheme';
describe('createTheme', () => {
it('create custom theme', () => {
const custom = createTheme({
palette: {
mode: 'dark',
primary: {
main: 'rgb(240,0,0)',
},
layer0: '#123',
},
});
expect(custom.palette.primary.main).toBe('rgb(240,0,0)');
expect(custom.palette.primary.shade).toBe('rgb(242, 38, 38)');
expect(custom.palette.layer0).toBe('#123');
});
it('create default theme', () => {
const theme = createTheme();
expect(theme).toMatchInlineSnapshot(`
Object {
"breakpoints": Object {
"down": [Function],
"keys": Array [
"xs",
"sm",
"md",
"lg",
"xl",
"xxl",
],
"unit": "px",
"up": [Function],
"values": Object {
"lg": 992,
"md": 769,
"sm": 544,
"xl": 1200,
"xs": 0,
"xxl": 1440,
},
},
"components": Object {
"height": Object {
"lg": 6,
"md": 4,
"sm": 3,
},
"panel": Object {
"headerHeight": 4,
"padding": 1,
},
},
"isDark": true,
"isLight": false,
"name": "Dark",
"palette": Object {
"border0": "#202226",
"border1": "#2c3235",
"border2": "#464c54",
"contrastThreshold": 3,
"error": Object {
"border": "#FF5286",
"contrastText": "#fff",
"main": "#D10E5C",
"name": "error",
"text": "#FF5286",
},
"formComponent": Object {
"background": "#0b0c0e",
"border": "#2c3235",
"disabledBackground": "rgba(255, 255, 255, 0.04)",
"disabledText": "rgba(255, 255, 255, 0.3)",
"text": "rgba(255, 255, 255, 0.75)",
},
"getContrastText": [Function],
"getHoverColor": [Function],
"hoverFactor": 0.15,
"info": Object {
"border": "#5B93FF",
"contrastText": "#fff",
"main": "#3658E2",
"name": "info",
"text": "#5B93FF",
},
"layer0": "#0b0c0e",
"layer1": "#141619",
"layer2": "#202226",
"mode": "dark",
"primary": Object {
"border": "#5B93FF",
"contrastText": "#fff",
"main": "#3658E2",
"name": "primary",
"text": "#5B93FF",
},
"secondary": Object {
"border": "rgba(255,255,255,0.1)",
"contrastText": "rgba(255, 255, 255, 0.8)",
"main": "rgba(255,255,255,0.1)",
"name": "secondary",
"text": "rgba(255,255,255,0.1)",
},
"success": Object {
"border": "#6CCF8E",
"contrastText": "#fff",
"main": "#13875D",
"name": "success",
"text": "#6CCF8E",
},
"text": Object {
"disabled": "rgba(255, 255, 255, 0.3)",
"link": "#5B93FF",
"maxContrast": "#fff",
"primary": "rgba(255, 255, 255, 0.75)",
"secondary": "rgba(255, 255, 255, 0.50)",
},
"tonalOffset": 0.1,
"warning": Object {
"border": "#eb7b18",
"contrastText": "#000",
"main": "#eb7b18",
"name": "warning",
"text": "#eb7b18",
},
},
"shadows": Object {
"z1": "0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)",
"z2": "0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12)",
"z3": "0px 3px 3px -2px rgba(0,0,0,0.2),0px 3px 4px 0px rgba(0,0,0,0.14),0px 1px 8px 0px rgba(0,0,0,0.12)",
},
"shape": Object {
"borderRadius": [Function],
},
"spacing": [Function],
"typography": Object {
"body": Object {
"fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
"fontSize": "1rem",
"fontWeight": 400,
"letterSpacing": "0.01071em",
"lineHeight": 1.5,
},
"fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
"fontFamilyMonospace": "Menlo, Monaco, Consolas, 'Courier New', monospace",
"fontSize": 14,
"fontWeightBold": 700,
"fontWeightLight": 300,
"fontWeightMedium": 500,
"fontWeightRegular": 400,
"h1": Object {
"fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
"fontSize": "2rem",
"fontWeight": 300,
"letterSpacing": "-0.05357em",
"lineHeight": 1.167,
},
"h2": Object {
"fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
"fontSize": "1.7142857142857142rem",
"fontWeight": 300,
"letterSpacing": "-0.02083em",
"lineHeight": 1.2,
},
"h3": Object {
"fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
"fontSize": "1.5rem",
"fontWeight": 400,
"letterSpacing": "0em",
"lineHeight": 1.167,
},
"h4": Object {
"fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
"fontSize": "1.2857142857142858rem",
"fontWeight": 400,
"letterSpacing": "0.01389em",
"lineHeight": 1.235,
},
"h5": Object {
"fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
"fontSize": "1.1428571428571428rem",
"fontWeight": 400,
"letterSpacing": "0em",
"lineHeight": 1.334,
},
"h6": Object {
"fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
"fontSize": "1rem",
"fontWeight": 500,
"letterSpacing": "0.01071em",
"lineHeight": 1.6,
},
"htmlFontSize": 14,
"pxToRem": [Function],
"size": Object {
"base": "14px",
"lg": "18px",
"md": "14px",
"sm": "12px",
"xs": "10px",
},
},
"zIndex": Object {
"dropdown": 1030,
"modal": 1060,
"modalBackdrop": 1050,
"navbarFixed": 1000,
"sidemenu": 1020,
"tooltip": 1040,
"typeahead": 1030,
},
}
`);
expect(theme.palette.mode).toBe('dark');
});
});

View File

@ -4,6 +4,7 @@ import { createPalette, ThemePalette, ThemePaletteInput } from './createPalette'
import { createShadows, ThemeShadows } from './createShadows';
import { createShape, ThemeShape, ThemeShapeInput } from './createShape';
import { createSpacing, ThemeSpacingOptions, ThemeSpacing } from './createSpacing';
import { createTransitions, ThemeTransitions } from './createTransitions';
import { createTypography, ThemeTypography, ThemeTypographyInput } from './createTypography';
import { ThemeZIndices, zIndex } from './zIndex';
@ -20,6 +21,7 @@ export interface GrafanaThemeV2 {
typography: ThemeTypography;
zIndex: ThemeZIndices;
shadows: ThemeShadows;
transitions: ThemeTransitions;
}
/** @internal */
@ -45,9 +47,10 @@ export function createTheme(options: NewThemeOptions = {}): GrafanaThemeV2 {
const breakpoints = createBreakpoints();
const spacing = createSpacing(spacingInput);
const shape = createShape(shapeInput);
const components = createComponents();
const typography = createTypography(palette, typographyInput);
const shadows = createShadows(palette);
const transitions = createTransitions();
const components = createComponents(palette, shadows);
return {
name,
@ -60,6 +63,7 @@ export function createTheme(options: NewThemeOptions = {}): GrafanaThemeV2 {
components,
typography,
shadows,
transitions,
zIndex: {
...zIndex,
},

View File

@ -0,0 +1,84 @@
import { createTransitions } from './createTransitions';
describe('transitions', () => {
const { duration, easing, getAutoHeightDuration, create } = createTransitions();
describe('create() function', () => {
it('should create default transition without arguments', () => {
const transition = create();
expect(transition).toEqual(`all ${duration.standard}ms ${easing.easeInOut} 0ms`);
});
it('should take string props as a first argument', () => {
const transition = create('color');
expect(transition).toEqual(`color ${duration.standard}ms ${easing.easeInOut} 0ms`);
});
it('should also take array of props as first argument', () => {
const options = { delay: 20 };
const multiple = create(['color', 'size'], options);
const single1 = create('color', options);
const single2 = create('size', options);
const expected = `${single1},${single2}`;
expect(multiple).toEqual(expected);
});
it('should optionally accept number "duration" option in second argument', () => {
const transition = create('font', { duration: 500 });
expect(transition).toEqual(`font 500ms ${easing.easeInOut} 0ms`);
});
it('should optionally accept string "duration" option in second argument', () => {
const transition = create('font', { duration: '500ms' });
expect(transition).toEqual(`font 500ms ${easing.easeInOut} 0ms`);
});
it('should round decimal digits of "duration" prop to whole numbers', () => {
const transition = create('font', { duration: 12.125 });
expect(transition).toEqual(`font 12ms ${easing.easeInOut} 0ms`);
});
it('should optionally accept string "easing" option in second argument', () => {
const transition = create('transform', { easing: easing.sharp });
expect(transition).toEqual(`transform ${duration.standard}ms ${easing.sharp} 0ms`);
});
it('should optionally accept number "delay" option in second argument', () => {
const transition = create('size', { delay: 150 });
expect(transition).toEqual(`size ${duration.standard}ms ${easing.easeInOut} 150ms`);
});
it('should optionally accept string "delay" option in second argument', () => {
const transition = create('size', { delay: '150ms' });
expect(transition).toEqual(`size ${duration.standard}ms ${easing.easeInOut} 150ms`);
});
it('should round decimal digits of "delay" prop to whole numbers', () => {
const transition = create('size', { delay: 1.547 });
expect(transition).toEqual(`size ${duration.standard}ms ${easing.easeInOut} 2ms`);
});
it('should return NaN when passed a negative number', () => {
const zeroHeightDurationNegativeOne = getAutoHeightDuration(-1);
// eslint-disable-next-line no-restricted-globals
expect(isNaN(zeroHeightDurationNegativeOne)).toEqual(true);
const zeroHeightDurationSmallNegative = getAutoHeightDuration(-0.000001);
// eslint-disable-next-line no-restricted-globals
expect(isNaN(zeroHeightDurationSmallNegative)).toEqual(true);
const zeroHeightDurationBigNegative = getAutoHeightDuration(-100000);
// eslint-disable-next-line no-restricted-globals
expect(isNaN(zeroHeightDurationBigNegative)).toEqual(true);
});
it('should return values for pre-calculated positive examples', () => {
let zeroHeightDuration = getAutoHeightDuration(14);
expect(zeroHeightDuration).toEqual(159);
zeroHeightDuration = getAutoHeightDuration(100);
expect(zeroHeightDuration).toEqual(239);
zeroHeightDuration = getAutoHeightDuration(0.0001);
expect(zeroHeightDuration).toEqual(46);
zeroHeightDuration = getAutoHeightDuration(100000);
expect(zeroHeightDuration).toEqual(6685);
});
});
});

View File

@ -0,0 +1,87 @@
// Code based on Material UI
// The MIT License (MIT)
// Copyright (c) 2014 Call-Em-All
// Follow https://material.google.com/motion/duration-easing.html#duration-easing-natural-easing-curves
// to learn the context in which each easing should be used.
const easing = {
// This is the most common easing curve.
easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
// Objects enter the screen at full velocity from off-screen and
// slowly decelerate to a resting point.
easeOut: 'cubic-bezier(0.0, 0, 0.2, 1)',
// Objects leave the screen at full velocity. They do not decelerate when off-screen.
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
// The sharp curve is used by objects that may return to the screen at any time.
sharp: 'cubic-bezier(0.4, 0, 0.6, 1)',
};
// Follow https://material.io/guidelines/motion/duration-easing.html#duration-easing-common-durations
// to learn when use what timing
const duration = {
shortest: 150,
shorter: 200,
short: 250,
// most basic recommended timing
standard: 300,
// this is to be used in complex animations
complex: 375,
// recommended when something is entering screen
enteringScreen: 225,
// recommended when something is leaving screen
leavingScreen: 195,
};
/** @alpha */
export interface CreateTransitionOptions {
duration?: number | string;
easing?: string;
delay?: number | string;
}
/** @alpha */
export function create(props: string | string[] = ['all'], options: CreateTransitionOptions = {}) {
const { duration: durationOption = duration.standard, easing: easingOption = easing.easeInOut, delay = 0 } = options;
return (Array.isArray(props) ? props : [props])
.map(
(animatedProp) =>
`${animatedProp} ${
typeof durationOption === 'string' ? durationOption : formatMs(durationOption)
} ${easingOption} ${typeof delay === 'string' ? delay : formatMs(delay)}`
)
.join(',');
}
export function getAutoHeightDuration(height: number) {
if (!height) {
return 0;
}
const constant = height / 36;
// https://www.wolframalpha.com/input/?i=(4+%2B+15+*+(x+%2F+36+)+**+0.25+%2B+(x+%2F+36)+%2F+5)+*+10
return Math.round((4 + 15 * constant ** 0.25 + constant / 5) * 10);
}
function formatMs(milliseconds: number) {
return `${Math.round(milliseconds)}ms`;
}
/** @alpha */
export interface ThemeTransitions {
create: typeof create;
duration: typeof duration;
easing: typeof easing;
getAutoHeightDuration: typeof getAutoHeightDuration;
}
/** @internal */
export function createTransitions(): ThemeTransitions {
return {
create,
duration,
easing,
getAutoHeightDuration,
};
}

View File

@ -1,2 +1,3 @@
export { createTheme, GrafanaThemeV2 } from './createTheme';
export { ThemePaletteColor } from './types';
export * as colorManipulator from './colorManipulator';

View File

@ -4,9 +4,11 @@ export interface ThemePaletteColor {
name: string;
/** Main color */
main: string;
/** Used for hover */
shade: string;
/** Used for text */
text: string;
/** Used for text */
/** Used for borders */
border: string;
/** Used subtly colored backgrounds */
transparent: string;

View File

@ -31,9 +31,9 @@ const createTheme = (theme: GrafanaTheme) => {
barBg: theme.v2.palette.layer1,
// Form colors
inputBg: theme.v2.palette.formComponent.background,
inputBorder: theme.v2.palette.formComponent.border,
inputTextColor: theme.v2.palette.formComponent.text,
inputBg: theme.v2.components.form.background,
inputBorder: theme.v2.components.form.border,
inputTextColor: theme.v2.components.form.text,
inputBorderRadius: theme.v2.shape.borderRadius(1),
brandTitle: 'Grafana UI',

View File

@ -30,7 +30,7 @@ exports[`BigValue Render with basic options should render 1`] = `
<FormattedDisplayValue
style={
Object {
"color": "#f7f8fa",
"color": "#fff",
"fontSize": 230,
"fontWeight": 500,
"lineHeight": 1.2,

View File

@ -7,6 +7,7 @@ import mdx from './Button.mdx';
import { HorizontalGroup, VerticalGroup } from '../Layout/Layout';
import { ButtonGroup } from './ButtonGroup';
import { ComponentSize } from '../../types/size';
import { Card } from '../Card/Card';
export default {
title: 'Buttons/Button',
@ -78,6 +79,20 @@ export const Variants: Story<ButtonProps> = ({ children, ...args }) => {
<Button icon="angle-down" />
</ButtonGroup>
</HorizontalGroup>
<Card heading="Button inside card">
<Card.Actions>
<>
{allButtonVariants.map((variant) => (
<Button variant={variant} key={variant}>
{variant}
</Button>
))}
<Button variant="primary" disabled>
Disabled
</Button>
</>
</Card.Actions>
</Card>
</VerticalGroup>
);
};

View File

@ -3,7 +3,7 @@ import { css, CSSObject, cx } from '@emotion/css';
import { useTheme } from '../../themes';
import { IconName } from '../../types/icon';
import { getPropertiesForButtonSize } from '../Forms/commonStyles';
import { GrafanaTheme, GrafanaThemeV2, ThemePaletteColor } from '@grafana/data';
import { colorManipulator, GrafanaTheme, GrafanaThemeV2, ThemePaletteColor } from '@grafana/data';
import { ComponentSize } from '../../types/size';
import { getFocusStyles } from '../../themes/mixins';
import { Icon } from '../Icon/Icon';
@ -86,15 +86,14 @@ export const getButtonStyles = (props: StyleProps) => {
const disabledStyles: CSSObject = {
cursor: 'not-allowed',
opacity: 0.65,
boxShadow: 'none',
background: theme.v2.palette.formComponent.disabledBackground,
border: `1px solid ${theme.v2.palette.formComponent.disabledBackground}`,
background: theme.v2.palette.action.disabledBackground,
border: `1px solid transparent`,
color: theme.v2.palette.text.disabled,
pointerEvents: 'none',
'&:hover': {
background: theme.v2.palette.formComponent.disabledBackground,
background: theme.v2.palette.action.disabledBackground,
color: theme.v2.palette.text.disabled,
},
};
@ -147,10 +146,14 @@ function getButtonVariantStyles(theme: GrafanaThemeV2, color: ThemePaletteColor)
color: color.contrastText,
boxShadow: theme.shadows.z1,
border: `1px solid transparent`,
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
}),
'&:hover': {
background: theme.palette.getHoverColor(color.main),
background: color.shade,
color: color.contrastText,
boxShadow: theme.shadows.z2,
},
'&:focus': {
@ -178,7 +181,7 @@ export function getPropertiesForVariant(theme: GrafanaThemeV2, variant: ButtonVa
},
'&:hover': {
color: theme.palette.getHoverColor(theme.palette.text.link),
background: colorManipulator.alpha(theme.palette.text.link, theme.palette.action.hoverOpacity),
textDecoration: 'underline',
},
};

View File

@ -112,34 +112,47 @@ const getStyles = (theme: GrafanaTheme) => {
label: toolbar-button;
display: flex;
align-items: center;
height: ${theme.height.md}px;
padding: 0 ${theme.spacing.sm};
border-radius: ${theme.border.radius.sm};
line-height: ${theme.height.md - 2}px;
font-weight: ${theme.typography.weight.semibold};
border: 1px solid ${theme.colors.border2};
height: ${theme.v2.spacing(theme.v2.components.height.md)};
padding: ${theme.v2.spacing(0, 1)};
border-radius: ${theme.v2.shape.borderRadius()};
line-height: ${theme.v2.components.height.md * theme.v2.spacing.gridSize - 2}px;
font-weight: ${theme.v2.typography.fontWeightMedium};
border: 1px solid ${theme.v2.palette.border1};
box-shadow: ${theme.v2.shadows.z0};
white-space: nowrap;
transition: ${theme.v2.transitions.create(['background', 'box-shadow', 'border-color', 'color'], {
duration: theme.v2.transitions.duration.short,
})},
&:focus {
outline: none;
}
&:hover {
box-shadow: ${theme.v2.shadows.z2};
}
&[disabled],
&:disabled {
cursor: not-allowed;
opacity: 0.5;
opacity: ${theme.v2.palette.action.disabledOpacity};
background: ${theme.v2.palette.action.disabledBackground};
box-shadow: none;
&:hover {
color: ${theme.colors.textWeak};
background: ${theme.colors.bg1};
color: ${theme.v2.palette.text.disabled};
background: ${theme.v2.palette.action.disabledBackground};
box-shadow: none;
}
}
}
`,
default: css`
color: ${theme.colors.textWeak};
background-color: ${theme.colors.bg1};
color: ${theme.v2.palette.text.secondary};
background-color: ${theme.v2.palette.layer1};
&:hover {
color: ${theme.colors.text};
background: ${styleMixins.hoverColor(theme.colors.bg1, theme)};
color: ${theme.v2.palette.text.primary};
background: ${theme.v2.palette.layer2};
}
`,
active: css`

View File

@ -2,7 +2,7 @@
exports[`CallToActionCard rendering when message and footer provided 1`] = `
<div
class="css-1lvb0kq-call-to-action-card"
class="css-1wsd3n2-call-to-action-card"
>
<div
class="css-m2iibx"
@ -24,7 +24,7 @@ exports[`CallToActionCard rendering when message and footer provided 1`] = `
exports[`CallToActionCard rendering when message and no footer provided 1`] = `
<div
class="css-1lvb0kq-call-to-action-card"
class="css-1wsd3n2-call-to-action-card"
>
<div
class="css-m2iibx"
@ -41,7 +41,7 @@ exports[`CallToActionCard rendering when message and no footer provided 1`] = `
exports[`CallToActionCard rendering when no message and footer provided 1`] = `
<div
class="css-1lvb0kq-call-to-action-card"
class="css-1wsd3n2-call-to-action-card"
>
<a
href="http://dummy.link"

View File

@ -6,6 +6,7 @@ import mdx from './Card.mdx';
import { Button } from '../Button';
import { IconButton } from '../IconButton/IconButton';
import { TagList } from '../Tags/TagList';
import { VerticalGroup } from '../Layout/Layout';
const logo = 'https://grafana.com/static/assets/img/apple-touch-icon.png';
@ -42,12 +43,23 @@ export const Basic: Story<Props> = ({ disabled }) => {
export const AsLink: Story<Props> = ({ disabled }) => {
return (
<Card
href="https://grafana.com"
heading="Filter by name"
description="Filter data by query. This is useful if you are sharing the results from a different panel that has many queries and you want to only visualize a subset of that in this panel."
disabled={disabled}
/>
<VerticalGroup>
<Card
href="https://grafana.com"
heading="Filter by name"
description="Filter data by query. This is useful if you are sharing the results from a different panel that has many queries and you want to only visualize a subset of that in this panel."
disabled={disabled}
/>
<Card
href="https://grafana.com"
heading="Filter by name2"
description="Filter data by query. This is useful if you are sharing the results from a different panel that has many queries and you want to only visualize a subset of that in this panel."
disabled={disabled}
/>
<Card href="https://grafana.com" heading="Production system overview" disabled={disabled}>
<Card.Meta>Meta tags</Card.Meta>
</Card>
</VerticalGroup>
);
};

View File

@ -136,43 +136,28 @@ export const Card: CardInterface = ({
);
};
/**
* @public
*/
export const getContainerStyles = stylesFactory((theme: GrafanaTheme, disabled = false, disableHover = false) => {
return css`
display: flex;
width: 100%;
color: ${theme.colors.textStrong};
background: ${theme.colors.bg2};
border-radius: ${theme.border.radius.sm};
position: relative;
pointer-events: ${disabled ? 'none' : 'auto'};
margin-bottom: ${theme.spacing.sm};
const getContainerStyles = stylesFactory((theme: GrafanaTheme, disabled = false, disableHover = false) => {
return css({
display: 'flex',
width: '100%',
background: theme.v2.palette.layer2,
borderRadius: theme.v2.shape.borderRadius(),
position: 'relative',
pointerEvents: disabled ? 'none' : 'auto',
marginBottom: theme.v2.spacing(1),
transition: theme.v2.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
duration: theme.v2.transitions.duration.short,
}),
&::after {
content: '';
display: ${disabled ? 'block' : 'none'};
position: absolute;
top: 1px;
left: 1px;
right: 1px;
bottom: 1px;
background: linear-gradient(180deg, rgba(75, 79, 84, 0.5) 0%, rgba(82, 84, 92, 0.5) 100%);
width: calc(100% - 2px);
height: calc(100% - 2px);
border-radius: ${theme.border.radius.sm};
}
&:hover {
background: ${disableHover ? theme.colors.bg2 : styleMixins.hoverColor(theme.colors.bg2, theme)};
cursor: ${disableHover ? 'default' : 'pointer'};
}
&:focus {
${styleMixins.focusCss(theme)};
}
`;
...(!disableHover && {
'&:hover': {
background: theme.v2.palette.getHoverColor(theme.v2.palette.layer2, 0.03),
cursor: 'pointer',
zIndex: 1,
},
'&:focus': styleMixins.getFocusStyles(theme.v2),
}),
});
});
/**

View File

@ -155,12 +155,12 @@ const getStyles = (theme: GrafanaTheme) => {
left: ${theme.spacing.xxs};
}
.thumb-vertical {
background: ${theme.colors.bg3};
background: ${theme.v2.palette.action.focus};
border-radius: ${theme.border.radius.md};
opacity: 0;
}
.thumb-horizontal {
background: ${theme.colors.bg3};
background: ${theme.v2.palette.action.focus};
border-radius: ${theme.border.radius.md};
opacity: 0;
}

View File

@ -2,7 +2,7 @@
exports[`CustomScrollbar renders correctly 1`] = `
<div
className="css-1fb8j9z"
className="css-1xduqpt"
style={
Object {
"height": "auto",

View File

@ -43,7 +43,7 @@ export const ButtonSelect = React.memo(<T,>(props: Props<T>) => {
};
return (
<div className={styles.wrapper}>
<>
<ToolbarButton
className={className}
isOpen={isOpen}
@ -71,7 +71,7 @@ export const ButtonSelect = React.memo(<T,>(props: Props<T>) => {
</ClickOutsideWrapper>
</div>
)}
</div>
</>
);
});
@ -79,10 +79,6 @@ ButtonSelect.displayName = 'ButtonSelect';
const getStyles = (theme: GrafanaTheme) => {
return {
wrapper: css`
position: relative;
display: inline-flex;
`,
menuWrapper: css`
position: absolute;
z-index: ${theme.zIndex.dropdown};

View File

@ -21,17 +21,14 @@ export interface RadioButtonProps {
const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme, size: RadioButtonSize, fullWidth?: boolean) => {
const { fontSize, height, padding } = getPropertiesForButtonSize(size, theme.v2);
const c = theme.palette;
const textColor = theme.colors.textSemiWeak;
const textColorHover = theme.colors.text;
const textColorActive = theme.colors.textBlue;
const borderColor = theme.colors.border2;
const borderColorHover = theme.colors.border3;
const borderColorActive = theme.colors.border2;
const textColor = theme.v2.palette.text.secondary;
const textColorHover = theme.v2.palette.text.primary;
const textColorActive = theme.v2.palette.primary.text;
const borderColor = theme.v2.components.form.border;
const borderColorHover = theme.v2.components.form.borderHover;
const borderColorActive = theme.v2.components.form.border;
const bg = theme.colors.bodyBg;
const bgDisabled = theme.isLight ? c.gray95 : c.gray15;
const bgActive = theme.colors.bg2;
const bgActive = theme.v2.palette.layer2;
const border = `1px solid ${borderColor}`;
const borderActive = `1px solid ${borderColorActive}`;
const borderHover = `1px solid ${borderColorHover}`;
@ -56,8 +53,8 @@ const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme, size: RadioButt
&:disabled + label {
cursor: default;
background: ${bgDisabled};
color: ${textColor};
color: ${theme.v2.palette.text.disabled};
cursor: not-allowed;
}
`,
radioLabel: css`

View File

@ -10,15 +10,15 @@ export const getFocusStyle = (theme: GrafanaTheme) => css`
`;
export const sharedInputStyle = (theme: GrafanaTheme, invalid = false) => {
const palette = theme.v2.palette;
const borderColor = invalid ? palette.error.border : palette.formComponent.border;
const background = palette.formComponent.background;
const textColor = palette.text.primary;
const borderColor = invalid ? theme.v2.palette.error.border : theme.v2.components.form.border;
const borderColorHover = invalid ? theme.v2.palette.error.shade : theme.v2.components.form.borderHover;
const background = theme.v2.components.form.background;
const textColor = theme.v2.components.form.text;
return css`
background-color: ${background};
line-height: ${theme.typography.lineHeight.md};
font-size: ${theme.typography.size.md};
background: ${background};
line-height: ${theme.v2.typography.body.lineHeight};
font-size: ${theme.v2.typography.size.md};
color: ${textColor};
border: 1px solid ${borderColor};
padding: ${theme.v2.spacing(0, 1, 0, 1)};
@ -38,7 +38,7 @@ export const sharedInputStyle = (theme: GrafanaTheme, invalid = false) => {
}
&:hover {
border-color: ${borderColor};
border-color: ${borderColorHover};
}
&:focus {
@ -46,12 +46,12 @@ export const sharedInputStyle = (theme: GrafanaTheme, invalid = false) => {
}
&:disabled {
background-color: ${palette.formComponent.disabledBackground};
color: ${palette.text.disabled};
background-color: ${theme.v2.palette.action.disabledBackground};
color: ${theme.v2.palette.action.disabledText};
}
&::placeholder {
color: ${palette.text.disabled};
color: ${theme.v2.palette.text.disabled};
opacity: 1;
}
`;

View File

@ -13,7 +13,7 @@ export interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
name: IconName;
/** Icon size */
size?: IconSize;
/** Need this to change hover effect based on what surface it is on */
/** @deprecated */
surface?: SurfaceType;
/** Type od the icon - mono or default */
iconType?: IconType;
@ -26,9 +26,9 @@ export interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
type SurfaceType = 'dashboard' | 'panel' | 'header';
export const IconButton = React.forwardRef<HTMLButtonElement, Props>(
({ name, size = 'md', surface = 'panel', iconType, tooltip, tooltipPlacement, className, ...restProps }, ref) => {
({ name, size = 'md', iconType, tooltip, tooltipPlacement, className, ...restProps }, ref) => {
const theme = useTheme();
const styles = getStyles(theme, surface, size);
const styles = getStyles(theme, size);
const button = (
<button ref={ref} {...restProps} className={cx(styles.button, className)}>
@ -50,19 +50,8 @@ export const IconButton = React.forwardRef<HTMLButtonElement, Props>(
IconButton.displayName = 'IconButton';
function getHoverColor(theme: GrafanaTheme, surface: SurfaceType): string {
switch (surface) {
case 'dashboard':
return theme.isLight ? theme.palette.gray95 : theme.palette.gray15;
case 'panel':
return theme.isLight ? theme.palette.gray6 : theme.palette.gray15;
case 'header':
return theme.isLight ? theme.colors.bg3 : theme.palette.gray25;
}
}
const getStyles = stylesFactory((theme: GrafanaTheme, surface: SurfaceType, size: IconSize) => {
const hoverColor = getHoverColor(theme, surface);
const getStyles = stylesFactory((theme: GrafanaTheme, size: IconSize) => {
const hoverColor = theme.v2.palette.action.hover;
const pixelSize = getSvgSize(size);
return {

View File

@ -30,10 +30,6 @@ interface StyleDeps {
}
export const getInputStyles = stylesFactory(({ theme, invalid = false, width }: StyleDeps) => {
const theme2 = theme.v2;
const borderRadius = theme2.shape.borderRadius(1);
const height = theme.v2.components.height.md;
const prefixSuffixStaticWidth = '28px';
const prefixSuffix = css`
position: absolute;
@ -48,7 +44,7 @@ export const getInputStyles = stylesFactory(({ theme, invalid = false, width }:
height: 100%;
/* Min width specified for prefix/suffix classes used outside React component*/
min-width: ${prefixSuffixStaticWidth};
color: ${theme2.palette.text.secondary};
color: ${theme.v2.palette.text.secondary};
`;
return {
@ -57,14 +53,14 @@ export const getInputStyles = stylesFactory(({ theme, invalid = false, width }:
css`
label: input-wrapper;
display: flex;
width: ${width ? `${theme2.spacing(width)}` : '100%'};
height: ${theme2.spacing(height)};
border-radius: ${borderRadius};
width: ${width ? `${theme.v2.spacing(width)}` : '100%'};
height: ${theme.v2.spacing(theme.v2.components.height.md)};
border-radius: ${theme.v2.shape.borderRadius()};
&:hover {
> .prefix,
.suffix,
.input {
border-color: ${invalid ? theme2.palette.error.border : theme2.palette.primary.border};
border-color: ${invalid ? theme.v2.palette.error.border : theme.v2.palette.primary.border};
}
// only show number buttons on hover
@ -141,14 +137,14 @@ export const getInputStyles = stylesFactory(({ theme, invalid = false, width }:
position: relative;
z-index: 0;
flex-grow: 1;
border-radius: ${borderRadius};
border-radius: ${theme.v2.shape.borderRadius()};
height: 100%;
width: 100%;
`
),
inputDisabled: css`
background-color: ${theme2.palette.formComponent.disabledBackground};
color: ${theme2.palette.text.disabled};
background-color: ${theme.v2.palette.action.disabledBackground};
color: ${theme.v2.palette.action.disabledText};
`,
addon: css`
label: input-addon;
@ -185,8 +181,8 @@ export const getInputStyles = stylesFactory(({ theme, invalid = false, width }:
prefixSuffix,
css`
label: input-prefix;
padding-left: ${theme2.spacing(1)};
padding-right: ${theme2.spacing(0.5)};
padding-left: ${theme.v2.spacing(1)};
padding-right: ${theme.v2.spacing(0.5)};
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
@ -196,8 +192,8 @@ export const getInputStyles = stylesFactory(({ theme, invalid = false, width }:
prefixSuffix,
css`
label: input-suffix;
padding-left: ${theme2.spacing(1)};
padding-right: ${theme2.spacing(0.5)};
padding-left: ${theme.v2.spacing(1)};
padding-right: ${theme.v2.spacing(0.5)};
margin-bottom: -2px;
border-left: none;
border-top-left-radius: 0;
@ -207,7 +203,7 @@ export const getInputStyles = stylesFactory(({ theme, invalid = false, width }:
),
loadingIndicator: css`
& + * {
margin-left: ${theme2.spacing(0.5)};
margin-left: ${theme.v2.spacing(0.5)};
}
`,
};

View File

@ -28,24 +28,16 @@ Menu.displayName = 'Menu';
/** @internal */
const getStyles = (theme: GrafanaTheme) => {
const wrapperBg = theme.colors.formInputBg;
const wrapperShadow = theme.isDark ? theme.palette.black : theme.palette.gray3;
const headerBg = theme.colors.formInputBg;
const headerSeparator = theme.colors.border3;
return {
header: css`
padding: 4px;
border-bottom: 1px solid ${headerSeparator};
background: ${headerBg};
margin-bottom: ${theme.spacing.xs};
border-radius: ${theme.border.radius.sm} ${theme.border.radius.sm} 0 0;
padding: ${theme.v2.spacing(0.5, 0.5, 1, 0.5)};
border-bottom: 1px solid ${theme.v2.palette.border1};
`,
wrapper: css`
background: ${wrapperBg};
box-shadow: 0 2px 5px 0 ${wrapperShadow};
background: ${theme.v2.palette.layer2};
box-shadow: ${theme.v2.shadows.z2};
display: inline-block;
border-radius: ${theme.border.radius.sm};
border-radius: ${theme.v2.shape.borderRadius()};
`,
};
};

View File

@ -38,13 +38,11 @@ MenuGroup.displayName = 'MenuGroup';
/** @internal */
const getStyles = (theme: GrafanaTheme) => {
const groupLabelColor = theme.colors.textWeak;
return {
groupLabel: css`
color: ${groupLabelColor};
font-size: ${theme.typography.size.sm};
line-height: ${theme.typography.lineHeight.md};
padding: ${theme.spacing.xs} ${theme.spacing.sm};
color: ${theme.v2.palette.text.secondary};
font-size: ${theme.v2.typography.size.sm};
padding: ${theme.v2.spacing(0.5, 1)};
`,
};
};

View File

@ -1,7 +1,7 @@
import React from 'react';
import { css, cx } from '@emotion/css';
import { GrafanaTheme, LinkTarget } from '@grafana/data';
import { styleMixins, useStyles } from '../../themes';
import { useStyles } from '../../themes';
import { Icon } from '../Icon/Icon';
import { IconName } from '../../types';
@ -56,39 +56,34 @@ MenuItem.displayName = 'MenuItem';
/** @internal */
const getStyles = (theme: GrafanaTheme) => {
const linkColor = theme.colors.text;
const linkColorHover = theme.colors.linkHover;
const itemBgHover = styleMixins.hoverColor(theme.colors.bg1, theme);
return {
link: css`
color: ${linkColor};
color: ${theme.v2.palette.text.primary};
display: flex;
cursor: pointer;
padding: 5px 12px 5px 10px;
&:hover {
color: ${linkColorHover};
color: ${theme.v2.palette.text.primary};
text-decoration: none;
}
`,
item: css`
background: none;
border-left: 2px solid transparent;
cursor: pointer;
white-space: nowrap;
&:hover {
background: ${itemBgHover};
border-image: linear-gradient(#f05a28 30%, #fbca0a 99%);
border-image-slice: 1;
background: ${theme.v2.palette.action.hover};
}
`,
activeItem: css`
background: ${theme.colors.bg2};
background: ${theme.v2.palette.action.selected};
`,
icon: css`
opacity: 0.7;
margin-right: 10px;
color: ${theme.colors.linkDisabled};
color: ${theme.v2.palette.text.secondary};
`,
};
};

View File

@ -132,10 +132,10 @@ const getStyles = (theme: GrafanaTheme) => {
return {
toolbar: css`
display: flex;
background: ${theme.colors.dashboardBg};
background: ${theme.v2.palette.layer0};
justify-content: flex-end;
flex-wrap: wrap;
padding: 0 ${spacing.sm} ${spacing.sm} ${spacing.md};
padding: ${theme.v2.spacing(0, 1, 1, 2)};
`,
toolbarLeft: css`
display: flex;

View File

@ -1,6 +1,5 @@
import React, { PureComponent } from 'react';
import { SelectableValue } from '@grafana/data';
import { Tooltip } from '../Tooltip/Tooltip';
import { ButtonSelect } from '../Dropdown/ButtonSelect';
import { ButtonGroup, ToolbarButton, ToolbarButtonVariant } from '../Button';
import { selectors } from '@grafana/e2e-selectors';
@ -68,16 +67,15 @@ export class RefreshPicker extends PureComponent<Props> {
return (
<div className="refresh-picker">
<ButtonGroup className="refresh-picker-buttons">
<Tooltip placement="bottom" content={tooltip!}>
<ToolbarButton
onClick={onRefresh}
variant={variant}
icon={isLoading ? 'fa fa-spinner' : 'sync'}
aria-label={selectors.components.RefreshPicker.runButton}
>
{text}
</ToolbarButton>
</Tooltip>
<ToolbarButton
tooltip={tooltip}
onClick={onRefresh}
variant={variant}
icon={isLoading ? 'fa fa-spinner' : 'sync'}
aria-label={selectors.components.RefreshPicker.runButton}
>
{text}
</ToolbarButton>
{!noIntervalPicker && (
<ButtonSelect
value={selectedValue}

View File

@ -3,7 +3,6 @@ import { useTheme } from '../../themes/ThemeContext';
import { getSelectStyles } from './getSelectStyles';
import { cx } from '@emotion/css';
import { SelectableValue } from '@grafana/data';
import { Icon } from '../Icon/Icon';
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
interface SelectMenuProps {
@ -46,7 +45,7 @@ export const SelectMenuOptions = React.forwardRef<HTMLDivElement, React.PropsWit
return (
<div
ref={ref}
className={cx(styles.option, isFocused && styles.optionFocused)}
className={cx(styles.option, isFocused && styles.optionFocused, isSelected && styles.optionSelected)}
{...innerProps}
aria-label="Select option"
>
@ -56,11 +55,6 @@ export const SelectMenuOptions = React.forwardRef<HTMLDivElement, React.PropsWit
{data.description && <div className={styles.optionDescription}>{data.description}</div>}
{data.component && <data.component />}
</div>
{isSelected && (
<span>
<Icon name="check" />
</span>
)}
</div>
);
}

View File

@ -11,7 +11,7 @@ import { GrafanaTheme } from '@grafana/data';
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const singleValue = css`
label: singleValue;
color: ${theme.colors.formInputText};
color: ${theme.v2.components.form.text};
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

View File

@ -3,17 +3,11 @@ import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
export const getSelectStyles = stylesFactory((theme: GrafanaTheme) => {
const bgColor = theme.colors.formInputBg;
const menuShadowColor = theme.colors.dropdownShadow;
const optionBgHover = theme.colors.dropdownOptionHoverBg;
const multiValueContainerBg = theme.colors.bg2;
const multiValueColor = theme.colors.text;
return {
menu: css`
label: grafana-select-menu;
background: ${bgColor};
box-shadow: 0px 4px 4px ${menuShadowColor};
background: ${theme.v2.palette.layer2};
box-shadow: ${theme.v2.shadows.z3};
position: relative;
min-width: 100%;
z-index: 1;
@ -28,8 +22,9 @@ export const getSelectStyles = stylesFactory((theme: GrafanaTheme) => {
white-space: nowrap;
cursor: pointer;
border-left: 2px solid transparent;
&:hover {
background: ${optionBgHover};
background: ${theme.v2.palette.action.hover};
}
`,
optionImage: css`
@ -40,32 +35,28 @@ export const getSelectStyles = stylesFactory((theme: GrafanaTheme) => {
optionDescription: css`
label: grafana-select-option-description;
font-weight: normal;
font-size: ${theme.typography.size.sm};
color: ${theme.colors.textWeak};
font-size: ${theme.v2.typography.size.sm};
color: ${theme.v2.palette.text.secondary};
white-space: normal;
line-height: ${theme.typography.lineHeight.md};
line-height: ${theme.v2.typography.body.lineHeight};
`,
optionBody: css`
label: grafana-select-option-body;
display: flex;
font-weight: ${theme.typography.weight.semibold};
font-weight: ${theme.v2.typography.fontWeightMedium};
flex-direction: column;
flex-grow: 1;
`,
optionFocused: css`
label: grafana-select-option-focused;
background: ${optionBgHover};
border-image: linear-gradient(#f05a28 30%, #fbca0a 99%);
border-image-slice: 1;
border-style: solid;
border-top: 0;
border-right: 0;
border-bottom: 0;
border-left-width: 2px;
background: ${theme.v2.palette.action.focus};
`,
optionSelected: css`
background: ${theme.v2.palette.action.selected};
`,
singleValue: css`
label: grafana-select-single-value;
color: ${theme.colors.formInputText};
color: ${theme.v2.components.form.text};
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@ -88,7 +79,7 @@ export const getSelectStyles = stylesFactory((theme: GrafanaTheme) => {
`,
loadingMessage: css`
label: grafana-select-loading-message;
padding: ${theme.spacing.sm};
padding: ${theme.v2.spacing(1)};
text-align: center;
width: 100%;
`,
@ -97,16 +88,16 @@ export const getSelectStyles = stylesFactory((theme: GrafanaTheme) => {
display: flex;
align-items: center;
line-height: 1;
background: ${multiValueContainerBg};
border-radius: ${theme.border.radius.sm};
margin: 0 ${theme.spacing.sm} 0 0;
padding: ${theme.spacing.xxs} 0 ${theme.spacing.xxs} ${theme.spacing.sm};
color: ${multiValueColor};
background: ${theme.v2.palette.layer2};
border-radius: ${theme.v2.shape.borderRadius()};
margin: ${theme.v2.spacing(0, 1, 0, 0)};
padding: ${theme.v2.spacing(0.25, 0, 0.25, 1)};
color: ${theme.v2.palette.text.primary};
font-size: ${theme.typography.size.sm};
`,
multiValueRemove: css`
label: grafana-select-multi-value-remove;
margin: 0 ${theme.spacing.xs};
margin: ${theme.v2.spacing(0, 0.5)};
cursor: pointer;
`,
};

View File

@ -89,8 +89,9 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({
overflow: hidden;
text-overflow: ellipsis;
padding: ${theme.spacing.xs};
:hover {
background-color: ${theme.colors.bg3};
background-color: ${theme.v2.palette.action.hover};
}
`,
filterListInput: css`

View File

@ -1,18 +0,0 @@
import React from 'react';
import { ThemeColors } from './ThemeColors';
export default {
title: 'Docs Overview/Theme',
component: ThemeColors,
decorators: [],
parameters: {
options: {
showPanel: false,
},
docs: {},
},
};
export const OldThemeDemo = () => {
return <ThemeColors />;
};

View File

@ -1,132 +0,0 @@
import React, { FC } from 'react';
import { css, cx } from '@emotion/css';
import { useTheme } from '../../themes/ThemeContext';
import { Icon } from '../Icon/Icon';
import { HorizontalGroup } from '../Layout/Layout';
interface DemoBoxProps {
bg: string;
border?: string;
textColor?: string;
}
const DemoBox: FC<DemoBoxProps> = ({ bg, border, children }) => {
const style = cx(
css`
padding: 32px 32px 16px 32px;
background: ${bg};
width: 100%;
`,
border
? css`
border: 1px solid ${border};
`
: null
);
return <div className={style}>{children}</div>;
};
const DemoText: FC<{ color?: string; bold?: boolean; size?: number }> = ({ color, bold, size, children }) => {
const style = css`
padding: 4px;
color: ${color ?? 'inherit'};
font-weight: ${bold ? 500 : 400};
font-size: ${size ?? 14}px;
`;
return <div className={style}>{children}</div>;
};
export const ThemeColors = () => {
const theme = useTheme();
return (
<div
className={css`
width: 100%;
`}
>
<DemoBox bg={theme.colors.dashboardBg}>
<DemoText>theme.colors.dashboardBg</DemoText>
<DemoBox bg={theme.colors.bg1} border={theme.colors.border1}>
<DemoText>
theme.colors.bg1 is the main & preferred content background for text and elements This box is using border1
</DemoText>
<DemoBox bg={theme.colors.bg2} border={theme.colors.border2}>
<DemoText>
colors.bg2 background used for elements placed on colors.bg1. Using colors.border1 should be used on
elements placed ontop of bg1. This box is using border2.
</DemoText>
<DemoBox bg={theme.colors.bg3} border={theme.colors.border2}>
<DemoText>colors.bg3 background used for elements placed on colors.bg2.</DemoText>
</DemoBox>
</DemoBox>
</DemoBox>
</DemoBox>
<HorizontalGroup>
<DemoBox bg={theme.colors.bodyBg}>
<>
Text on main body background (bg1)
<DemoText color={theme.colors.textHeading} size={24}>
textHeading Usually a bit bigger text <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.text}>
text <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.textSemiWeak}>
textSemiWeak <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.textWeak}>
textWeak <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.textFaint}>
textFaint <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.textStrong}>
textStrong <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.formInputText}>
formInputText <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.formLabel} bold>
formLabel is also bold <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.formDescription}>
formDescription <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.textBlue} bold>
textBlue usually bold
</DemoText>
<DemoText color={theme.colors.link}>link</DemoText>
<DemoText color={theme.colors.linkHover}>linkHover</DemoText>
<DemoText color={theme.colors.linkDisabled}>linkDisabled</DemoText>
<DemoText color={theme.colors.linkExternal}>linkExternal</DemoText>
</>
</DemoBox>
<DemoBox bg={theme.colors.formInputBg}>
This is inside form input bg (same as dashboard bg)
<DemoText color={theme.colors.formInputText}>formInputText</DemoText>
<DemoText color={theme.colors.formInputDisabledText}>formInputDisabledText</DemoText>
<DemoText color={theme.colors.formInputPlaceholderText}>formInputPlaceholderText</DemoText>
</DemoBox>
<DemoBox bg={theme.colors.bg2}>
Inside bg2
<DemoText color={theme.colors.text}>
text <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.textWeak}>
textWeak <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.textFaint}>
textFaint <Icon name="trash-alt" />
</DemoText>
<DemoText color={theme.colors.textStrong}>
textStrong <Icon name="trash-alt" />
</DemoText>
</DemoBox>
</HorizontalGroup>
</div>
);
};

View File

@ -1,6 +1,6 @@
import React from 'react';
import { EmotionPerfTest } from './EmotionPerfTest';
import { NewThemeDemo as NewThemeDemoComponent } from './NewThemeDemo';
import { ThemeDemo as NewThemeDemoComponent } from './ThemeDemo';
export default {
title: 'Docs Overview/Theme',
@ -14,7 +14,7 @@ export default {
},
};
export const NewThemeDemo = () => {
export const ThemeDemo = () => {
return <NewThemeDemoComponent />;
};

View File

@ -2,7 +2,7 @@ import React, { FC, useState } from 'react';
import { css, cx } from '@emotion/css';
import { useTheme } from '../../themes/ThemeContext';
import { Icon } from '../Icon/Icon';
import { HorizontalGroup } from '../Layout/Layout';
import { HorizontalGroup, VerticalGroup } from '../Layout/Layout';
import { GrafanaThemeV2, ThemePaletteColor } from '@grafana/data';
import { CollapsableSection } from '../Collapse/CollapsableSection';
import { Field } from '../Forms/Field';
@ -10,6 +10,10 @@ import { Input } from '../Input/Input';
import { RadioButtonGroup } from '../Forms/RadioButtonGroup/RadioButtonGroup';
import { Switch } from '../Switch/Switch';
import { allButtonVariants, Button } from '../Button';
import { InlineField } from '../Forms/InlineField';
import { InlineFieldRow } from '../Forms/InlineFieldRow';
import { Card } from '../Card/Card';
import { Select } from '../Select/Select';
interface DemoBoxProps {
bg?: string;
@ -45,10 +49,12 @@ const DemoText: FC<{ color?: string; bold?: boolean; size?: number }> = ({ color
return <div className={style}>{children}</div>;
};
export const NewThemeDemo = () => {
export const ThemeDemo = () => {
const [radioValue, setRadioValue] = useState('v');
const [boolValue, setBoolValue] = useState(false);
const [selectValue, setSelectValue] = useState('Item 2');
const oldTheme = useTheme();
const t = oldTheme.v2;
const richColors = [
@ -60,6 +66,12 @@ export const NewThemeDemo = () => {
t.palette.info,
];
const selectOptions = [
{ label: 'Item 1', value: 'Item 1' },
{ label: 'Item 2', value: 'Item 2' },
{ label: 'Item 3', value: 'Item 3' },
{ label: 'Item 4', value: 'Item 4' },
];
const radioOptions = [
{ value: 'h', label: 'Horizontal' },
{ value: 'v', label: 'Vertical' },
@ -103,6 +115,7 @@ export const NewThemeDemo = () => {
<tr>
<td>name</td>
<td>main</td>
<td>shade (used for hover)</td>
<td>border & text</td>
</tr>
</thead>
@ -122,6 +135,9 @@ export const NewThemeDemo = () => {
<Field label="Input disabled" disabled>
<Input placeholder="Placeholder" value="Disabled value" />
</Field>
<Field label="Select">
<Select options={selectOptions} value={selectValue} onChange={(v) => setSelectValue(v?.value!)} />
</Field>
<Field label="Radio label">
<RadioButtonGroup options={radioOptions} value={radioValue} onChange={setRadioValue} />
</Field>
@ -136,31 +152,61 @@ export const NewThemeDemo = () => {
<Switch value={false} disabled />
</Field>
</HorizontalGroup>
<VerticalGroup>
<div>Inline forms</div>
<InlineFieldRow>
<InlineField label="Label">
<Input placeholder="Placeholder" />
</InlineField>
<InlineField label="Another Label" disabled>
<Input placeholder="Disabled" />
</InlineField>
</InlineFieldRow>
</VerticalGroup>
</DemoBox>
</CollapsableSection>
<CollapsableSection label="Shadows" isOpen={true}>
<DemoBox bg={t.palette.layer1}>
<HorizontalGroup>
<ShadowDemo name="Z1" shadow={t.shadows.z1} />
<ShadowDemo name="Z2" shadow={t.shadows.z2} />
<ShadowDemo name="Z3" shadow={t.shadows.z3} />
{Object.keys(t.shadows).map((key) => (
<ShadowDemo name={key} shadow={(t.shadows as any)[key]} key={key} />
))}
</HorizontalGroup>
</DemoBox>
</CollapsableSection>
<CollapsableSection label="Buttons" isOpen={true}>
<DemoBox bg={t.palette.layer1}>
<HorizontalGroup>
{allButtonVariants.map((variant) => (
<Button variant={variant} key={variant}>
{variant}
<VerticalGroup spacing="lg">
<HorizontalGroup>
{allButtonVariants.map((variant) => (
<Button variant={variant} key={variant}>
{variant}
</Button>
))}
<Button variant="primary" disabled>
Disabled
</Button>
))}
<Button variant="primary" disabled>
Disabled
</Button>
</HorizontalGroup>
</HorizontalGroup>
<Card heading="Button inside card">
<Card.Actions>
<>
{allButtonVariants.map((variant) => (
<Button variant={variant} key={variant}>
{variant}
</Button>
))}
<Button variant="primary" disabled>
Disabled
</Button>
</>
</Card.Actions>
</Card>
</VerticalGroup>
</DemoBox>
</CollapsableSection>
<CollapsableSection label="Actions" isOpen={true}>
<ActionsDemo />
</CollapsableSection>
</DemoBox>
</div>
);
@ -183,14 +229,23 @@ export function RichColorDemo({ theme, color }: RichColorDemoProps) {
color: ${color.contrastText};
padding: 8px;
font-weight: 500;
&:hover {
background: ${theme.palette.getHoverColor(color.main)};
}
`}
>
{color.main}
</div>
</td>
<td>
<div
className={css`
background: ${color.shade};
color: ${color.contrastText};
border-radius: 4px;
padding: 8px;
`}
>
{color.shade}
</div>
</td>
<td>
<div
className={css`
@ -198,9 +253,6 @@ export function RichColorDemo({ theme, color }: RichColorDemoProps) {
color: ${color.text};
border-radius: 4px;
padding: 8px;
&:hover {
color: ${color.text};
}
`}
>
{color.text}
@ -245,3 +297,55 @@ export function ShadowDemo({ name, shadow }: { name: string; shadow: string }) {
});
return <div className={style}>{name}</div>;
}
export function ActionsDemo() {
const t = useTheme().v2;
const item = css({
padding: '8px',
':hover': {
background: t.palette.action.hover,
},
});
const hover = css({
background: t.palette.action.hover,
});
const selected = css({
background: t.palette.action.selected,
});
const focused = css({
background: t.palette.action.focus,
});
return (
<HorizontalGroup>
<DemoBox bg={t.palette.layer0}>
<VerticalGroup>
<div className={item}>item</div>
<div className={item}>item</div>
<div className={cx(item, hover)}>item hover</div>
<div className={cx(item, selected)}>item selected</div>
<div className={cx(item, focused)}>item focused</div>
</VerticalGroup>
</DemoBox>
<DemoBox bg={t.palette.layer1}>
<VerticalGroup>
<div className={item}>item</div>
<div className={item}>item</div>
<div className={cx(item, hover)}>item hover</div>
<div className={cx(item, selected)}>item selected</div>
<div className={cx(item, focused)}>item focused</div>
</VerticalGroup>
</DemoBox>
<DemoBox bg={t.palette.layer2}>
<VerticalGroup>
<div className={item}>item</div>
<div className={item}>item</div>
<div className={cx(item, hover)}>item hover</div>
<div className={cx(item, selected)}>item selected</div>
<div className={cx(item, focused)}>item focused</div>
</VerticalGroup>
</DemoBox>
</HorizontalGroup>
);
}

View File

@ -12,18 +12,16 @@ import { TimeRangeList } from './TimeRangeList';
import { TimePickerFooter } from './TimePickerFooter';
const getStyles = stylesFactory((theme: GrafanaTheme, isReversed, hideQuickRanges, isContainerTall) => {
const containerBorder = theme.isDark ? theme.palette.dark9 : theme.palette.gray5;
return {
container: css`
background: ${theme.colors.bodyBg};
box-shadow: 0px 0px 20px ${theme.colors.dropdownShadow};
background: ${theme.v2.palette.layer2};
box-shadow: ${theme.v2.shadows.z4};
position: absolute;
z-index: ${theme.zIndex.dropdown};
width: 546px;
top: 116%;
border-radius: 2px;
border: 1px solid ${containerBorder};
border: 1px solid ${theme.v2.palette.border0};
${isReversed ? 'left' : 'right'}: 0;
@media only screen and (max-width: ${theme.breakpoints.lg}) {
@ -37,14 +35,14 @@ const getStyles = stylesFactory((theme: GrafanaTheme, isReversed, hideQuickRange
leftSide: css`
display: flex;
flex-direction: column;
border-right: ${isReversed ? 'none' : `1px solid ${theme.colors.border1}`};
border-right: ${isReversed ? 'none' : `1px solid ${theme.v2.palette.divider}`};
width: ${!hideQuickRanges ? '60%' : '100%'};
overflow: hidden;
order: ${isReversed ? 1 : 0};
`,
rightSide: css`
width: 40% !important;
border-right: ${isReversed ? `1px solid ${theme.colors.border1}` : 'none'};
border-right: ${isReversed ? `1px solid ${theme.v2.palette.divider}` : 'none'};
@media only screen and (max-width: ${theme.breakpoints.lg}) {
width: 100% !important;
@ -63,12 +61,11 @@ const getNarrowScreenStyles = stylesFactory((theme: GrafanaTheme) => {
flex-direction: row;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid ${theme.colors.border1};
border-bottom: 1px solid ${theme.v2.palette.divider};
padding: 7px 9px 7px 9px;
`,
body: css`
border-bottom: 1px solid ${theme.colors.border1};
box-shadow: inset 0px 2px 2px ${theme.colors.dropdownShadow};
border-bottom: 1px solid ${theme.v2.palette.divider};
`,
form: css`
padding: 7px 9px 7px 9px;
@ -97,11 +94,8 @@ const getFullScreenStyles = stylesFactory((theme: GrafanaTheme, hideQuickRanges?
});
const getEmptyListStyles = stylesFactory((theme: GrafanaTheme) => {
const formBackground = theme.isDark ? theme.palette.gray15 : theme.palette.gray98;
return {
container: css`
background-color: ${formBackground};
padding: 12px;
margin: 12px;

View File

@ -1,8 +1,7 @@
import React, { memo } from 'react';
import { css } from '@emotion/css';
import { css, cx } from '@emotion/css';
import { GrafanaTheme, TimeOption } from '@grafana/data';
import { useTheme, stylesFactory, styleMixins } from '../../../themes';
import { Icon } from '../../Icon/Icon';
import { useTheme, stylesFactory } from '../../../themes';
const getStyles = stylesFactory((theme: GrafanaTheme) => {
return {
@ -11,20 +10,16 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
align-items: center;
justify-content: space-between;
padding: 7px 9px 7px 9px;
border-left: 2px solid rgba(255, 255, 255, 0);
&:hover {
background: ${styleMixins.hoverColor(theme.colors.bg1, theme)};
border-image: linear-gradient(#f05a28 30%, #fbca0a 99%);
border-image-slice: 1;
border-style: solid;
border-top: 0;
border-right: 0;
border-bottom: 0;
border-left-width: 2px;
background: ${theme.v2.palette.action.hover};
cursor: pointer;
}
`,
selected: css`
background: ${theme.v2.palette.action.selected};
}
`,
};
});
@ -39,9 +34,8 @@ export const TimeRangeOption = memo<Props>(({ value, onSelect, selected = false
const styles = getStyles(theme);
return (
<div className={styles.container} onClick={() => onSelect(value)} tabIndex={-1}>
<div className={cx(styles.container, selected && styles.selected)} onClick={() => onSelect(value)} tabIndex={-1}>
<span>{value.display}</span>
{selected ? <Icon name="check" /> : null}
</div>
);
});

View File

@ -31,7 +31,8 @@ $popper-margin-from-ref: 5px;
background: $tooltipBackground;
border-radius: $border-radius-sm;
box-shadow: $tooltipShadow;
padding: $space-sm;
padding: $space-xs $space-sm;
font-size: $font-size-sm;
color: $tooltipColor;
font-weight: $font-weight-semi-bold;

View File

@ -54,9 +54,17 @@ $gray-5: ${theme.palette.gray5};
$gray-6: ${theme.palette.gray6};
$input-black: ${theme.colors.formInputBg};
$white: ${theme.palette.white};
$layer0: ${theme.v2.palette.layer0};
$layer1: ${theme.v2.palette.layer1};
$layer2: ${theme.v2.palette.layer2};
$divider: ${theme.v2.palette.divider};
$border0: ${theme.v2.palette.border0};
$border1: ${theme.v2.palette.border1};
// Accent colors
// -------------------------
$blue: ${theme.palette.blue85};
@ -120,9 +128,10 @@ $hr-border-color: $dark-9;
// Panel
// -------------------------
$panel-bg: ${theme.colors.panelBg};
$panel-border: 1px solid ${theme.colors.panelBorder};
$panel-header-hover-bg: ${theme.colors.bg2};
$panel-bg: ${theme.v2.components.panel.background};
$panel-border: ${theme.v2.components.panel.border};
$panel-header-hover-bg: ${theme.v2.palette.action.hover};
$panel-box-shadow: ${theme.v2.components.panel.boxShadow};
$panel-corner: $panel-bg;
// page header
@ -141,8 +150,8 @@ $code-tag-bg: $dark-1;
$code-tag-border: $dark-9;
// cards
$card-background: ${theme.colors.bg2};
$card-background-hover: ${styleMixins.hoverColor(theme.colors.bg2, theme)};
$card-background: ${theme.v2.palette.layer2};
$card-background-hover: ${theme.v2.palette.layer2};
$card-shadow: none;
// Lists
@ -159,11 +168,10 @@ $scrollbarBorder: black;
// Tables
// -------------------------
$table-bg-accent: ${styleMixins.hoverColor(theme.colors.bg1, theme)}; // for striping
$table-border: $dark-6; // table and cell border
$table-bg-odd: $dark-3;
$table-bg-hover: $dark-6;
$table-bg-accent: ${theme.v2.palette.layer2};
$table-border: ${theme.v2.palette.border1};
$table-bg-odd: ${theme.v2.palette.getHoverColor(theme.v2.palette.layer1, 0.02)};
$table-bg-hover: ${theme.v2.palette.getHoverColor(theme.v2.palette.layer1, 0.05)};
// Buttons
// -------------------------
@ -221,10 +229,10 @@ $typeahead-selected-color: $yellow;
// Dropdowns
// -------------------------
$dropdownBackground: $panel-bg;
$dropdownBorder: ${theme.colors.panelBorder};
$dropdownDividerTop: transparent;
$dropdownDividerBottom: ${theme.palette.gray25};
$dropdownBackground: ${theme.v2.palette.layer2};
$dropdownBorder: ${theme.v2.palette.border0};
$dropdownDividerTop: ${theme.v2.palette.divider};
$dropdownDividerBottom: ${theme.v2.palette.divider};
$dropdownLinkColor: $link-color;
$dropdownLinkColorHover: $white;
@ -252,17 +260,14 @@ $side-menu-header-color: ${theme.colors.text};
// Menu dropdowns
// -------------------------
$menu-dropdown-bg: ${theme.colors.bg1};
$menu-dropdown-hover-bg: ${theme.colors.bg2};
$menu-dropdown-shadow: 5px 5px 20px -5px $black;
$menu-dropdown-bg: ${theme.v2.palette.layer2};
$menu-dropdown-hover-bg: ${theme.v2.palette.action.hover};
$menu-dropdown-shadow: ${theme.v2.shadows.z3};
// Tabs
// -------------------------
$tab-border-color: $dark-9;
// Toolbar
$toolbar-bg: $input-black;
// Form states and alerts
// -------------------------
$warning-text-color: $warn;
@ -276,22 +281,21 @@ $alert-info-bg: linear-gradient(100deg, $blue-base, $blue-shade);
// Tooltips and popovers
// -------------------------
$tooltipColor: $text-color;
$tooltipArrowWidth: 5px;
$tooltipLinkColor: $link-color;
$tooltipShadow: 0 0 10px black;
$graph-tooltip-bg: $dark-1;
$tooltipBackground: $gray15;
$tooltipColor: $text-color;
$tooltipArrowColor: $tooltipBackground;
$tooltipBackgroundError: $brand-danger;
$tooltipBackground: ${theme.v2.palette.layer2};
$tooltipColor: ${theme.v2.palette.text.primary};
$tooltipArrowColor: ${theme.v2.palette.layer2};
$tooltipBackgroundError: ${theme.v2.palette.error.main};
$tooltipShadow: ${theme.v2.shadows.z2};
$popover-bg: $dark-2;
$popover-color: $text-color;
$popover-border-color: $dark-9;
$popover-header-bg: $dark-9;
$popover-shadow: 0 0 20px black;
$popover-bg: ${theme.v2.palette.layer2};
$popover-color: ${theme.v2.palette.text.primary};
$popover-border-color: ${theme.v2.palette.border1};
$popover-header-bg: ${theme.v2.palette.layer2};
$popover-shadow: ${theme.v2.shadows.z4};
$popover-help-bg: $tooltipBackground;
$popover-help-color: $text-color;
@ -377,9 +381,6 @@ $panel-editor-tabs-line-color: #e3e3e3;
$panel-editor-viz-item-bg-hover: darken($blue-base, 46%);
$panel-options-group-border: none;
$panel-options-group-header-bg: ${theme.colors.bg2};
$panel-grid-placeholder-bg: darken(${theme.palette.blue77}, 30%);
$panel-grid-placeholder-shadow: 0 0 4px ${theme.palette.blue80};

View File

@ -51,6 +51,15 @@ $gray-7: ${theme.palette.gray7};
$white: ${theme.palette.white};
$layer0: ${theme.v2.palette.layer0};
$layer1: ${theme.v2.palette.layer1};
$layer2: ${theme.v2.palette.layer2};
$divider: ${theme.v2.palette.divider};
$border0: ${theme.v2.palette.border0};
$border1: ${theme.v2.palette.border1};
// Accent colors
// -------------------------
$blue: ${theme.colors.textBlue};
@ -113,10 +122,11 @@ $hr-border-color: $gray-4 !default;
// Panel
// -------------------------
$panel-bg: ${theme.colors.panelBg};
$panel-border: 1px solid ${theme.colors.panelBorder};
$panel-header-hover-bg: ${theme.colors.bg2};
$panel-corner: $gray-4;
$panel-bg: ${theme.v2.components.panel.background};
$panel-border: ${theme.v2.components.panel.border};
$panel-header-hover-bg: ${theme.v2.palette.action.hover};
$panel-box-shadow: ${theme.v2.components.panel.boxShadow};
$panel-corner: $panel-bg;
// Page header
$page-header-bg: ${theme.colors.pageHeaderBg};
@ -134,8 +144,8 @@ $code-tag-bg: $gray-6;
$code-tag-border: $gray-4;
// cards
$card-background: ${theme.colors.bg2};
$card-background-hover: ${styleMixins.hoverColor(theme.colors.bg2, theme)};
$card-background: ${theme.v2.palette.layer2};
$card-background-hover: ${theme.v2.palette.layer2};
$card-shadow: none;
// Lists
@ -152,11 +162,10 @@ $scrollbarBorder: $gray-7;
// Tables
// -------------------------
$table-bg-accent: ${styleMixins.hoverColor(theme.colors.bg1, theme)};
$table-border: $gray-3; // table and cell border
$table-bg-odd: $gray-6;
$table-bg-hover: $gray-5;
$table-bg-accent: ${theme.v2.palette.layer2};
$table-border: ${theme.v2.palette.border1};
$table-bg-odd: ${theme.v2.palette.getHoverColor(theme.v2.palette.layer1, 0.02)};
$table-bg-hover: ${theme.v2.palette.getHoverColor(theme.v2.palette.layer1, 0.05)};
// Buttons
// -------------------------
@ -214,10 +223,10 @@ $typeahead-selected-color: $yellow;
// Dropdowns
// -------------------------
$dropdownBackground: $white;
$dropdownBorder: $gray-4;
$dropdownDividerTop: $gray-6;
$dropdownDividerBottom: $gray-4;
$dropdownBackground: ${theme.v2.palette.layer2};
$dropdownBorder: ${theme.v2.palette.border0};
$dropdownDividerTop: ${theme.v2.palette.divider};
$dropdownDividerBottom: ${theme.v2.palette.divider};
$dropdownLinkColor: $dark-2;
$dropdownLinkColorHover: $link-color;
@ -247,17 +256,14 @@ $side-menu-header-color: ${theme.palette.gray95};
// Menu dropdowns
// -------------------------
$menu-dropdown-bg: $panel-bg;
$menu-dropdown-hover-bg: $gray-6;
$menu-dropdown-shadow: 5px 5px 10px -5px $gray-1;
$menu-dropdown-bg: ${theme.v2.palette.layer2};
$menu-dropdown-hover-bg: ${theme.v2.palette.action.hover};
$menu-dropdown-shadow: ${theme.v2.shadows.z3};
// Tabs
// -------------------------
$tab-border-color: $gray-5;
// Toolbar
$toolbar-bg: white;
// Form states and alerts
// -------------------------
$warning-text-color: lighten($orange, 10%);
@ -270,22 +276,23 @@ $alert-warning-bg: linear-gradient(90deg, $red-base, $red-shade);
$alert-info-bg: linear-gradient(100deg, $blue-base, $blue-shade);
// Tooltips and popovers
$tooltipBackground: $gray-1;
$tooltipColor: $gray-7;
$tooltipArrowColor: $tooltipBackground; // Used by Angular tooltip
$tooltipBackgroundError: $brand-danger;
$tooltipShadow: 0 0 5px $gray60;
$tooltipBackground: ${theme.v2.palette.layer2};
$tooltipColor: ${theme.v2.palette.text.primary};
$tooltipArrowColor: ${theme.v2.palette.layer2};
$tooltipBackgroundError: ${theme.v2.palette.error.main};
$tooltipShadow: ${theme.v2.shadows.z2};
$popover-bg: ${theme.v2.palette.layer2};
$popover-color: ${theme.v2.palette.text.primary};
$popover-border-color: ${theme.v2.palette.border1};
$popover-header-bg: ${theme.v2.palette.layer2};
$popover-shadow: ${theme.v2.shadows.z4};
$graph-tooltip-bg: $gray-5;
$tooltipArrowWidth: 5px;
$tooltipLinkColor: lighten($tooltipColor, 5%);
$popover-bg: $page-bg;
$popover-color: $text-color;
$popover-border-color: $gray-5;
$popover-header-bg: $gray-5;
$popover-shadow: 0 0 20px $white;
$popover-error-bg: $btn-danger-bg;
$popover-help-bg: $tooltipBackground;
$popover-help-color: $tooltipColor;
@ -370,9 +377,6 @@ $panel-editor-tabs-line-color: $dark-2;
$panel-editor-viz-item-bg-hover: lighten($blue-base, 45%);
$panel-options-group-border: none;
$panel-options-group-header-bg: $gray-5;
$panel-grid-placeholder-bg: lighten(${theme.palette.blue95}, 30%);
$panel-grid-placeholder-shadow: 0 0 4px ${theme.palette.blue95};

View File

@ -1,6 +1,8 @@
import defaultTheme, { commonColorsPalette } from './default';
import { GrafanaThemeType, GrafanaTheme, createTheme } from '@grafana/data';
const v2 = createTheme({ palette: { mode: 'dark' } });
const basicColors = {
...commonColorsPalette,
black: '#000000',
@ -35,28 +37,28 @@ const basicColors = {
};
const backgrounds = {
bg1: basicColors.gray10,
bg2: basicColors.gray15,
bg3: basicColors.gray25,
dashboardBg: basicColors.gray05,
bgBlue1: basicColors.blue80,
bgBlue2: basicColors.blue77,
bg1: v2.palette.layer1,
bg2: v2.palette.layer2,
bg3: v2.palette.action.hover,
dashboardBg: v2.palette.layer0,
bgBlue1: v2.palette.primary.main,
bgBlue2: v2.palette.primary.shade,
};
const borders = {
border1: basicColors.gray15,
border2: basicColors.gray25,
border3: basicColors.gray33,
border1: v2.palette.border0,
border2: v2.palette.border1,
border3: v2.palette.border2,
};
const textColors = {
textStrong: basicColors.gray98,
textHeading: basicColors.gray4,
text: basicColors.gray85,
textSemiWeak: basicColors.gray70,
textWeak: basicColors.gray60,
textFaint: basicColors.gray33,
textBlue: basicColors.blue85,
textStrong: v2.palette.text.maxContrast,
textHeading: v2.palette.text.primary,
text: v2.palette.text.primary,
textSemiWeak: v2.palette.text.secondary,
textWeak: v2.palette.text.disabled,
textFaint: v2.palette.text.disabled,
textBlue: v2.palette.primary.text,
};
const form = {
@ -130,7 +132,7 @@ const darkTheme: GrafanaTheme = {
shadows: {
listItem: 'none',
},
v2: createTheme({ palette: { mode: 'dark' } }),
v2: v2,
};
export default darkTheme;

View File

@ -1,6 +1,8 @@
import defaultTheme, { commonColorsPalette } from './default';
import { GrafanaThemeType, GrafanaTheme, createTheme } from '@grafana/data';
const v2 = createTheme({ palette: { mode: 'light' } });
const basicColors = {
...commonColorsPalette,
black: '#000000',
@ -34,18 +36,18 @@ const basicColors = {
};
const backgrounds = {
bg1: basicColors.white,
bg2: basicColors.gray97,
bg3: basicColors.gray90,
dashboardBg: basicColors.gray98,
bg1: v2.palette.layer1,
bg2: v2.palette.layer2,
bg3: v2.palette.action.hover,
dashboardBg: v2.palette.layer0,
bgBlue1: basicColors.blue80,
bgBlue2: basicColors.blue77,
};
const borders = {
border1: basicColors.gray90,
border2: basicColors.gray85,
border3: basicColors.gray70,
border1: v2.palette.border0,
border2: v2.palette.border1,
border3: v2.palette.border2,
};
const textColors = {
@ -131,7 +133,7 @@ const lightTheme: GrafanaTheme = {
shadows: {
listItem: 'none',
},
v2: createTheme({ palette: { mode: 'light' } }),
v2: v2,
};
export default lightTheme;

View File

@ -139,8 +139,8 @@ function renderTitle(title: string, breadcrumbs: NavModelBreadcrumb[]) {
const getStyles = (theme: GrafanaTheme) => ({
headerCanvas: css`
background: ${theme.colors.bg2};
border-bottom: 1px solid ${theme.colors.border1};
background: ${theme.v2.palette.layer0};
border-bottom: 1px solid ${theme.v2.palette.border0};
`,
});

View File

@ -2,20 +2,20 @@
exports[`Render should render component 1`] = `
<div
className="panel-container css-1sl7nld"
className="panel-container css-bopjp7"
>
<AddPanelWidgetHandle
onCancel={[Function]}
styles={
Object {
"actionsRow": "css-txvz1e",
"actionsRow": "css-7gkft9",
"actionsWrapper": "css-gxxmom",
"backButton": "css-1cdxa9p",
"headerRow": "css-1ka09x",
"headerRow": "css-3sdqvi",
"libraryPanelsWrapper": "css-18m13of",
"noMargin": "css-u023fv",
"panelSearchInput": "css-2ug8g3",
"wrapper": "css-1sl7nld",
"wrapper": "css-bopjp7",
}
}
>
@ -25,7 +25,7 @@ exports[`Render should render component 1`] = `
className="css-gxxmom"
>
<div
className="css-txvz1e"
className="css-7gkft9"
>
<div
aria-label="Add new panel"

View File

@ -90,7 +90,7 @@ export const OptionsPaneCategory: FC<OptionsPaneCategoryProps> = React.memo(
const getStyles = (theme: GrafanaTheme) => {
return {
box: css`
border-bottom: 1px solid ${theme.colors.pageHeaderBorder};
border-bottom: 1px solid ${theme.v2.palette.divider};
&:last-child {
border-bottom: none;
}

View File

@ -64,6 +64,9 @@ export const OptionsPaneOptions: React.FC<Props> = (props) => {
for (const item of vizOptions) {
mainBoxElements.push(item.render());
}
for (const item of justOverrides) {
mainBoxElements.push(item.render());
}
break;
case OptionFilter.Overrides:
for (const override of justOverrides) {
@ -95,9 +98,6 @@ export const OptionsPaneOptions: React.FC<Props> = (props) => {
<div className={styles.scrollWrapper}>
<CustomScrollbar autoHeightMin="100%">
<div className={styles.mainBox}>{mainBoxElements}</div>
{!isSearching && listMode === OptionFilter.All && (
<div className={styles.overridesBox}>{justOverrides.map((override) => override.render())}</div>
)}
</CustomScrollbar>
</div>
</div>
@ -180,14 +180,8 @@ const getStyles = (theme: GrafanaTheme) => ({
`,
mainBox: css`
background: ${theme.colors.bg1};
margin-bottom: ${theme.spacing.md};
border: 1px solid ${theme.colors.border1};
border-top: none;
`,
overridesBox: css`
background: ${theme.colors.bg1};
border: 1px solid ${theme.colors.border1};
margin-bottom: ${theme.spacing.md};
flex-grow: 1;
`,
});

View File

@ -486,6 +486,7 @@ export const getStyles = stylesFactory((theme: GrafanaTheme, props: Props) => {
min-height: 0;
width: 100%;
padding-left: ${paneSpacing};
padding-right: 2px;
`,
tabsWrapper: css`
height: 100%;

View File

@ -381,7 +381,7 @@ const getTransformationCardStyles = stylesFactory((theme: GrafanaTheme) => {
}
&:hover {
background: ${theme.colors.bg3};
background: ${theme.v2.palette.action.hover};
box-shadow: none;
border: none;
}

View File

@ -25,7 +25,7 @@ export const DiffValues: React.FC<DiffProps> = ({ diff }) => {
};
const getStyles = (theme: GrafanaTheme) => css`
background-color: ${theme.colors.bg3};
background-color: ${theme.v2.palette.action.hover};
border-radius: ${theme.border.radius.md};
color: ${theme.colors.textHeading};
font-size: ${theme.typography.size.base};

View File

@ -69,18 +69,21 @@ const getStyles = (theme: GrafanaTheme) => {
display: flex;
flex-shrink: 0;
cursor: pointer;
background: ${theme.colors.bg2};
border: 1px solid ${theme.colors.border2};
border-radius: ${theme.border.radius.sm};
background: ${theme.v2.palette.layer2};
border-radius: ${theme.v2.shape.borderRadius()};
box-shadow: ${theme.v2.shadows.z0};
align-items: center;
padding: 8px;
width: 100%;
position: relative;
overflow: hidden;
height: 55px;
transition: ${theme.v2.transitions.create(['background'], {
duration: theme.v2.transitions.duration.short,
})};
&:hover {
background: ${styleMixins.hoverColor(theme.colors.bg2, theme)};
background: ${styleMixins.hoverColor(theme.v2.palette.layer2, theme)};
}
`,
itemContent: css`

View File

@ -2,7 +2,7 @@
exports[`MetaInfoText should render component 1`] = `
<div
className="css-1jdkzq2"
className="css-1egjxkg"
>
<Memo(MetaInfoItem)
key="0-label"

View File

@ -136,8 +136,8 @@ const getQueryEditorRowTitleStyles = stylesFactory((theme: GrafanaTheme) => {
&:hover {
.query-name-wrapper {
background: ${theme.colors.bg3};
border: 1px dashed ${theme.colors.border3};
background: ${theme.v2.palette.action.hover};
border: 1px dashed ${theme.v2.palette.border1};
}
.query-name-edit-icon {

View File

@ -56,9 +56,17 @@ $gray-5: #ececec;
$gray-6: #f4f5f8;
$input-black: #0b0c0e;
$white: #ffffff;
$layer0: #0d0f16;
$layer1: #181b1f;
$layer2: #22252b;
$divider: rgba(218,224,254,0.06);
$border0: #181b1f;
$border1: rgba(218,224,254,0.15);
// Accent colors
// -------------------------
$blue: #33a2e5;
@ -66,7 +74,7 @@ $red: $red-base;
$yellow: #ecbb13;
$orange: #eb7b18;
$purple: #9933cc;
$variable: #33a2e5;
$variable: #5790FF;
$brand-primary: #eb7b18;
$brand-success: #299c46;
@ -86,17 +94,17 @@ $critical: #e02f44;
// Scaffolding
// -------------------------
$body-bg: #141619;
$page-bg: #141619;
$dashboard-bg: #0b0c0e;
$body-bg: #181b1f;
$page-bg: #181b1f;
$dashboard-bg: #0d0f16;
$text-color-strong: #f7f8fa;
$text-color: #c7d0d9;
$text-color-semi-weak: #9fa7b3;
$text-color-weak: #7b8087;
$text-color-faint: #464c54;
$text-color-emphasis: #f7f8fa;
$text-blue: #33a2e5;
$text-color-strong: #fff;
$text-color: rgba(255, 255, 255, 0.75);
$text-color-semi-weak: rgba(255, 255, 255, 0.50);
$text-color-weak: rgba(255, 255, 255, 0.35);
$text-color-faint: rgba(255, 255, 255, 0.35);
$text-color-emphasis: #fff;
$text-blue: #5790FF;
$text-shadow-faint: 1px 1px 4px rgb(45, 45, 45);
$textShadow: none;
@ -114,7 +122,7 @@ $external-link-color: #33a2e5;
// Typography
// -------------------------
$headings-color: #d8d9da;
$headings-color: rgba(255, 255, 255, 0.75);
$abbr-border-color: $gray-2 !default;
$text-muted: $text-color-weak;
@ -122,29 +130,30 @@ $hr-border-color: $dark-9;
// Panel
// -------------------------
$panel-bg: #141619;
$panel-border: 1px solid #202226;
$panel-header-hover-bg: #202226;
$panel-bg: #181b1f;
$panel-border: #181b1f;
$panel-header-hover-bg: rgba(255, 255, 255, 0.08);
$panel-box-shadow: 0px 1px 1px -1px rgba(0,0,0,0.5),0px 1px 1px 0px rgba(0,0,0,0.4),0px 1px 3px 0px rgba(0,0,0,0.3);
$panel-corner: $panel-bg;
// page header
$page-header-bg: #202226;
$page-header-bg: #22252b;
$page-header-shadow: inset 0px -4px 14px $dark-3;
$page-header-border-color: #202226;
$page-header-border-color: #181b1f;
$divider-border-color: $gray-1;
// Graphite Target Editor
$tight-form-func-bg: #202226;
$tight-form-func-highlight-bg: #25272b;
$tight-form-func-bg: #22252b;
$tight-form-func-highlight-bg: #272a30;
$modal-backdrop-bg: #2c3235;
$modal-backdrop-bg: rgba(255, 255, 255, 0.08);
$code-tag-bg: $dark-1;
$code-tag-border: $dark-9;
// cards
$card-background: #202226;
$card-background-hover: #25272b;
$card-background: #22252b;
$card-background-hover: #22252b;
$card-shadow: none;
// Lists
@ -152,7 +161,7 @@ $list-item-bg: $card-background;
$list-item-hover-bg: $card-background-hover;
$list-item-shadow: $card-shadow;
$empty-list-cta-bg: #202226;
$empty-list-cta-bg: #22252b;
// Scrollbars
$scrollbarBackground: #404357;
@ -161,11 +170,10 @@ $scrollbarBorder: black;
// Tables
// -------------------------
$table-bg-accent: #191b1e; // for striping
$table-border: $dark-6; // table and cell border
$table-bg-odd: $dark-3;
$table-bg-hover: $dark-6;
$table-bg-accent: #22252b;
$table-border: rgba(218,224,254,0.15);
$table-bg-odd: rgb(28, 31, 35);
$table-bg-hover: rgb(35, 38, 42);
// Buttons
// -------------------------
@ -205,12 +213,12 @@ $input-bg: $input-black;
$input-bg-disabled: $dark-6;
$input-color: #c7d0d9;
$input-border-color: #2c3235;
$input-border-color: rgba(218,224,254,0.15);
$input-box-shadow: none;
$input-border-focus: #5794f2;
$input-box-shadow-focus: $blue-light !default;
$input-color-placeholder: #464c54;
$input-label-bg: #202226;
$input-color-placeholder: rgba(255, 255, 255, 0.35);
$input-label-bg: #22252b;
$input-color-select-arrow: $white;
// Search
@ -223,10 +231,10 @@ $typeahead-selected-color: $yellow;
// Dropdowns
// -------------------------
$dropdownBackground: $panel-bg;
$dropdownBorder: #202226;
$dropdownDividerTop: transparent;
$dropdownDividerBottom: #2c3235;
$dropdownBackground: #22252b;
$dropdownBorder: #181b1f;
$dropdownDividerTop: rgba(218,224,254,0.06);
$dropdownDividerBottom: rgba(218,224,254,0.06);
$dropdownLinkColor: $link-color;
$dropdownLinkColorHover: $white;
@ -247,24 +255,21 @@ $navbarBorder: 1px solid $dark-6;
$side-menu-bg: $panel-bg;
$side-menu-bg-mobile: $panel-bg;
$side-menu-border: none;
$side-menu-item-hover-bg: #202226;
$side-menu-item-hover-bg: #22252b;
$side-menu-shadow: 0 0 20px black;
$side-menu-icon-color: #9fa7b3;
$side-menu-header-color: #c7d0d9;
$side-menu-header-color: rgba(255, 255, 255, 0.75);
// Menu dropdowns
// -------------------------
$menu-dropdown-bg: #141619;
$menu-dropdown-hover-bg: #202226;
$menu-dropdown-shadow: 5px 5px 20px -5px $black;
$menu-dropdown-bg: #22252b;
$menu-dropdown-hover-bg: rgba(255, 255, 255, 0.08);
$menu-dropdown-shadow: 0px 2px 4px -1px rgba(0,0,0,0.5),0px 4px 5px 0px rgba(0,0,0,0.4),0px 1px 10px 0px rgba(0,0,0,0.3);
// Tabs
// -------------------------
$tab-border-color: $dark-9;
// Toolbar
$toolbar-bg: $input-black;
// Form states and alerts
// -------------------------
$warning-text-color: $warn;
@ -278,22 +283,21 @@ $alert-info-bg: linear-gradient(100deg, $blue-base, $blue-shade);
// Tooltips and popovers
// -------------------------
$tooltipColor: $text-color;
$tooltipArrowWidth: 5px;
$tooltipLinkColor: $link-color;
$tooltipShadow: 0 0 10px black;
$graph-tooltip-bg: $dark-1;
$tooltipBackground: $gray15;
$tooltipColor: $text-color;
$tooltipArrowColor: $tooltipBackground;
$tooltipBackgroundError: $brand-danger;
$tooltipBackground: #22252b;
$tooltipColor: rgba(255, 255, 255, 0.75);
$tooltipArrowColor: #22252b;
$tooltipBackgroundError: #D10E5C;
$tooltipShadow: 0px 3px 1px -2px rgba(0,0,0,0.5),0px 2px 2px 0px rgba(0,0,0,0.4),0px 1px 5px 0px rgba(0,0,0,0.3);
$popover-bg: $dark-2;
$popover-color: $text-color;
$popover-border-color: $dark-9;
$popover-header-bg: $dark-9;
$popover-shadow: 0 0 20px black;
$popover-bg: #22252b;
$popover-color: rgba(255, 255, 255, 0.75);
$popover-border-color: rgba(218,224,254,0.15);
$popover-header-bg: #22252b;
$popover-shadow: 0px 5px 5px -3px rgba(0,0,0,0.5),0px 8px 10px 1px rgba(0,0,0,0.4),0px 3px 14px 2px rgba(0,0,0,0.3);
$popover-help-bg: $tooltipBackground;
$popover-help-color: $text-color;
@ -328,14 +332,14 @@ $json-explorer-url-color: #027bff;
// Changelog and diff
// -------------------------
$diff-label-bg: #2c3235;
$diff-label-bg: rgba(255, 255, 255, 0.08);
$diff-label-fg: $white;
$diff-group-bg: #202226;
$diff-group-bg: #22252b;
$diff-arrow-color: $white;
$diff-json-bg: #202226;
$diff-json-fg: #c7d0d9;
$diff-json-bg: #22252b;
$diff-json-fg: rgba(255, 255, 255, 0.75);
$diff-json-added: $blue-shade;
$diff-json-deleted: $red-shade;
@ -379,9 +383,6 @@ $panel-editor-tabs-line-color: #e3e3e3;
$panel-editor-viz-item-bg-hover: darken($blue-base, 46%);
$panel-options-group-border: none;
$panel-options-group-header-bg: #202226;
$panel-grid-placeholder-bg: darken(#1f60c4, 30%);
$panel-grid-placeholder-shadow: 0 0 4px #3274d9;

View File

@ -53,6 +53,15 @@ $gray-7: #f7f8fa;
$white: #ffffff;
$layer0: #F4F5F5;
$layer1: #fff;
$layer2: #F7F7F8;
$divider: rgba(0, 2, 78, 0.07);
$border0: #fff;
$border1: rgba(0, 2, 78, 0.20);
// Accent colors
// -------------------------
$blue: #33a2e5;
@ -80,9 +89,9 @@ $critical: #c4162a;
// Scaffolding
// -------------------------
$body-bg: #ffffff;
$page-bg: #ffffff;
$dashboard-bg: #f7f8fa;
$body-bg: #fff;
$page-bg: #fff;
$dashboard-bg: #F4F5F5;
$text-color: #464c54;
$text-color-strong: #202226;
@ -115,29 +124,30 @@ $hr-border-color: $gray-4 !default;
// Panel
// -------------------------
$panel-bg: #ffffff;
$panel-border: 1px solid #dce1e6;
$panel-header-hover-bg: #f1f5f9;
$panel-corner: $gray-4;
$panel-bg: #fff;
$panel-border: #fff;
$panel-header-hover-bg: rgba(0, 0, 0, 0.04);
$panel-box-shadow: 0px 1px 1px -1px rgba(0,0,0,0.2),0px 0px 0px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12);
$panel-corner: $panel-bg;
// Page header
$page-header-bg: #f1f5f9;
$page-header-bg: #F7F7F8;
$page-header-shadow: inset 0px -3px 10px $gray-6;
$page-header-border-color: #dce1e6;
$page-header-border-color: #fff;
$divider-border-color: $gray-2;
// Graphite Target Editor
$tight-form-func-bg: #f1f5f9;
$tight-form-func-highlight-bg: #eaf0f6;
$tight-form-func-bg: #F7F7F8;
$tight-form-func-highlight-bg: #f2f2f3;
$modal-backdrop-bg: #ffffff;
$modal-backdrop-bg: #fff;
$code-tag-bg: $gray-6;
$code-tag-border: $gray-4;
// cards
$card-background: #f1f5f9;
$card-background-hover: #eaf0f6;
$card-background: #F7F7F8;
$card-background-hover: #F7F7F8;
$card-shadow: none;
// Lists
@ -154,11 +164,10 @@ $scrollbarBorder: $gray-7;
// Tables
// -------------------------
$table-bg-accent: #fafafa;
$table-border: $gray-3; // table and cell border
$table-bg-odd: $gray-6;
$table-bg-hover: $gray-5;
$table-bg-accent: #F7F7F8;
$table-border: rgba(0, 2, 78, 0.20);
$table-bg-odd: rgb(249, 249, 249);
$table-bg-hover: rgb(242, 242, 242);
// Buttons
// -------------------------
@ -203,7 +212,7 @@ $input-box-shadow: none;
$input-border-focus: #5794f2;
$input-box-shadow-focus: #5794f2;
$input-color-placeholder: #9fa7b3;
$input-label-bg: #f1f5f9;
$input-label-bg: #F7F7F8;
$input-color-select-arrow: #7b8087;
// search
@ -216,10 +225,10 @@ $typeahead-selected-color: $yellow;
// Dropdowns
// -------------------------
$dropdownBackground: $white;
$dropdownBorder: $gray-4;
$dropdownDividerTop: $gray-6;
$dropdownDividerBottom: $gray-4;
$dropdownBackground: #F7F7F8;
$dropdownBorder: #fff;
$dropdownDividerTop: rgba(0, 2, 78, 0.07);
$dropdownDividerBottom: rgba(0, 2, 78, 0.07);
$dropdownLinkColor: $dark-2;
$dropdownLinkColorHover: $link-color;
@ -249,17 +258,14 @@ $side-menu-header-color: #e9edf2;
// Menu dropdowns
// -------------------------
$menu-dropdown-bg: $panel-bg;
$menu-dropdown-hover-bg: $gray-6;
$menu-dropdown-shadow: 5px 5px 10px -5px $gray-1;
$menu-dropdown-bg: #F7F7F8;
$menu-dropdown-hover-bg: rgba(0, 0, 0, 0.04);
$menu-dropdown-shadow: 0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12);
// Tabs
// -------------------------
$tab-border-color: $gray-5;
// Toolbar
$toolbar-bg: white;
// Form states and alerts
// -------------------------
$warning-text-color: lighten($orange, 10%);
@ -272,27 +278,28 @@ $alert-warning-bg: linear-gradient(90deg, $red-base, $red-shade);
$alert-info-bg: linear-gradient(100deg, $blue-base, $blue-shade);
// Tooltips and popovers
$tooltipBackground: $gray-1;
$tooltipColor: $gray-7;
$tooltipArrowColor: $tooltipBackground; // Used by Angular tooltip
$tooltipBackgroundError: $brand-danger;
$tooltipShadow: 0 0 5px $gray60;
$tooltipBackground: #F7F7F8;
$tooltipColor: rgba(0, 0, 0, 0.87);
$tooltipArrowColor: #F7F7F8;
$tooltipBackgroundError: #E0226E;
$tooltipShadow: 0px 2px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12);
$popover-bg: #F7F7F8;
$popover-color: rgba(0, 0, 0, 0.87);
$popover-border-color: rgba(0, 2, 78, 0.20);
$popover-header-bg: #F7F7F8;
$popover-shadow: 0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12);
$graph-tooltip-bg: $gray-5;
$tooltipArrowWidth: 5px;
$tooltipLinkColor: lighten($tooltipColor, 5%);
$popover-bg: $page-bg;
$popover-color: $text-color;
$popover-border-color: $gray-5;
$popover-header-bg: $gray-5;
$popover-shadow: 0 0 20px $white;
$popover-error-bg: $btn-danger-bg;
$popover-help-bg: $tooltipBackground;
$popover-help-color: $tooltipColor;
$popover-code-bg: #ffffff;
$popover-code-bg: #fff;
$popover-code-boxshadow: 0 0 5px $gray60;
// images
@ -321,13 +328,13 @@ $json-explorer-url-color: $blue-base;
// Changelog and diff
// -------------------------
$diff-label-bg: #dce1e6;
$diff-label-bg: rgba(0, 0, 0, 0.04);
$diff-label-fg: $gray-2;
$diff-arrow-color: $dark-2;
$diff-group-bg: #f1f5f9;
$diff-group-bg: #F7F7F8;
$diff-json-bg: #f1f5f9;
$diff-json-bg: #F7F7F8;
$diff-json-fg: #464c54;
$diff-json-added: $blue-shade;
@ -372,9 +379,6 @@ $panel-editor-tabs-line-color: $dark-2;
$panel-editor-viz-item-bg-hover: lighten($blue-base, 45%);
$panel-options-group-border: none;
$panel-options-group-header-bg: $gray-5;
$panel-grid-placeholder-bg: lighten(#5794f2, 30%);
$panel-grid-placeholder-shadow: 0 0 4px #5794f2;

View File

@ -30,7 +30,7 @@
.dashboard-settings__aside {
padding: 32px 0 0 32px;
background: lightOrDark($gray95, $gray15);
background: $dashboard-bg;
display: flex;
flex-direction: column;
}

View File

@ -117,7 +117,6 @@
border-left: 2px solid transparent;
&:hover {
@include left-brand-border-gradient();
color: $link-hover-color;
background: $menu-dropdown-hover-bg !important;
}
@ -326,7 +325,6 @@
}
&:hover {
@include left-brand-border-gradient();
color: $link-hover-color;
background: $input-label-bg;
}

View File

@ -29,7 +29,7 @@
/* Used by old angular panels */
.panel-options-group {
border-bottom: $panel-border;
border-bottom: 1px solid $divider;
}
.panel-options-group__header {

View File

@ -74,10 +74,12 @@ div.flot-text {
display: flex;
flex-direction: column;
flex: 1 1 0;
box-shadow: $panel-box-shadow;
&--transparent {
background-color: transparent;
border: 1px solid transparent;
box-shadow: none;
}
&:hover {