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

[Storybook] Add story code snippets #7716

Merged
merged 51 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
1e727f4
feat: add custom code-sippet addon panel
mgadewoll May 24, 2024
556e4de
refactor: renames prettier config file to js file for extension usage
mgadewoll May 24, 2024
3416c6d
feat: add and use jsxDecorator
mgadewoll May 24, 2024
60881c6
fix: prevent fewer hooks called error on euiTheme
mgadewoll May 24, 2024
0eca467
docs(storybook): updates stories to ensure code-snippet generation
mgadewoll May 24, 2024
8485fc3
docs(storybook): various story adjustments
mgadewoll May 24, 2024
47af532
docs(storybook): skip code snippet generation for components that hav…
mgadewoll May 24, 2024
ccc2f2d
refactor: update style object construction regex
mgadewoll May 24, 2024
87dc4b3
chore: update yarn lock
mgadewoll Jun 7, 2024
72e8139
build: update prettier types dependency to correct version
mgadewoll Jun 7, 2024
754d719
refactor: update to exclude empty object and array values from props
mgadewoll Jun 7, 2024
ce7a4ba
fix: ensure default tags with emotion css are output correctly
mgadewoll Jun 7, 2024
9af0693
refactor: rename emotion object data key
mgadewoll Jun 7, 2024
faa31d3
docs(storybook): revert custom opening handling for EuiheaderAlert fl…
mgadewoll Jun 12, 2024
135ddce
feat(code-snippet-addon): show/hide addon conditionally based on skip…
mgadewoll Jun 13, 2024
9e9d2e3
feat(code-snippet-addon): enable opening the addon panel based on lin…
mgadewoll Jun 13, 2024
b46d24b
refactor(code-snippet): move event setup to addon directory
mgadewoll Jun 13, 2024
35de340
refactor(code-snippet): remove obsolete double quote transform since …
mgadewoll Jun 13, 2024
416c4e1
docs: add addon README
mgadewoll Jun 13, 2024
ebfbf42
docs: update addon readme
mgadewoll Jun 13, 2024
a5d890b
chore(code-snippet): cleanup
mgadewoll Jun 17, 2024
d9eb542
chore(code-snippet): remove unused skip code
mgadewoll Jun 17, 2024
e24fb1d
docs: add documentation on manual code snippet
mgadewoll Jun 17, 2024
6b58f32
docs(code-snippet): update links
mgadewoll Jun 17, 2024
1f7eb3f
docs(code-snippet): update readme
mgadewoll Jun 19, 2024
c102bff
refactor: update .match usages
mgadewoll Jun 19, 2024
ed25571
move jsx constants and change them to be Sets
mgadewoll Jun 19, 2024
e052ae0
refactor: tighten types where possible
mgadewoll Jun 19, 2024
69a32d1
fix(code-snippet): fix isFragment type guards
mgadewoll Jun 19, 2024
014c2bd
docs(storybook): ensure EuiSpacer args are spread to component
mgadewoll Jun 19, 2024
de8fb1c
docs(storybook): skip snippet generation for EuiInnerText
mgadewoll Jun 19, 2024
b5cd7d0
feat(code-snippet): add support for snippet value overrides
mgadewoll Jun 19, 2024
78b55d5
chore: cleanup log
mgadewoll Jun 20, 2024
e9faa76
feat(code-snippet): add story element only filter functionality
mgadewoll Jun 20, 2024
d9a7c02
chore: cleanup
mgadewoll Jun 20, 2024
c8253d3
feat(code-snippet): support spread args for manual code snippets
mgadewoll Jun 24, 2024
18ca9a5
docs(storybook): enable code snippets for providers
mgadewoll Jun 24, 2024
ec9add9
feat(code-snippet): support removing default props
mgadewoll Jun 24, 2024
478b16a
docs(storybook): remove plugin controls from markdown stories
mgadewoll Jun 24, 2024
ec83ba7
docs: update code-snippet readme
mgadewoll Jun 24, 2024
ac3fcda
fix: determine defaultProps per node iteration instead of root only
mgadewoll Jun 24, 2024
cbec91f
fix: ensure story wrapper is resolved correctly
mgadewoll Jun 24, 2024
cec0c1c
Revert EuiValidatableControl change
cee-chen Jun 27, 2024
489cd2d
Show EuiInMemoryTable code snippet
cee-chen Jun 27, 2024
85ea8c4
fix(code-snippet): ensure story element is correctly resolved
mgadewoll Jun 27, 2024
a44df62
docs(storybook): re-enables EuiValidatableControl single story elemen…
mgadewoll Jun 27, 2024
1c784f4
feat(code-snippet): support arg value override replacement marker
mgadewoll Jun 27, 2024
58f724e
fix(code-snippet): ensure isForwardRef type guard captures all cases
mgadewoll Jun 27, 2024
b5a1e39
docs: update readme and comment
mgadewoll Jun 28, 2024
d272e3c
docs: update readme
mgadewoll Jun 28, 2024
dbb9a20
feat(code-snippet): remove default props from manual snippet
mgadewoll Jun 28, 2024
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
7 changes: 7 additions & 0 deletions packages/eui/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
parser: "typescript",
printWidth: 80,
semi: true,
singleQuote: true,
trailingComma: "es5"
}
227 changes: 227 additions & 0 deletions packages/eui/.storybook/addons/code-snippet/README.md
mgadewoll marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# Storybook code-snippet addon

