From c9b5acfefc47d6c0deef1d7a5f2477e64ef0f42f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 23 Sep 2022 08:22:16 +0200 Subject: [PATCH] Frontend: Update frontend styleguide emotion example (#55608) * Frontend: Update frontend styleguide emotion example * Update styling guide * Fixes * Add back link to cx * prettier * Update contribute/style-guides/frontend.md Co-authored-by: Ashley Harrison * prettier Co-authored-by: Ashley Harrison --- contribute/style-guides/frontend.md | 11 +++- contribute/style-guides/styling.md | 91 +++++++++-------------------- 2 files changed, 35 insertions(+), 67 deletions(-) diff --git a/contribute/style-guides/frontend.md b/contribute/style-guides/frontend.md index c4691401ad7..dc0fc6e4427 100644 --- a/contribute/style-guides/frontend.md +++ b/contribute/style-guides/frontend.md @@ -166,17 +166,22 @@ interface ModalState { ##### Emotion class names ```typescript -const getStyles = = () => ({ +const getStyles = (theme: GrafanaTheme2) => ({ // bad ElementWrapper: css`...`, // bad - ["element-wrapper"]: css`...`, + ['element-wrapper']: css`...`, // good - elementWrapper: css`...`, + elementWrapper: css({ + padding: theme.spacing(1, 2), + background: theme.colors.background.secondary, + }), }); ``` +Use hook useStyles2(getStyles) to memoize the styles generation and try to avoid passing props to the the getStyles function and instead compose classes using emotion cx function. + #### Use `ALL_CAPS` for constants. ```typescript diff --git a/contribute/style-guides/styling.md b/contribute/style-guides/styling.md index 550f5d3b69a..e6c9ab63a57 100644 --- a/contribute/style-guides/styling.md +++ b/contribute/style-guides/styling.md @@ -4,26 +4,9 @@ ## Usage -### Basic styling - For styling components, use [Emotion's `css` function](https://emotion.sh/docs/emotion#css). -```tsx -import React from 'react'; -import { css } from '@emotion/css'; - -const ComponentA = () => ( -
- As red as you can get -
-); -``` - -### Styling with theme +### Basic styling To access the theme in your styles, use the `useStyles` hook. It provides basic memoization and access to the theme object. @@ -31,33 +14,35 @@ To access the theme in your styles, use the `useStyles` hook. It provides basic ```tsx import React, { FC } from 'react'; -import { GrafanaTheme } from '@grafana/data'; -import { useStyles } from '@grafana/ui'; +import { GrafanaTheme2 } from '@grafana/data'; +import { useStyles2 } from '@grafana/ui'; import { css } from '@emotion/css'; const Foo: FC = () => { - const styles = useStyles(getStyles); + const styles = useStyles2(getStyles); // Use styles with classNames return
...
; }; -const getStyles = (theme: GrafanaTheme) => css` - padding: ${theme.spacing.md}; -`; +const getStyles = (theme: GrafanaTheme2) => + css({ + padding: theme.spacing(1, 2), // will result in 8px 16px padding + }); ``` ### Styling complex components -In more complex cases, especially when you need to style multiple DOM elements in one component, or when using styles that depend on properties and/or state, you should create a helper function that returns an object of styles. This function should also be wrapped in the `stylesFactory` helper function, which will provide basic memoization. +In more complex cases, especially when you need to style multiple DOM elements in one component, or when using styles that depend on properties and/or state you +can have your getStyles function return an object with many class names and use [Emotion's `cx` function](https://emotion.sh/docs/emotion#cx) to compose them. Let's say you need to style a component that has a different background depending on the `isActive` property : ```tsx import React from 'react'; -import { css } from '@emotion/css'; -import { GrafanaTheme } from '@grafana/data'; -import { selectThemeVariant, stylesFactory, useTheme } from '@grafana/ui'; +import { css, cx } from '@emotion/css'; +import { GrafanaTheme2 } from '@grafana/data'; +import { useStyles2 } from '@grafana/ui'; interface ComponentAProps { isActive: boolean; @@ -65,10 +50,10 @@ interface ComponentAProps { const ComponentA: React.FC = ({ isActive }) => { const theme = useTheme(); - const styles = getStyles(theme, isActive); + const styles = useStyles2(theme); return ( -
+
As red as you can get
@@ -76,42 +61,20 @@ const ComponentA: React.FC = ({ isActive }) => { }; // Mind, that you can pass multiple arguments, theme included -const getStyles = stylesFactory((theme: GrafanaTheme, isActive: boolean) => { - const backgroundColor = isActive ? theme.colors.red : theme.colors.blue; - +const getStyles = (theme: GrafanaTheme2) => { return { - wrapper: css` - background: ${backgroundColor}; - `, - icon: css` - font-size: ${theme.typography.size.sm}; - `, + wrapper: css({ + background: theme.colors.background.secondary; + }), + active: css({ + background: theme.colors.primary.main, + text: theme.colors.primary.contrastText, + }, + icon: css({ + fontSize: theme.typography.bodySmall.fontSize; + }) }; -}); +}; ``` For more information about themes at Grafana please see the [themes guide](./themes.md). - -### Composing class names - -For class composition, use [Emotion's `cx` function](https://emotion.sh/docs/emotion#cx). - -```tsx -import React from 'react'; -import { css, cx } from '@emotion/css'; - -interface Props { - className?: string; -} - -function ComponentA({ className }: Props) { - const finalClassName = cx( - className, - css` - background: red; - ` - ); - - return
As red as you can ge
; -} -```