Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Theme: Updated font to Inter, updates typography, a start of moving legacy & global styles from sass to emotion #32988

Merged
merged 18 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/grafana-data/src/themes/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const colors = {
// Dashboard bg / layer 0 (light theme)
gray90: '#F4F5F5',
// Card bg / layer 1
gray100: '#F7F7F8',
gray100: '#F4F5F5',
// divider line
gray80: '#D0D1D3',
// from figma
Expand Down
14 changes: 6 additions & 8 deletions packages/grafana-data/src/themes/createPalette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ export interface ThemeHoverStrengh {}
export interface ThemePalette extends ThemePaletteBase<ThemePaletteColor> {
/** Returns a text color for the background */
getContrastText(background: string): string;
/* Return a hover color for any color */
getHoverColor(color: string, hoverFactor?: number): string;
/* Brighten or darken a color by specified factor (0-1) */
emphasize(color: string, amount?: number): string;
}

/** @internal */
Expand All @@ -81,7 +81,7 @@ class DarkPalette implements ThemePaletteBase<Partial<ThemePaletteColor>> {

text = {
primary: 'rgba(255, 255, 255, 0.77)',
secondary: 'rgba(255, 255, 255, 0.55)',
secondary: 'rgba(255, 255, 255, 0.50)',
disabled: 'rgba(255, 255, 255, 0.35)',
link: colors.blueDarkText,
maxContrast: colors.white,
Expand Down Expand Up @@ -247,10 +247,6 @@ export function createPalette(palette: ThemePaletteInput): ThemePalette {
return contrastText;
}

function getHoverColor(color: string, factorOverride?: number) {
return emphasize(color, factorOverride ?? hoverFactor);
}

const getRichColor = ({ color, name }: GetRichColorProps): ThemePaletteColor => {
color = { ...color, name };
if (!color.main) {
Expand Down Expand Up @@ -284,7 +280,9 @@ export function createPalette(palette: ThemePaletteInput): ThemePalette {
success: getRichColor({ color: success, name: 'success' }),
warning: getRichColor({ color: warning, name: 'warning' }),
getContrastText,
getHoverColor,
emphasize: (color: string, factor?: number) => {
return emphasize(color, factor ?? hoverFactor);
},
},
other
);
Expand Down
36 changes: 17 additions & 19 deletions packages/grafana-data/src/themes/createTypography.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ export interface ThemeTypography {
h6: ThemeTypographyVariant;

body: ThemeTypographyVariant;
bodySmall: ThemeTypographyVariant;

/** from legacy old theme */
/**
* @deprecated
* from legacy old theme
* */
size: {
base: string;
xs: string;
Expand Down Expand Up @@ -59,8 +63,8 @@ export interface ThemeTypographyInput {
htmlFontSize?: number;
}

const defaultFontFamily = '"Roboto", "Helvetica", "Arial", sans-serif';
const defaultFontFamilyMonospace = "Menlo, Monaco, Consolas, 'Courier New', monospace";
const defaultFontFamily = '"Inter", "Helvetica", "Arial", sans-serif';
const defaultFontFamilyMonospace = "'Roboto Mono', monospace";

export function createTypography(palette: ThemePalette, typographyInput: ThemeTypographyInput = {}): ThemeTypography {
const {
Expand All @@ -71,7 +75,7 @@ export function createTypography(palette: ThemePalette, typographyInput: ThemeTy
fontWeightLight = 300,
fontWeightRegular = 400,
fontWeightMedium = 500,
fontWeightBold = 700,
fontWeightBold = 500,
// Tell Grafana-UI what's the font-size on the html element.
// 16px is the default font-size used by browsers.
htmlFontSize = 14,
Expand Down Expand Up @@ -99,22 +103,20 @@ export function createTypography(palette: ThemePalette, typographyInput: ThemeTy
fontFamily,
fontWeight,
fontSize: pxToRem(size),
// Unitless following https://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/
lineHeight,
// The letter spacing was designed for the Roboto font-family. Using the same letter-spacing
// across font-families can cause issues with the kerning.
...(fontFamily === defaultFontFamily ? { letterSpacing: `${round(letterSpacing / size)}em` } : {}),
letterSpacing: `${letterSpacing}em`,
...casing,
});

const variants = {
h1: buildVariant(fontWeightLight, 28, 1.167, -1.5),
h2: buildVariant(fontWeightLight, 24, 1.2, -0.5),
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),
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),
};

const size = {
Expand All @@ -139,7 +141,3 @@ export function createTypography(palette: ThemePalette, typographyInput: ThemeTy
...variants,
};
}

function round(value: number) {
return Math.round(value * 1e5) / 1e5;
}
2 changes: 1 addition & 1 deletion packages/grafana-data/src/themes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export { ThemePalette } from './createPalette';
export { ThemeBreakpoints } from './breakpoints';
export { ThemeShadows } from './createShadows';
export { ThemeShape } from './createShape';
export { ThemeTypography } from './createTypography';
export { ThemeTypography, ThemeTypographyVariant } from './createTypography';
export { ThemeTransitions } from './createTransitions';
export { ThemeSpacing } from './createSpacing';
export { ThemeZIndices } from './zIndex';
Expand Down
3 changes: 2 additions & 1 deletion packages/grafana-ui/.storybook/storybookTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { create } from '@storybook/theming/create';
import lightTheme from '../src/themes/light';
import darkTheme from '../src/themes/dark';
import { GrafanaTheme } from '@grafana/data';
import '../src/components/Icon/iconBundle';

const createTheme = (theme: GrafanaTheme) => {
return create({
Expand All @@ -27,7 +28,7 @@ const createTheme = (theme: GrafanaTheme) => {

// Toolbar default and active colors
barTextColor: theme.v2.palette.primary.text,
barSelectedColor: theme.v2.palette.getHoverColor(theme.v2.palette.primary.text),
barSelectedColor: theme.v2.palette.emphasize(theme.v2.palette.primary.text),
barBg: theme.v2.palette.layer1,

// Form colors
Expand Down
1 change: 0 additions & 1 deletion packages/grafana-ui/src/components/BarGauge/BarGauge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,6 @@ export function getBasicAndGradientStyles(props: Props): BasicAndGradientStyles

// shift empty region back to fill gaps due to border radius
emptyBar.left = '-3px';
emptyBar.width = `${maxBarWidth - barWidth}px`;

if (isBasic) {
// Basic styles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ exports[`BarGauge Render with basic options should render 1`] = `
"flexGrow": 1,
"left": "-3px",
"position": "relative",
"width": "180px",
}
}
/>
Expand Down
2 changes: 1 addition & 1 deletion packages/grafana-ui/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const getContainerStyles = stylesFactory((theme: GrafanaTheme, disabled = false,

...(!disableHover && {
'&:hover': {
background: theme.v2.palette.getHoverColor(theme.v2.palette.layer2, 0.03),
background: theme.v2.palette.emphasize(theme.v2.palette.layer2, 0.03),
cursor: 'pointer',
zIndex: 1,
},
Expand Down
3 changes: 1 addition & 2 deletions packages/grafana-ui/src/components/Icon/Icon.story.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import React, { ChangeEvent, useState } from 'react';
import { css } from '@emotion/css';

import { Input, Field, Icon } from '@grafana/ui';
import { getAvailableIcons, IconName } from '../../types';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { useTheme } from '../../themes';
import mdx from './Icon.mdx';

export default {
title: 'Docs Overview/Icon',
title: 'General/Icon',
component: Icon,
decorators: [withCenteredStory],
parameters: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import React from 'react';
import { css } from '@emotion/css';
import { IconButton } from '@grafana/ui';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { useTheme } from '../../themes/ThemeContext';
import { GrafanaTheme } from '@grafana/data';
import { useTheme } from '../../themes';
import { IconSize, IconName } from '../../types';
import mdx from './IconButton.mdx';

Expand All @@ -19,57 +18,44 @@ export default {
};

export const Simple = () => {
const theme = useTheme();

return (
<div>
{renderScenario(
'dashboard',
theme,
['sm', 'md', 'lg', 'xl', 'xxl'],
['search', 'trash-alt', 'arrow-left', 'times']
)}
{renderScenario('panel', theme, ['sm', 'md', 'lg', 'xl', 'xxl'], ['search', 'trash-alt', 'arrow-left', 'times'])}
{renderScenario('header', theme, ['sm', 'md', 'lg', 'xl', 'xxl'], ['search', 'trash-alt', 'arrow-left', 'times'])}
<RenderScenario layer="layer0" />
<RenderScenario layer="layer1" />
<RenderScenario layer="layer2" />
</div>
);
};

function renderScenario(surface: string, theme: GrafanaTheme, sizes: IconSize[], icons: IconName[]) {
let bg = 'red';
interface ScenarioProps {
layer: 'layer0' | 'layer1' | 'layer2';
}

switch (surface) {
case 'dashboard':
bg = theme.colors.dashboardBg;
break;
case 'panel':
bg = theme.colors.bodyBg;
break;
case 'header': {
bg = theme.colors.pageHeaderBg;
}
}
const RenderScenario = ({ layer }: ScenarioProps) => {
const theme = useTheme();
const sizes: IconSize[] = ['sm', 'md', 'lg', 'xl', 'xxl'];
const icons: IconName[] = ['search', 'trash-alt', 'arrow-left', 'times'];

return (
<div
className={css`
padding: 30px;
background: ${bg};
background: ${theme.v2.palette[layer]};
button {
margin-right: 8px;
margin-left: 8px;
margin-bottom: 8px;
}
`}
>
<div>Surface: {surface}</div>
<div>{layer}</div>
{icons.map((icon) => {
return sizes.map((size) => (
<span key={icon + size}>
<IconButton name={icon} size={size} surface={surface as any} />
<IconButton name={icon} size={size} />
</span>
));
})}
</div>
);
}
};
30 changes: 24 additions & 6 deletions packages/grafana-ui/src/components/Tabs/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,16 @@ export const Tab = React.forwardRef<HTMLLIElement, TabProps>(
</>
);

const itemClass = cx(
tabsStyles.tabItem,
active ? tabsStyles.activeStyle : tabsStyles.notActive,
!href && tabsStyles.padding
);

return (
<li
{...otherProps}
className={cx(!href && tabsStyles.padding, tabsStyles.tabItem, active && tabsStyles.activeStyle)}
className={itemClass}
onClick={onChangeTab}
aria-label={otherProps['aria-label'] || selectors.components.Tab.title(label)}
ref={ref}
Expand All @@ -57,7 +63,6 @@ const getTabStyles = stylesFactory((theme: GrafanaTheme) => {
return {
tabItem: css`
list-style: none;
margin-right: ${theme.v2.spacing(2)};
position: relative;
display: block;
color: ${theme.v2.palette.text.secondary};
Expand All @@ -72,15 +77,28 @@ const getTabStyles = stylesFactory((theme: GrafanaTheme) => {
height: 100%;
color: ${theme.v2.palette.text.secondary};
}

`,
notActive: css`
a:hover,
&:hover,
&:focus {
color: ${theme.v2.palette.text.primary};

&::before {
display: block;
content: ' ';
position: absolute;
left: 0;
right: 0;
height: 4px;
border-radius: 2px;
bottom: 0px;
background: ${theme.v2.palette.action.hover};
}
}
`,
padding: css`
padding: 11px 15px 9px;
padding: ${theme.v2.spacing(1.5, 2, 1)};
`,
activeStyle: css`
label: activeTabStyle;
Expand All @@ -100,8 +118,8 @@ const getTabStyles = stylesFactory((theme: GrafanaTheme) => {
right: 0;
height: 4px;
border-radius: 2px;
bottom: 2px;
background-image: ${theme.v2.palette.gradients.brandHorizontal};
bottom: 0px;
background-image: ${theme.v2.palette.gradients.brandHorizontal} !important;
}
`,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { StoryExample } from '../../utils/storybook/StoryExample';
import { VerticalGroup } from '../Layout/Layout';
import { Typography } from './Typography';

export default {
title: 'General/Typography',
component: Typography,
parameters: {
docs: {},
},
};

export const Typopgraphy = () => {
return (
<VerticalGroup>
<StoryExample name="Native header elements (global styles)">
<h1>h1. Heading</h1>
<h2>h2. Heading</h2>
<h3>h3. Heading</h3>
<h4>h4. Heading</h4>
<h5>h5. Heading</h5>
<h6>h6. Heading</h6>
</StoryExample>
</VerticalGroup>
);
};
16 changes: 16 additions & 0 deletions packages/grafana-ui/src/components/Typography/Typography.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';

/** @internal */
export interface Props {
children: React.ReactNode;
}

/**
* @internal
* TODO implementation coming
**/
export const Typography = ({ children }: Props) => {
return <h1>{children}</h1>;
};

Typography.displayName = 'Typography';
12 changes: 12 additions & 0 deletions packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import { Global } from '@emotion/react';
import { useTheme } from '..';
import { getElementStyles } from './elements';

/** @internal */
export function GlobalStyles() {
const theme = useTheme();
const types = getElementStyles(theme.v2);

return <Global styles={[types]} />;
}
Loading