-
Notifications
You must be signed in to change notification settings - Fork 816
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
base: main
Are you sure you want to change the base?
[Storybook] Add story code snippets #7716
Conversation
6c1c416
to
01bfb67
Compare
- adds addon panel for outputting code snippet with Storybooks SyntaxHighlighter - registers code-snippet addon panel in Storybook manager
- adds the main bulk of the addon functionality; the jsxDecorator takes the story element, transforms it according to our needs and passes the element to react-element-to-jsx-string to output a jsx string
- calling useEuiTheme only on the initial decorator call and not every recursive check
- ensure naming convention for stateful wrapper to start with Stateful... for filters to work - ensure args are passed along when using decorators - ensure no anonymous render functions are used as they would otherwise be skipped
- EuiCombobox: setup onChange handler and use it in the stateful wrapper; fix static value for options - EuiheaderAlert: adds a storybook only prop to ensure the full code is used for the snippet generation and not the close state one as the snippet is only generated on arg change and not triggered by preview changes
β¦e render functions
e144ec5
to
6d3413d
Compare
const Flyout = ( | ||
props: EuiHeaderAlertProps & { __STORYBOOK_ONLY__isOpen: boolean } | ||
) => { | ||
const { __STORYBOOK_ONLY__isOpen, ...rest } = props ?? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This here could be a bit controversial I guess. πΆοΈ
The issue I'm trying to solve is that the code snippet is generated based on available code on mount or arg change but the story starts in "closed" state which means that the flyout is actually not available and hence not part of the generated code. Changes in the rendered preview do not trigger another code snippet generation.
Either we'd need to always have the flyout opened to ensure the full code is generated or - as currently done here - we manually trigger the initial open state and close it right after.
import { useEuiTextDiff, EuiTextDiffProps } from './text_diff'; | ||
|
||
const meta: Meta<EuiTextDiffProps> = { | ||
title: 'Utilities/useEuiTextDiff', | ||
// casting here to match story output while preserving component docgen information | ||
component: useEuiTextDiff as unknown as () => ReactElement, | ||
parameters: { | ||
codeSnippet: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently the only use case for a manual code snippet but as this story is for a custom hook and not a component, the code snippet generation actually does not make sense otherwise. We could skip the generation but providing the snippet manually provides - imho - more value to users.
@@ -90,17 +96,18 @@ const StatefulInputPopover = ({ | |||
closePopover?.(); | |||
}; | |||
|
|||
const connectedInput = React.isValidElement(input) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to simulate the expected behavior that the popover opens on focusing the input.
setSelectedOptions(options); | ||
action('onChange')(options, ...args); | ||
onChange?.(options, ...args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small update to enable the handlers globally and use them here instead of the manual action
calls.
@@ -81,15 +86,19 @@ export const Playground: Story = { | |||
export const WithTooltip: Story = { | |||
parameters: { | |||
controls: { | |||
include: ['fullWidth', 'options', 'selectedOptions'], | |||
include: ['fullWidth', 'options', 'selectedOptions', 'onChange'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we want to use onChange
in the wrapper component, it needs to be included to be available.
Preview staging links for this PR:
|
π Build Succeeded
History
|
Summary
π§ This PR is still being updated and annotated π§
π’ This PR adds code snippets to our stories. π¦ π©βπ»
The goal of this is to improve devX by providing dynamically updated code snippets for the stories. The code snippet is generated on story load as well as when any
args
change (e.g. when controls in the controls table are being updated)This new functionality for code snippets is provided in an additional story panel next to the available panels for "Controls", "Actions" and "Interactions".
The basis for the code snippet generation is heavily inspired (copied and enhanced) on Storybooks Source block. The internal
jsxDecorator
file was copied and then adjusted to our specific needs. The main functionality to generate a string from react elements comes from thereact-element-to-jsx-string
package that is used.The overall setup
We run our custom
jsxDecorator
on every story as a decorator viapreview.tsx
. This decorator generates the code snippet asstring
and sends it via Storybooks Channel events to our newly added custom addon panel which outputs the code string using StorybooksSyntaxHighlighter
copmponent.The main updates to the
jsxDecorator
on our side are to ensure the code outputs clean and relevant code snippets.What was considered:
css
on a component in a story it will be an Emotion component)Stateful
(requires us to follow an agreed convention)_
underscore,<_Component>
is changed to<Component>
)css
attribute to ensure it is not transformed to Emotionfalse
values wherefalse
has meaning)The updates happen in different stages in
jsxDecorator
:react-element-to-jsx-string
and with which optionsreact-element-to-jsx-string
prettier
Options
Currently there are two addon specific parameter options added with this PR that can be used under the key
codeSnippet
in theparameters
config key.Limitations
children
or any prop value)Components that make use of render functions (specifically for
children
) are currently (manually) skipped until support is added.Screenshots
skipped code snippet generation
Disclaimer
jsxDecorator
functionality yet.QA