Skip to content

Commit a3d07c3

Browse files
committed
docs: move kibana and emotion FAQ to docs
1 parent 0596135 commit a3d07c3

File tree

4 files changed

+750
-0
lines changed

4 files changed

+750
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
---
2+
sidebar_label: Emotion
3+
---
4+
5+
# Styling apps with Emotion
6+
7+
```mdx-code-block
8+
import { EuiCode } from '@elastic/eui';
9+
```
10+
11+
[Emotion](https://emotion.sh/) is the underlying CSS-in-JS library used by EUI.
12+
It helps us manage CSS styles at scale injecting precisely what's needed
13+
to render visible components, _fast_.
14+
For best compatibility, we highly recommend all apps using EUI to implement
15+
Emotion as their primary styling method.
16+
17+
## What's Emotion and CSS-in-JS?
18+
19+
CSS-in-JS is a concept of writing styles directly in JS/TS files.
20+
While this may sound strange at first, it comes with many advantages compared
21+
to traditional CSS or SASS/LESS.
22+
23+
It brings the plain old CSS syntax you already know to the JavaScript world,
24+
so that your style definitions reference React components directly
25+
and predictably. No more class name guesswork, selector specificity issues
26+
or loading unnecessarily large stylesheets on each page load.
27+
28+
Emotion can compose and optimize styles, generate source maps and labels
29+
for easy debugging, and includes powerful testing utilities enabling assertions
30+
on real stylesheets and CSS properties.
31+
32+
<Demo isSourceOpen>
33+
```tsx
34+
import { css } from '@emotion/react';
35+
36+
// Declaring styles in a template literal is just like writing plain CSS
37+
const rainbowStyles = css`
38+
padding: .25rem;
39+
border-radius: .5rem;
40+
background: linear-gradient(90deg in hsl longer hue, red, red);
41+
/* Edit me and try this out! */
42+
/* filter: invert() */
43+
`;
44+
45+
export default <div css={rainbowStyles} />;
46+
```
47+
</Demo>
48+
49+
We highly encourage reading [Emotion docs](https://emotion.sh/docs/introduction)
50+
to better understand its underlying concepts.
51+
52+
## Writing styles
53+
54+
We recommend writing styles using the template literal notation
55+
(e.g., <EuiCode language="tsx">css\`color: red\`</EuiCode>), also called
56+
_string styles_. It makes writing styles very similar to the native CSS styling
57+
experience and allows seamless usage of pseudo classes like `:hover`
58+
or `::before`.
59+
60+
You can pass any regular CSS styles to the `css` template literal. The styles
61+
are processed by Emotion using [Stylis](https://github.com/thysultan/stylis)
62+
which can be configured to run plugins like vendor prefixing. By default,
63+
EUI applies CSS property prefixes targeting the latest evergreen browsers,
64+
following our [supported browsers matrix](https://www.elastic.co/support/matrix#matrix_browsers).
65+
66+
## Frequently Asked Questions
67+
68+
### What's the difference between the `css` imported from `@emotion/react` and `@emotion/css`?
69+
70+
[`@emotion/css`](https://emotion.sh/docs/@emotion/css) is the vanilla JS
71+
version of Emotion. It does not require any babel setup. It generates a `css-`
72+
prefixed className with the attached styles, which can be applied directly
73+
to vanilla JS DOM nodes or passed to a React `className={}` prop, e.g.
74+
75+
```tsx
76+
import { css } from '@emotion/css';
77+
const styles = css`
78+
color: red;
79+
`;
80+
<EuiComponent className={styles} />
81+
```
82+
83+
[`@emotion/react`](https://emotion.sh/docs/@emotion/react) is mostly
84+
syntactical sugar on top of the vanilla JS library. It allows usage
85+
of the `css` prop, which handles setting the generated CSS onto the underlying
86+
component's `className`, and automatically concatenates any other `css` styles
87+
passed onto the component together into a single ruleset for you. Example:
88+
89+
```tsx
90+
import { css } from '@emotion/react';
91+
const styles = css`
92+
color: red;
93+
`;
94+
<EuiComponent css={styles} />
95+
```
96+
97+
Please note that `@emotion/react` usage requires a
98+
[babel preset](https://www.npmjs.com/package/@emotion/babel-preset-css-prop)
99+
setup, and that Kibana plugins already set up to use `styled-components` cannot
100+
use both `styled-components` and `@emotion/react` at the same time.
101+
102+
#### When should I use one vs the other?
103+
104+
In general, when working directly in React/JSX, we recommend using
105+
`@emotion/react` for the nicer `css` prop syntactical sugar.
106+
107+
For consistency, we recommend using `@emotion/css` only when necessary.
108+
Examples of necessary (but hopefully rare) use-cases:
109+
- When styling raw JS DOM nodes
110+
- If your Kibana plugin is set up with `styled-components`, it will not support `@emotion/react` and you must use `@emotion/css` instead
111+
- If, for some reason, you absolutely do not want your styles to be automatically concatenated with other Emotion styles into a single selector, and want it to remain its own separate className/selector
112+
113+
### Can I use both `styled-components` and `@emotion/react` at the same time?
114+
115+
No. If your Kibana plugin uses babel to compile `styled-components` (please see this file/regex to check if your plugin is listed: https://github.com/elastic/kibana/blob/main/packages/kbn-babel-preset/styled_components_files.js), you cannot use `@emotion/react`.
116+
117+
`styled-components` and `@emotion/react` are incompatible and Kibana can't use the babel plugins for both on the same code. While Kibana will not actively throw if you try to do so, and may actually attempt to (**very** inconsistently) render some Emotion styles, this is actually a bug on Emotion's end - they drop some validation in `NODE_ENV=production` which allows their styles to sometimes be applied even when they're not supposed to. You will still see missing CSS, however, and you should be careful not to use both. The giveaway is if you see `Styled` in the classNames of your component DOM.
118+
119+
If you still wish to use Emotion while your plugin is setup for `styled-components`, all is not lost - you can use vanilla JS `@emotion/css` passed to the `className` prop in the interim.
120+
121+
#### Should I migrate my plugin away from `styled-components` to Emotion?
122+
123+
Yes, teams should begin migrating. While we don't yet have a set target date for moving entirely away from styled-components in Kibana, we expect to share one soon.
124+
125+
Our goal is to standardize on Emotion as our CSS-in-JS solution in Kibana. This will ensure consistency, easier support, and a unified theming system across the platform.
126+
127+
Here are a few key points to consider:
128+
129+
- The EUI team is more able to help assist with or debug styling issues in Emotion over styled-components
130+
- EUI exports Emotion style utilities that we do not have available for styled-components
131+
- EUI has already set up cache providers for Emotion in, which help control where styles render on the page & can determine specificity/order, that we do not have set up for styled-components
132+
133+
As a simple first step in this transition, consider using [@emotion/styled](https://emotion.sh/docs/styled). This allows you to keep the familiar styled syntax while aligning with the Emotion ecosystem
134+
135+
We've also found [this guide](https://simonhartcher.com/migrating-from-styled-components-to-emotion) to be a useful reference for migration.
136+
137+
### Theming and Emotion's `css` prop
138+
139+
Emotion's `css` prop allows consumers to [receive the EUI theme](https://emotion.sh/docs/theming#css-prop) from a callback within the prop:
140+
141+
```tsx
142+
<SomeComponent
143+
css={({ euiTheme }) => ({
144+
color: euiTheme.colors.primaryText,
145+
padding: euiTheme.size.l,
146+
})}
147+
/>
148+
```
149+
150+
This allows you to skip calling `useEuiTheme()` and is a nice syntactical sugar shortcut. That being said, there **are** caveats to its usage:
151+
152+
#### Typing
153+
154+
By default, Emotion's args for this API are untyped. You must [define a theme](https://emotion.sh/docs/typescript#define-a-theme) in your own `emotion.d.ts` file for the above callback usage to be properly typed. You can simply extend EUI's theme like so:
155+
156+
```ts
157+
import '@emotion/react';
158+
import type { UseEuiTheme } from '@elastic/eui';
159+
160+
// @see https://emotion.sh/docs/typescript#define-a-theme
161+
declare module '@emotion/react' {
162+
export interface Theme extends UseEuiTheme {}
163+
}
164+
```
165+
166+
You will then need to import this file into your `tsconfig.json`. See the [osquery plugin](https://github.com/elastic/kibana/blob/main/x-pack/plugins/osquery/tsconfig.json#L17-L18) for an example of their tsconfig setup.
167+
168+
#### Performance
169+
170+
Please note that the above callback syntax **does** come with performance implications, so if a high number of renders is an issue with the component you're styling, we recommend either defining your style callback statically outside the render cycle, or using `useCallback` to memoize your style fn. For example:
171+
172+
```tsx
173+
const YourStyles = ({ euiTheme }: UseEuiTheme) => ({
174+
color: euiTheme.colors.primary,
175+
padding: euiTheme.size.l,
176+
});
177+
178+
export const YourComponent = () => (
179+
(<div css={YourStyles} />
180+
);
181+
```
182+

0 commit comments

Comments
 (0)