mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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>
This commit is contained in:
@@ -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>;
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user