## Description

> This is an internal EUI Storybook addon which adds code snippets to EUI stories.

The purpose of this addon is to improve the developer experience by providing code snippets with dynamically updated props based on the story controls.

This addon is provided as additional story panel next to the available panels for "Controls", "Actions" and "Interactions".

The basis for the code snippet generation is based on Storybooks [`Source`](https://storybook.js.org/docs/writing-docs/doc-blocks#source) block. The internally used [`jsxDecorator`](https://github.com/storybookjs/storybook/blob/2bff7a1c156bbd42ab381f84b8a55a07694e7e53/code/renderers/react/src/docs/jsxDecorator.tsx) file was copied and then adjusted and extended to fit the specific needs for EUI. The main functionality to generate a jsx string from react elements comes from the [`react-element-to-jsx-string`](https://github.com/algolia/react-element-to-jsx-strin) package.

## Concept

The `code-snippet` addon follows the [official guides](https://storybook.js.org/docs/addons/writing-addons) to create a Storybook addon. The only real difference is that this addon is not released separately but simply added and used internally.

The addon is defined and registered in `manager.ts` this ensures it's available in Storybook. Storybook handles most of the rendered output (e.g. tab list and tab buttons), the only custom content is what is passed via the `render` key on the addon config. This content will be output as child of the addon panel that Storybook renders.

```ts
// Register a addon
addons.register(ADDON_ID, (api: API) => {
// Register a panel
addons.add(PANEL_ID, {
type: types.PANEL,
title: 'Code Snippet',
match: ({ viewMode }) => viewMode === 'story',
render: Panel,
});
});
```

The main code snippet generation functionality is done in `jsx_decorator.tsx`. It's used as a decorator for every story in `preview.tsx`.


```ts
import { customJsxDecorator } from './addons/code-snippet/decorators/jsx_decorator';

const preview: Preview = {
decorators: [
customJsxDecorator,
]
}
```

This decorator generates the code snippet as a `string` and sends it via Storybooks [Channel events](https://storybook.js.org/docs/addons/addons-api#usechannel) to the custom addon panel which outputs the code string to the panel which updates its state on receiving the event ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/components/panel.tsx#L58)).

```ts
channel.emit(EVENTS.SNIPPET_RENDERED, {
id,
source: jsx,
args: unmappedArgs,
});
```

![Dimensions](https://github.com/elastic/eui/assets/44670957/9bb087f5-82bd-4b55-8264-5decc0a36cff)

## Differences to the Storybook `jsxDecorator`

The main changes/additions to the original `jsxDecorator` from Storybook are to ensure the generator outputs clean and EUI relevant code snippets.

Additional features added:
- renames Emotion wrappers to the actual component name (whenever we use `css` on a component in a story it will be an Emotion-wrapped component)
- renames stateful wrappers that start with the wording Stateful (requires us to follow an agreed naming convention)
- removes obsolete fragment wrappers (but keeps required ones)
- removes story specific wrappers (e.g. layout or styling)
- keep related wrappers (e.g. parent & subcomponent or related by name)
- resolves any other unexpected wrapper we might add to structure complex stories
- renames internal component names that start with _underscore (e.g. `<_Component>` is changed to `<Component>`)
- ensures `css` attribute is output properly and not as resolved Emotion object
- ensures boolean props are output in a meaningful way (generally as shorthand but it keeps specifically defined `false` values where `false` has a meaning)
- ensures project specific formatting via `prettier`
- supports adding manual code snippets


## How it works

The generation happens in different stages:

1. `pre-conversion`: determine what react element should be passed to react-element-to-jsx-string and with which options
2. `conversion`: pass react elements to react-element-to-jsx-string
3. `post-conversion`: do additional replacements on the returned string
4. `formatting`: format the result using prettier

### 1. Pre-conversion

Before passing a React element to the `react-element-to-jsx-string` package functionality, we first determine:

1. Should a story be skipped? ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/utils.ts#L196))
- a story may be skipped:
- by using `parameters.codeSnippet.skip` ([example](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/src/components/drag_and_drop/drag_drop_context.stories.tsx#L31))
- by returning an anonymous function without `args` from story `render`
2. Is a manual code snippet provided? ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/jsx_decorator.tsx#L100)) ([example](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/src/components/text_diff/text_diff.stories.tsx#L24))

3. What React element should be used? (only a single React element can be passed to `react-element-to-jsx-string`) ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/jsx_decorator.tsx#L146))

1. Check if the outer element should be resolved due to manual flagging via `parameters.codeSnippet.resolveChildren`. The children would be used instead. ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L214)).
2. We check the story react element for some base conditions ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L226)) for which we return the current element. Otherwise we move to the elements `children`:
- Is the element the story component?
- Is the element the stories parent? (We usually want to show Parent & subcomponents together)
- Is the element a subcomponent?
- Is the element a stateful wrapper? (To add interactivity we usually wrap stories in stateful wrappers that are not relevant for the snippet)
- Is the element a React.Fragment? (where obsolete we would want to remove wrapping fragments)
3. If the element is an array we resolve for the children ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L235)).

