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 <ashley.harrison@grafana.com>

* prettier

Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
pull/54950/head^2
Torkel Ödegaard 3 years ago committed by GitHub
parent 61c50ca1aa
commit c9b5acfefc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      contribute/style-guides/frontend.md
  2. 91
      contribute/style-guides/styling.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

@ -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 = () => (
<div
className={css`
background: red;
`}
>
As red as you can get
</div>
);
```
### 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<FooProps> = () => {
const styles = useStyles(getStyles);
const styles = useStyles2(getStyles);
// Use styles with classNames
return <div className={styles}>...</div>;
};
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<ComponentAProps> = ({ isActive }) => {
const theme = useTheme();
const styles = getStyles(theme, isActive);
const styles = useStyles2(theme);
return (
<div className={styles.wrapper}>
<div className={cx(styles.wrapper, isActive && styles.active)}>
As red as you can get
<i className={styles.icon} />
</div>
@ -76,42 +61,20 @@ const ComponentA: React.FC<ComponentAProps> = ({ 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 <div className={finalClassName}>As red as you can ge</div>;
}
```

Loading…
Cancel
Save