mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Theme: V8 Theme updates (#33050)
* GraphNG: Use new theme props * Minor fix to letterspacing in button * Minor tweaks * Updated * Revert to roboto * Added concept of a dark or white base * Style updates * Sass * Updated light text blue * updates * reverting button group design * Fixed tests * updates * Updated tests
This commit is contained in:
@@ -34,7 +34,7 @@ export const colors = {
|
||||
lightBorder1: '#E4E7E7',
|
||||
|
||||
blueDarkMain: '#4165F5',
|
||||
blueDarkText: '#33a2e5', // '#5790FF',
|
||||
blueDarkText: '#58a6ff', //'#33a2e5', // '#5790FF',
|
||||
redDarkMain: '#D10E5C',
|
||||
redDarkText: '#FF5286',
|
||||
greenDarkMain: '#1A7F4B',
|
||||
@@ -43,7 +43,7 @@ export const colors = {
|
||||
orangeDarkText: '#F8D06B',
|
||||
|
||||
blueLightMain: '#3871DC',
|
||||
blueLightText: '#1F62E0',
|
||||
blueLightText: '#0465d7', // '#1F62E0',
|
||||
redLightMain: '#E0226E',
|
||||
redLightText: '#CF0E5B',
|
||||
greenLightMain: '#1A7F4B',
|
||||
|
||||
@@ -79,10 +79,12 @@ export type ThemePaletteInput = DeepPartial<ThemePaletteBase<ThemePaletteColor>>
|
||||
class DarkPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
mode: ThemePaletteMode = 'dark';
|
||||
|
||||
whiteBase = '201, 209, 217';
|
||||
|
||||
text = {
|
||||
primary: 'rgba(255, 255, 255, 0.77)',
|
||||
secondary: 'rgba(255, 255, 255, 0.50)',
|
||||
disabled: 'rgba(255, 255, 255, 0.35)',
|
||||
primary: `rgb(${this.whiteBase})`,
|
||||
secondary: `rgba(${this.whiteBase}, 0.65)`,
|
||||
disabled: `rgba(${this.whiteBase}, 0.40)`,
|
||||
link: colors.blueDarkText,
|
||||
maxContrast: colors.white,
|
||||
};
|
||||
@@ -94,10 +96,10 @@ class DarkPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
};
|
||||
|
||||
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)',
|
||||
main: `rgba(${this.whiteBase}, 0.1)`,
|
||||
shade: `rgba(${this.whiteBase}, 0.15)`,
|
||||
text: `rgba(${this.whiteBase}, 0.13)`,
|
||||
contrastText: `rgb(${this.whiteBase})`,
|
||||
};
|
||||
|
||||
info = this.primary;
|
||||
@@ -121,19 +123,19 @@ class DarkPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
layer1 = colors.gray10;
|
||||
layer2 = colors.gray15;
|
||||
|
||||
divider = 'rgba(218,224,254,0.06)';
|
||||
divider = `rgba(${this.whiteBase}, 0.10)`;
|
||||
|
||||
border0 = this.layer1;
|
||||
border1 = 'rgba(218,224,254,0.15)';
|
||||
border2 = 'rgba(218,224,254,0.20)';
|
||||
border1 = `rgba(${this.whiteBase}, 0.15)`;
|
||||
border2 = `rgba(${this.whiteBase}, 0.20)`;
|
||||
|
||||
action = {
|
||||
hover: 'rgba(255, 255, 255, 0.08)',
|
||||
selected: 'rgba(255, 255, 255, 0.12)',
|
||||
focus: 'rgba(255, 255, 255, 0.16)',
|
||||
hover: `rgba(${this.whiteBase}, 0.08)`,
|
||||
selected: `rgba(${this.whiteBase}, 0.12)`,
|
||||
focus: `rgba(${this.whiteBase}, 0.16)`,
|
||||
hoverOpacity: 0.08,
|
||||
disabledText: this.text.disabled,
|
||||
disabledBackground: 'rgba(255,255,255,0.07)',
|
||||
disabledBackground: `rgba(${this.whiteBase}, 0.07)`,
|
||||
disabledOpacity: 0.38,
|
||||
};
|
||||
|
||||
@@ -143,13 +145,15 @@ class DarkPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
};
|
||||
|
||||
contrastThreshold = 3;
|
||||
hoverFactor = 0.15;
|
||||
hoverFactor = 0.03;
|
||||
tonalOffset = 0.15;
|
||||
}
|
||||
|
||||
class LightPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
mode: ThemePaletteMode = 'light';
|
||||
|
||||
blackBase = '36, 41, 46';
|
||||
|
||||
primary = {
|
||||
main: colors.blueLightMain,
|
||||
border: colors.blueLightText,
|
||||
@@ -157,9 +161,9 @@ class LightPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
};
|
||||
|
||||
secondary = {
|
||||
main: 'rgba(0,0,0,0.11)',
|
||||
shade: 'rgba(0,0,0,0.16)',
|
||||
contrastText: 'rgba(0, 0, 0, 0.75)',
|
||||
main: `rgba(${this.blackBase}, 0.11)`,
|
||||
shade: `rgba(${this.blackBase}, 0.16)`,
|
||||
contrastText: `rgba(${this.blackBase}, 1)`,
|
||||
};
|
||||
|
||||
info = {
|
||||
@@ -184,9 +188,9 @@ class LightPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
};
|
||||
|
||||
text = {
|
||||
primary: 'rgba(0, 0, 0, 0.75)',
|
||||
secondary: 'rgba(0, 0, 0, 0.60)',
|
||||
disabled: 'rgba(0, 0, 0, 0.45)',
|
||||
primary: `rgba(${this.blackBase}, 1)`,
|
||||
secondary: `rgba(${this.blackBase}, 0.75)`,
|
||||
disabled: `rgba(${this.blackBase}, 0.50)`,
|
||||
link: this.primary.text,
|
||||
maxContrast: colors.black,
|
||||
};
|
||||
@@ -195,18 +199,18 @@ class LightPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
layer1 = colors.white;
|
||||
layer2 = colors.gray100;
|
||||
|
||||
divider = 'rgba(0, 2, 78, 0.07)';
|
||||
divider = `rgba(${this.blackBase}, 0.12)`;
|
||||
|
||||
border0 = this.layer1;
|
||||
border1 = 'rgba(0, 2, 78, 0.20)';
|
||||
border2 = 'rgba(0, 2, 78, 0.30)';
|
||||
border1 = `rgba(${this.blackBase}, 0.30)`;
|
||||
border2 = `rgba(${this.blackBase}, 0.40)`;
|
||||
|
||||
action = {
|
||||
hover: 'rgba(0, 0, 0, 0.04)',
|
||||
selected: 'rgba(0, 0, 0, 0.08)',
|
||||
hover: `rgba(${this.blackBase}, 0.04)`,
|
||||
selected: `rgba(${this.blackBase}, 0.08)`,
|
||||
hoverOpacity: 0.08,
|
||||
focus: 'rgba(0, 0, 0, 0.12)',
|
||||
disabledBackground: 'rgba(0,0,0,0.07)',
|
||||
focus: `rgba(${this.blackBase}, 0.12)`,
|
||||
disabledBackground: `rgba(${this.blackBase}, 0.07)`,
|
||||
disabledText: this.text.disabled,
|
||||
disabledOpacity: 0.38,
|
||||
};
|
||||
@@ -217,7 +221,7 @@ class LightPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {
|
||||
};
|
||||
|
||||
contrastThreshold = 3;
|
||||
hoverFactor = 0.15;
|
||||
hoverFactor = 0.03;
|
||||
tonalOffset = 0.2;
|
||||
}
|
||||
|
||||
@@ -240,7 +244,7 @@ export function createPalette(palette: ThemePaletteInput): ThemePalette {
|
||||
|
||||
function getContrastText(background: string) {
|
||||
const contrastText =
|
||||
getContrastRatio(background, dark.text.primary) >= contrastThreshold
|
||||
getContrastRatio(background, dark.text.maxContrast) >= contrastThreshold
|
||||
? dark.text.maxContrast
|
||||
: light.text.maxContrast;
|
||||
// todo, need color framework
|
||||
|
||||
@@ -63,7 +63,7 @@ export interface ThemeTypographyInput {
|
||||
htmlFontSize?: number;
|
||||
}
|
||||
|
||||
const defaultFontFamily = '"Inter", "Helvetica", "Arial", sans-serif';
|
||||
const defaultFontFamily = '"Roboto", "Helvetica", "Arial", sans-serif';
|
||||
const defaultFontFamilyMonospace = "'Roboto Mono', monospace";
|
||||
|
||||
export function createTypography(palette: ThemePalette, typographyInput: ThemeTypographyInput = {}): ThemeTypography {
|
||||
@@ -104,19 +104,19 @@ export function createTypography(palette: ThemePalette, typographyInput: ThemeTy
|
||||
fontWeight,
|
||||
fontSize: pxToRem(size),
|
||||
lineHeight,
|
||||
letterSpacing: `${letterSpacing}em`,
|
||||
...(fontFamily === defaultFontFamily ? { letterSpacing: `${round(letterSpacing / size)}em` } : {}),
|
||||
...casing,
|
||||
});
|
||||
|
||||
const variants = {
|
||||
h1: buildVariant(fontWeightMedium, 28, 1.2, -0.01),
|
||||
h2: buildVariant(fontWeightMedium, 24, 1.2, -0.01),
|
||||
h3: buildVariant(fontWeightMedium, 21, 1.3, -0.01),
|
||||
h4: buildVariant(fontWeightRegular, 18, 1.4, -0.005),
|
||||
h5: buildVariant(fontWeightRegular, 16, 1.334, -0.005),
|
||||
h6: buildVariant(fontWeightRegular, 14, 1.6, -0.005),
|
||||
body: buildVariant(fontWeightRegular, 14, 1.5, -0.005),
|
||||
bodySmall: buildVariant(fontWeightRegular, 12, 1.5, -0.005),
|
||||
h1: buildVariant(fontWeightLight, 28, 1.167, -0.25),
|
||||
h2: buildVariant(fontWeightLight, 24, 1.2, 0),
|
||||
h3: buildVariant(fontWeightRegular, 21, 1.167, 0),
|
||||
h4: buildVariant(fontWeightRegular, 18, 1.235, 0.25),
|
||||
h5: buildVariant(fontWeightRegular, 16, 1.334, 0),
|
||||
h6: buildVariant(fontWeightMedium, 14, 1.6, 0.15),
|
||||
body: buildVariant(fontWeightRegular, 14, 1.5, 0.15),
|
||||
bodySmall: buildVariant(fontWeightRegular, 12, 1.5, 0.15),
|
||||
};
|
||||
|
||||
const size = {
|
||||
@@ -141,3 +141,7 @@ export function createTypography(palette: ThemePalette, typographyInput: ThemeTy
|
||||
...variants,
|
||||
};
|
||||
}
|
||||
|
||||
function round(value: number) {
|
||||
return Math.round(value * 1e5) / 1e5;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ export const parameters = {
|
||||
dark: GrafanaDark,
|
||||
light: GrafanaLight,
|
||||
},
|
||||
layout: 'fullscreen',
|
||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||
options: {
|
||||
showPanel: true,
|
||||
|
||||
@@ -23,11 +23,11 @@ const createTheme = (theme: GrafanaTheme) => {
|
||||
fontCode: theme.v2.typography.fontFamilyMonospace,
|
||||
|
||||
// Text colors
|
||||
textColor: theme.v2.palette.text.primary,
|
||||
textColor: theme.v2.palette.primary.text,
|
||||
textInverseColor: theme.v2.palette.primary.contrastText,
|
||||
|
||||
// Toolbar default and active colors
|
||||
barTextColor: theme.v2.palette.primary.text,
|
||||
barTextColor: theme.v2.palette.text.primary,
|
||||
barSelectedColor: theme.v2.palette.emphasize(theme.v2.palette.primary.text),
|
||||
barBg: theme.v2.palette.layer1,
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`CustomScrollbar renders correctly 1`] = `
|
||||
<div
|
||||
className="css-1xduqpt"
|
||||
className="css-d4ozb2"
|
||||
style={
|
||||
Object {
|
||||
"height": "auto",
|
||||
|
||||
@@ -3,7 +3,6 @@ import { GrafanaTheme } from '@grafana/data';
|
||||
import { focusCss } from '../../themes/mixins';
|
||||
import { css as cssCore } from '@emotion/react';
|
||||
import { css } from '@emotion/css';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
export const getFocusStyle = (theme: GrafanaTheme) => css`
|
||||
&:focus {
|
||||
@@ -12,11 +11,11 @@ export const getFocusStyle = (theme: GrafanaTheme) => css`
|
||||
`;
|
||||
|
||||
export const getStyles = stylesFactory((theme: GrafanaTheme, isHorizontal: boolean) => {
|
||||
const { spacing, palette } = theme;
|
||||
const railColor = theme.isLight ? palette.gray5 : palette.dark6;
|
||||
const trackColor = theme.isLight ? palette.blue85 : palette.blue77;
|
||||
const handleColor = theme.isLight ? palette.blue85 : palette.blue80;
|
||||
const blueOpacity = tinycolor(handleColor).setAlpha(0.2).toString();
|
||||
const { spacing } = theme;
|
||||
const railColor = theme.v2.palette.border2;
|
||||
const trackColor = theme.v2.palette.primary.main;
|
||||
const handleColor = theme.v2.palette.primary.main;
|
||||
const blueOpacity = theme.v2.palette.primary.transparent;
|
||||
const hoverSyle = `box-shadow: 0px 0px 0px 6px ${blueOpacity}`;
|
||||
|
||||
return {
|
||||
@@ -37,6 +36,7 @@ export const getStyles = stylesFactory((theme: GrafanaTheme, isHorizontal: boole
|
||||
.rc-slider-handle {
|
||||
border: none;
|
||||
background-color: ${handleColor};
|
||||
box-shadow: ${theme.v2.shadows.z1};
|
||||
cursor: pointer;
|
||||
}
|
||||
.rc-slider-handle:hover,
|
||||
@@ -51,7 +51,6 @@ export const getStyles = stylesFactory((theme: GrafanaTheme, isHorizontal: boole
|
||||
}
|
||||
.rc-slider-rail {
|
||||
background-color: ${railColor};
|
||||
border: 1px solid ${railColor};
|
||||
cursor: pointer;
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -9,7 +9,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
label: counter;
|
||||
margin-left: ${theme.spacing.sm};
|
||||
border-radius: ${theme.spacing.lg};
|
||||
background-color: ${theme.colors.bg2};
|
||||
background-color: ${theme.v2.palette.action.hover};
|
||||
padding: ${theme.spacing.xxs} ${theme.spacing.sm};
|
||||
color: ${theme.colors.textWeak};
|
||||
font-weight: ${theme.typography.weight.semibold};
|
||||
|
||||
@@ -50,16 +50,14 @@ export class UPlotAxisBuilder extends PlotConfigBuilder<AxisProps, Axis> {
|
||||
theme,
|
||||
} = this.props;
|
||||
|
||||
let { typography } = theme;
|
||||
const font = `12px ${theme.v2.typography.fontFamily}`;
|
||||
|
||||
let font = `${typography.size.sm} ${typography.fontFamily.sansSerif}`;
|
||||
|
||||
const gridColor = theme.isDark ? theme.palette.gray25 : theme.palette.gray90;
|
||||
const gridColor = theme.v2.isDark ? 'rgba(240, 250, 255, 0.09)' : 'rgba(0, 10, 23, 0.09)';
|
||||
|
||||
let config: Axis = {
|
||||
scale: scaleKey,
|
||||
show,
|
||||
stroke: theme.colors.text,
|
||||
stroke: theme.v2.palette.text.primary,
|
||||
side: getUPlotSideFromAxis(placement),
|
||||
font,
|
||||
labelFont: font,
|
||||
|
||||
@@ -299,15 +299,15 @@ describe('UPlotConfigBuilder', () => {
|
||||
Object {
|
||||
"axes": Array [
|
||||
Object {
|
||||
"font": "12px 'Inter', 'Helvetica Neue', Arial, sans-serif",
|
||||
"font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
|
||||
"gap": 5,
|
||||
"grid": Object {
|
||||
"show": false,
|
||||
"stroke": "#2c3235",
|
||||
"stroke": "rgba(240, 250, 255, 0.09)",
|
||||
"width": 1,
|
||||
},
|
||||
"label": "test label",
|
||||
"labelFont": "12px 'Inter', 'Helvetica Neue', Arial, sans-serif",
|
||||
"labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
|
||||
"labelSize": 18,
|
||||
"scale": "scale-x",
|
||||
"show": true,
|
||||
@@ -315,10 +315,10 @@ describe('UPlotConfigBuilder', () => {
|
||||
"size": [Function],
|
||||
"space": [Function],
|
||||
"splits": undefined,
|
||||
"stroke": "rgba(255, 255, 255, 0.77)",
|
||||
"stroke": "rgb(201, 209, 217)",
|
||||
"ticks": Object {
|
||||
"show": true,
|
||||
"stroke": "#2c3235",
|
||||
"stroke": "rgba(240, 250, 255, 0.09)",
|
||||
"width": 1,
|
||||
},
|
||||
"timeZone": "browser",
|
||||
|
||||
@@ -51,6 +51,10 @@ export function getElementStyles(theme: GrafanaThemeV2) {
|
||||
margin: 0 0 ${theme.spacing(2)};
|
||||
}
|
||||
|
||||
button {
|
||||
letter-spacing: ${theme.typography.body.letterSpacing};
|
||||
}
|
||||
|
||||
// Ex: 14px base font * 85% = about 12px
|
||||
small {
|
||||
font-size: ${theme.typography.bodySmall.fontSize};
|
||||
|
||||
@@ -31,7 +31,7 @@ const theme: GrafanaThemeCommons = {
|
||||
name: 'Grafana Default',
|
||||
typography: {
|
||||
fontFamily: {
|
||||
sansSerif: "'Inter', 'Helvetica Neue', Arial, sans-serif",
|
||||
sansSerif: "'Roboto', 'Helvetica Neue', Arial, sans-serif",
|
||||
monospace: "'Roboto Mono', monospace",
|
||||
},
|
||||
size: {
|
||||
|
||||
@@ -21,7 +21,7 @@ export function getCanvasContext() {
|
||||
* @beta
|
||||
*/
|
||||
export function measureText(text: string, fontSize: number): TextMetrics {
|
||||
const fontStyle = `${fontSize}px 'Inter'`;
|
||||
const fontStyle = `${fontSize}px 'Roboto'`;
|
||||
const cacheKey = text + fontStyle;
|
||||
const fromCache = cache[cacheKey];
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import React from 'react';
|
||||
import { GlobalStyles } from '../../themes';
|
||||
import { GlobalStyles, useTheme } from '../../themes';
|
||||
import { RenderFunction } from '../../types';
|
||||
|
||||
const PaddedStory: React.FunctionComponent<{}> = ({ children }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '20px',
|
||||
display: 'flex',
|
||||
minHeight: '80vh',
|
||||
background: `${theme.v2.palette.layer1}`,
|
||||
}}
|
||||
>
|
||||
<GlobalStyles />
|
||||
|
||||
Reference in New Issue
Block a user