4. Once a single React element is determine the node and all its props (+ children) are recursively checked and resolved to ensure expected output:

- skip any obsolete React.Fragments (returning children instead) ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L330))
- ensure Emotion `css` is resolved and reversed as Emotion transforms the input syntax to an Emotion style object. (e.g. resolve `css={({ euiTheme }) => ({})}`) ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L357))
- ensure euiTheme tokens are output as variables (e.g. `someProp=euiTheme.colors.lightShade`) - This step adds the variable in special markes that are removed later. This is to prevent `react-element-to-jsx-string` from assuming a type and formatting unexpectedly ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L400))
- ensure `style` attribute is applied ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L468))
- resolve arrays (this outputs e.g. `someProp={[<SomeComponent />, <SomeOtherComponent />]}` instead of `[]`) ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L495))
- resolve objects (e.g. ensures output like `{ text: 'foobar' color: 'green' }`) ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L504))
- resolve class instances used as values to functions ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L518))
- [_todo_] resolve render functions

### 2. Conversion from React element to string

Once the React element is properly checked and resolved according to expected output needs, it can be passed to the functionality from `react-element-to-jsx-string` which will generate a jsx string based on the React element. ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L249))

```tsx
// example output
<EuiFlexItem
component="div"
css={{
backgroundColor: 'rgba(0, 119, 204, 0.1)'
}}
grow={true}
>
Flex item
</EuiFlexItem>
```

### 3. Post-conversion cleanup

The returned string of the conversion is then cleaned to ensure:

- rename internal Components (e.g. `<_Component>` to `<Component>`) ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L256))
- rename necessary React.Fragment to shorthand (e.g. `<React.Fragment>` to `<>`) [code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L277)
- ensure boolean value shorthand by manually filtering out values of `true` ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L290))
- this is manually handled and not by `react-element-to-jsx-string` because we want to keep some occurrences of `false` values when they have meaning (e.g. `<EuiFlexItem grow={false}>`)
- replace variable markers that were added in "1: Pre-conversion" ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L301))
- remove obsolete function naming ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx#L314))


### 4. Final Formatting

