Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Code Connect
Auto-generated code snippets with mapped properties between Figma and code.
Table of content
Scope
The purpose of this investigation was to:
For the purpose of the investigation, I used the EUI usage metrics to define the most common components (this excludes Cloud UI) which provide enough complexity:
There are some components that are used often but are less complex and their auto-generated code snippets might not be as useful for investigation purposes:
Summary
It is technically feasible to integrate Code Connect. It will significantly speed up feature development, onboard new developers quicker, minimize confusion regarding component usage, provide the space to advise best practices and highlight all discrepancies between the design and code implementation.
On the other hand, the integration will depend on the designers using the official main components and not detaching instances, and it will be fragile to any big (like the Visual Refresh initiative) or small (renaming a Figma property) Figma component library changes and a chore to set up and maintain (for the EUI development team).
Most of the tricky use cases can be handled without much issue (e.g. a variant in Figma being a separate component in the code) and some, while possible, require a lot of work (e.g. integrating icons). Storybook integration in its current form is poorly configurable, creates conflicts between Figma property mapping, React component props and story arguments, and has bugs (e.g. code snippet of nested components not hydrated). It would be recommended to use standalone Figma files with greater flexibility at the cost of more maintenance.
To bring benefit to all front-end / full-stack engineers, Dev Mode seats have to be provided to all.
Considerations
figma.connect
calls in a for-loop, as an example." source: https://github.com/figma/code-connect/blob/main/docs/react.md#basic-setupDemo
Short video demo here.
Figma file here.
Note: For most of these cases, the integration could be even better.
Conclusions
Benefits
aria-label
when "Icon only" property is toggled).Limitations
as Y
, e.g.as const
to narrow down the type) and@ts-ignore
or@ts-expect-error
comment annotations will be shown in the code snippet because the examples are not executed but resolved as a string.Storybook
Another example of the awkward Storybook integration is EuiButtonGroup (button-group.stories.tsx) which has 2 component wrappers: StatefulEuiButtonGroupSingle and StatefulEuiButtonGroupMulti. In order for these components to display correct names in the code snippet, they have to be renamed to EuiButtonGroup. But both cannot be named that way.
Additional problem is that for the sake of showcasing in Storybook, the wrappers add state logic. This state logic, abstracted in the wrappers, is not explicitly defined in the render function that Code Connect uses for code snippet generation. Therefore, important props are missing (like
onChange
andidSelected
) from the code snippet:If the original component is renamed within the story or a wrapper is created and used for the render functions, there's no way to change it for the code snippet. The only way to mitigate this is to rename the original component when importing and name the wrapper as the original component.
Storybook Designs add-on configuration capabilities are poor, e.g. we cannot add an import
import { Component } from '@elastic/eui';
(there's an issue open for this; on the other hand, developers can rely on auto-import) or resolve the "url" based on global configuration to avoid repetition (on the other hand, there can be a util function that returns the whole Figma URL or a constant to use within a template literal but copy-pasting a link from Figma is quick and easy so it might be a redundant abstraction).Storybook supports variant restrictions. In the case of standalone
*.figma.tsx
files, all subcomponents can be integrated within the same file. In the case of Storybook integration, usually each component has a separate*.stories.tsx
file, i.e. the relationship between Figma components and code components will now be scattered across different stories, even though in Figma it's the same component. Furthermore, reusing property mapping would be tricky. We'd need to extractsharedProps
constant to separate file to be reusable by all stories.Example: EuiButton and EuiButtonEmpty. Figma's Button style "empty" maps to a separate component in the code - EuiButtonEmpty. That component has a separate stories file. Therefore, from the level of EuiButton stories file we do not know about this subcomponent and may believe that we just haven't implemented the style for "empty". This might as well turn out to not be an issue. Take a look at:
I'm only adding "Playground" story to the "examples" set but there can be multiple stories, each representing a different use case (as per Storybook snippet in Variant restrictions):
Typography
Typography integration depends on whether the Figma library uses text styles (optionally with typography variables) or a component with instance swap. In the latter case, integration is possible because code implementation is based on the usage of typography components (e.g. EuiText and EuiTitle). But most of the time, the former is true because it's easier to manage by the designers.
Whatever the case, the EUI Figma library will support both ways. We can integrate typography components easily and display accurate code snippets for them. We cannot map in any way text styles.
For an example, see EuiPanel integration.
There's an issue open for this topic in Code Connect GH repo.
Icons
Each icon (glyph) is a separate component in Figma. For the purposes of this explanation, let's call them atomic icon components. They are used as an instance swap in all components, including an Icon component which is used as a standalone icon. This provides a unique challenge because most EUI components in the code, e.g. EuiButton, receive an icon name / source / SVG element in the
iconType
prop, and not the EuiIcon component instance:and that's the reverse approach to the Figma component library:
which results in a weird-ish code snippet being generated when figma.instance is used (no better alternative):
where this "Icon" is a Figma component reference. Upon copying the code snippet to the clipboard, here's what we get:
If I connected the chosen icon component (say "accessibility") in Figma to EuiIcon component, then Figma would hydrate the EuiButton code snippet with the EuiIcon code snippet of the accessibility icon instance swap, resulting in:
Circling to the beginning, that's not how the Button is designed to be used (with render props).
The Icon component is easily integrated because it's used as a standalone component and not an instance swap:
On the other hand, the atomic icon components are used as swappable instances in its "Type" property. In theory, those should be mapped to a string, resulting in the following code snippet:
Unfortunately, this is not possible and will result in "accessibility" being a comment upon copying and pasting because it's treated as an unlinked React component:
One solution would be to, instead of integrating atomic icon components, integrate all icon instance swaps with the EuiButton. That is not sustainable in the long run. Imagine integrating all components that consume an icon the number of times there are icons in the library.
It is recommended to create a script that pulls icons from a Figma file and generates icons.figma.tsx with appropriate integrations. You can read more about it here.
There are some issues on the topic in Code Connect GH repo:
Component Insights
EuiButton, EuiButtonEmpty
Figma | Docs | Code
Screen.Recording.2024-10-11.at.14.21.41.mov
EuiButtonGroup
Figma | Docs | Code
Screen.Recording.2024-10-11.at.14.17.14.mov
EuiPanel
Figma | Docs | Code
Screen.Recording.2024-10-11.at.14.25.37.mov
false
values are resolved to no prop passed, we cannot replicatehasShadow={true}
interface in the integration. A workaround are variant restrictions (as explained here), unfortunately Code Connect throws an error: "The Figma Variant "Shadow" does not have an option for true". For now, I skippedhasShadow
prop altogether.EuiBadge
Figma | Docs | Code
Screen.Recording.2024-10-10.at.10.52.54.mov
iconType
andiconSide
, and we can only ever have one icon at a time.EuiCallOut
Figma | Docs | Code
Screen.Recording.2024-10-11.at.13.00.55.mov
EuiToolTip
Figma | Docs | Code
Screen.Recording.2024-10-11.at.13.05.07.mov
EuiFieldText
Figma | Docs | Code
Screen.Recording.2024-10-11.at.13.34.08.mov
display
prop).EuiComboBox
Figma | Docs | Code
Screen.Recording.2024-10-11.at.13.49.05.mov
display
prop).EuiSelect
Figma | Docs | Code
Screen.Recording.2024-10-11.at.13.54.09.mov
display
prop).Sources