To ensure the formatting is correct after adjusting the string returned from `react-element-to-jsx-string` and to align it with the EUI projects formatting rules, we run `prettier` on the string as a final step. ([code](https://github.com/elastic/eui/blob/03d20559b4262d6a18de5fc8edf4ec3854753995/packages/eui/.storybook/addons/code-snippet/decorators/utils.ts#L207))

## Options

Currently there are a few addon specific parameter options added that can be used under the key `codeSnippet` in the parameters config key.

```ts
// meta or story config
const meta = {
title: 'Navigation/EuiButton',
component: EuiButton,
parameters: {
codeSnippet: {
// Optional way to override selected story args with manual values.
// This is useful when the story arg would render unreadable or not useful output.
// You can use interpolation markers #{} to ensure the value is output as is, this
// is useful for e.g. functions to prevent them from being called.
args: {
propA: 'new value for propA',
propB: "#{someFunctionCall('inputValue')}" // returns: propB={someFunctionCall('inputValue')}
},
// will skip code snippet generation for the component or story
// @default false
skip: true,
// Useful for complex story composition wrappers (using the story component as
// nested child and not as direct return for `render`).
// It will skip the outer story wrapper and return the code snippet for its children
// instead. See the story for `EuiHeader/Multiple Fixed Headers` as an example.
// @default false
resolveChildren: true,
// Useful when the story outputs additional content that should not be included in the
// snippet and instead only the actual story component should be output as snippet.
// @default false
resolveStoryElementOnly: true,
// The jsx renderer removes the story components default props. In case that they should
// be added to a specific code snippet it can be enabled by setting this option to `false`.
// @default true
removeDefaultProps: false,
}
}
}
```

## Additional functionality

### Manual code snippets

Instead of using the automatic code snippet generation, you can also provide a manual snippet which will be output instead. This is especially useful when the story content is not actually a component (e.g. a hook). You can see an example of this for the story of `useEuiTextDiff`.

To add the story args to the code snippet, add the defined marker `{{STORY_ARGS}}` to the snippet string. If the args should be spread on the root component use `{{...STORY_ARGS}}` instead.
These markers will be replaced automatically with the current story args. It's important to note that the `children` prop is removed and it should be manually added to the snippet input instead. Additionally the story `args` are filtered to remove the default props. This can be changed via the `removeDefaultProps` option.


```ts
// {{STORY_ARGS}}
parameters: {
codeSnippet: {
snippet: `
const [rendered, textDiffObject] = useTextDiff({{STORY_ARGS}})
`,
},
}

// {{...STORY_ARGS}}
parameters: {
codeSnippet: {
snippet: `
<SomeComponent {{...STORY_ARGS}}) />
`,
},
}
```

🚧 More will follow soon 🚧


## Limitations

1. Currently it's not yet supported to resolve `"render functions"` (either used as children or as any prop value). Components that make use of render functions (specifically for children) are currently (manually) skipped via `parameters.codeSnippet.skip: true` until support is added.

2. Currently the addon uses Storybooks `SyntaxHighlighter` component to output the code snippets. This works generally well but seems to have trouble properly detecting and styling code parts for large snippets. This results in some partially uncolored snippets. Using EUI components does currently not work just out of the box as there seem to be issues with applying Emotion correctly.
116 changes: 116 additions & 0 deletions packages/eui/.storybook/addons/code-snippet/components/panel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React, { useEffect, FunctionComponent } from 'react';
import {
useAddonState,
useChannel,
useStorybookApi,
} from '@storybook/manager-api';
import { AddonPanel, SyntaxHighlighter } from '@storybook/components';
import { styled } from '@storybook/theming';
import { STORY_RENDERED } from '@storybook/core-events';

import { ADDON_ID, ADDON_PARAMETER_KEY, EVENTS } from '../constants';
import { addHiddenStyle, clearHiddenStyle } from '../utils/addon_visibility';

const addonTabStyles = (selector: string) => `
${selector} {
display: none;
}
`;

interface PanelProps {
active?: boolean;
}

export const Panel: FunctionComponent<PanelProps> = ({ active, ...rest }) => {
const [addonState, setAddonState] = useAddonState(ADDON_ID, {
code: '',
isLoaded: false,
isSkipped: true,
});
const { code, isLoaded, isSkipped } = addonState;
const storybookApi = useStorybookApi();

useEffect(() => {
const addonTabId = `#tabbutton-${ADDON_ID.split('/').join('-')}-panel`;

/**
* we manually hide the addon tab element initially and show it only if it's not skipped.
* This uses style element injection over classes as we don't have access to the actual elements.
* We would need to wait for the elements to be rendered by Storybook to get them which is less
* consistent as controlling the styles.
* reference: https://storybook.js.org/docs/addons/writing-addons#style-the-addon
*/
if (isSkipped) {
addHiddenStyle(ADDON_ID, addonTabStyles(addonTabId));
} else {
clearHiddenStyle(ADDON_ID);
}
}, [isSkipped]);

const emit = useChannel({
[EVENTS.SNIPPET_RENDERED]: (args) => {
setAddonState((prevState) => ({ ...prevState, code: args.source ?? '' }));
},
[STORY_RENDERED]: (id: string) => {
const parameters = storybookApi.getParameters(id);
const isStorySkipped = parameters?.[ADDON_PARAMETER_KEY]?.skip ?? false;

setAddonState((prevState) => ({
...prevState,
isLoaded: true,
isSkipped: isStorySkipped,
}));
},
});

useEffect(() => {
if (isSkipped || !isLoaded || !active) return;

// emit OPENED event
emit(EVENTS.SNIPPET_PANEL_OPENED);

return () => {
// emit CLOSED event
emit(EVENTS.SNIPPET_PANEL_CLOSED);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSkipped, isLoaded, active]);

if (isSkipped) return null;

const emptyState = <span>No code snippet available</span>;
mgadewoll marked this conversation as resolved.
Show resolved Hide resolved
const loadingState = <span>Loading...</span>;

return (
<AddonPanel active={active ?? false} {...rest}>
{code ? (
<SyntaxHighlighter
language="tsx"
copyable
padded
showLineNumbers={false}
wrapLongLines
>
{code}
</SyntaxHighlighter>
Comment on lines +95 to +103
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any thoughts about dogfooding EuiCodeBlock for this instead of using Storybook's component? 👀

Copy link
Contributor Author

@mgadewoll mgadewoll Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's a good idea! I think I briefly had that thought while initially building this but went with the Storybook component just because it works out of the box (as they use it for their docs source code) and saved me some time 😅.
Let me have another look how it would work with our component 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I realize now why I took the Storybook component. There are issues using the EUI components because emotion is not properly resolved somehow for the addon panel. 🫠

You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha whoops 🙈 Yeah, Storybook probably needs the Emotion babel preset which is a whole fun setup thing (https://emotion.sh/docs/css-prop). You could the JSX pragma to see if that works?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But no worries if it doesn't, I'm totally fine with the Storybook component as-is!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I had a first brief look at it to set this up but it didn't work as expected and it will need some more digging. I think I'd opt for leaving it as is for now and doing the update as a standalone task because I do think it would be generally good to be able to use our component as the Storybook SyntaxHighlighter has some limitation that it does not always properly highlighting the code.

🗒️ What I tried/noticed:

  • Emotion works fine in the preview but not the manager parts
  • I tried adding the emotion preset and it did absolutely nothing (it also seemed like the root babel config is not used - adding a manual config for Storybook with the preset resulted in custom components with css prop working but the imported EUI files still were broken)
  • adding the JSX pragma worked when it was set in the EUI component files that are imported, not when added in the Storybook files (which is not an option)

) : (
<Container>{isLoaded ? emptyState : loadingState}</Container>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on using EuiEmptyPrompt or EuiCallOut instead of this container? Am I being too extra here right now? 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that's a good idea! Why not reuse what we already have!
Let's see first if we can hide the panel for not available code snippets because we would not need this, if we just hide it 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah wait, for the loading state it would still be used, so yes! I'll check how that'll look like 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ This is blocked due to the same issue around Emotion mentioned here.

)}
</AddonPanel>
);
};

const Container = styled.div(({ theme }) => ({
display: 'flex',
justifyContent: 'flex-start',
margin: 0,
padding: theme.layoutMargin,
}));
Loading
Loading