figma / code-connect Goto Github PK
View Code? Open in Web Editor NEWA tool for connecting your design system components in code with your design system in Figma
License: MIT License
A tool for connecting your design system components in code with your design system in Figma
License: MIT License
First of - thanks for the great work on this!
It would be amazing to also support Web Components (Lit, Stencil) to connect.
Our (Stripe's) Button component in Figma has a state
enum like this:
state: figma.enum("State", {
Default: "default",
Hovered: "hovered",
Pressed: "pressed",
Focused: "focused",
Disabled: "disabled",
})
In code the hovered, pressed, and focused states are based on CSS pseudo states and cannot be set via a prop. However, the disabled state can be manually set:
<Button disabled />
I'm not entirely sure how to model this in my Code Connect file to get the right syntax. It seems like I'd have to do this:
example: ({state}) => (
<Button disabled={state === 'disabled'} />
),
which of course does not result in the correct or even working code in Figma:
I tried to do this sort of thing:
example: ({state}) => state === 'disabled' ? <Button disabled /> : <Button />
But for some reason the code in Figma always shows up as <Button disabled />
no matter which enum is selected.
Would appreciate some guidance on how to handle this—thanks in advance!
Interesting feature - it looks like a builtin variant of Storybook.
Could you please add support for .NET MAUI?
I had originally started writing this issue because I kept getting errors when trying to scaffold a new component.
Although this is a minor issue, I can see some people getting hung up on it. The solution is simply to wrap the copied link in quotes to make sure the command doesn't break.
I think the instructions should reflect this, saying something like
npx figma connect create "https://..." --token <auth token>
While not currently documented, the source code shows support for a links
property which is supposed to show up in Figma (but it currently does not):
/**
* A list of links that will display in Figma along with the examples
*/
links?: FigmaConnectLink[]
First, congrats on the launch! 🎉 Super excited to see where Dev Mode is going. Of course I couldn't stop myself from playing around yesterday during the announcement and in general it was super easy to set up.
But I got stuck while trying to update the importPaths
for our component package. After copying the configuration example from the React documentation I noticed that some keys seem to miss quotes. My setup now looks like this:
figma.config.json
{
"codeConnect": {
"include": [
"packages/xyz/src/components/**"
],
"exclude": [],
"react": {
"importPaths": {
"./*": "@org/xyz"
}
}
}
}
Button.figma.tsx
import figma from '@figma/code-connect'
import { Button } from './Button'
Uploading to Figma immediately worked, but no matter what I specify at importPaths
, I get nothing but import { Button } from "./Button
in Dev Mode.
It could definitely be me, I would be thankful for a hint in the right direction!
I have a Figma component that uses a "Text" layer instead of a property. With code connect, is there a way to target this layer to map to a coded component prop? In my scenario, I'm trying to map this to the label
prop in the coded component. I've tried using figma. children()
with the name of the layer with no success, I know this isn't the intended here.
All the nested layers in this tree are either row or column layouts.
Currently, the import
statement of the example block is inferred/derived from the actual import
statement from the *.figma.tsx
file. This can be altered to a certain extent through importPaths
from figma.config.json
.
But it's not flexible enough for more use cases.
For example, the local component file is called Button
with a capital "B".
So the import is defined as import { Button } from './Button'
.
But the component is distributed as a standalone package named @uikit/button
, with a lowercase "b".
Defining an import path like "*": "@uikit/*"
will result in import { Button } from '@uikit/Button'
, with the original capital "B" vs the expected lowercase "b".
Currently, "instance swap" properties are referenced as "links" to other components. It would be great to be able to reference them by name, and get a string value when mapping back to the React component. Ideally, we should also be able to manipulate the strings when mapping (for example, to convert from snake_case to camelCase).
For icons for example, we don't have a React component for each individual icon. Instead, we use a single <Icon>
component, and we use a string prop to reference icons by id.
<Icon id="icChef" />
When connecting this to the Figma component, we get a "link" to the instance-swap icon, but we don't have a connected React component for every icon in Figma.
figma.connect(
Icon,
"https://www.figma.com/file/...[Icon component with an instance swap]",
{
props: {
iconId: figma.instance("Icon ID"),
},
example: (props) => <Icon id={props.iconId} />
},
);
So ideally, we should be able to do something like this, where the instance has a name
attribute we can access.
figma.connect(
Icon,
"https://www.figma.com/file/...[Icon component]",
{
props: {
iconId: figma.instance("Icon ID"),
},
example: (props) => <Icon id={props.iconId.name} />
},
);
Additionally, with a custom mapper function, we could also manipulate the instance at will:
props: {
// just get the `name` as a string
iconId: figma.instance("Icon ID", (instance) => instance.name),
},
example: (props) => <Icon id={props.iconId} />
or even change it how we see fit:
iconId: figma.instance("Icon ID", (instance) => toCamelCase(instance.name)),
I've created an icons.figma.tsx
file like the docs suggest using the sample script, and everything is working great as far as Figma goes. The generated code is exactly what I want, ie:
import { Button } from '@acme/ui';
import { IconName } from '@acme/icons';
<Button>
<IconName />
Button Text
</Button>
Where @acme/ui
are all the design system React components, and @acme/icons
are icon React components specifically. These two are separate packages that live in two separate repos.
I'm trying to add the Figma files to the source repo of the React UI lib, so component imports are local files, but the icon imports come from the separate icons package (ie. they're in the node_modules
).
The generated code is correct. However, I'm seeing this warning in the output when publishing:
Import for IconName could not be resolved, make sure that your `include` globs in `figma.config.json` matches the component source file (in addition to the Code Connect file). If you're using path aliases, make sure to include the same aliases in `figma.config.json` with the `paths` option.
Where IconName
is the name of my React component icon, which comes from a separate library:
// icons.figma.tsx
import figma from '@figma/code-connect';
import { IconName} from '@acme/icons';
figma.connect(IconName, ...);
My figma.config.json
looks like this:
{
"codeConnect": {
"include": ["src/figma/**"],
"exclude": [],
"importPaths": {
"*": "@acme/ui",
"@acme/icons": "@acme/icons"
}
}
}
And the component Figma files (ie. Button.figma.tsx
look like this:
// src/figma/Button.figma.tsx
import figma from '@figma/code-connect';
import { Button } from '../components';
figma.connect(Button, ...);
What am I missing?
Is there a way to connect component libraries like Mantine or Mui?
We have a <Tag/>
component with a boolean rounded
prop which is set by default to true
.
Similarly, in Figma, we also have a rounded
boolean prop defaulted to true
.
I'm having trouble configuring the Tag.figma.tsx
to output the proper code snippet.
If I don't change the default true/false mappings, this is the true
code snippet:
This is false
:
Both of these snippets would render the same component, as rounded
is defaulted to true
in the React component.
I would like a way to have the code snippets to look like this for true
:
import { Tag } from "../NewTag"
<Tag>Tag</Tag>
and this for false
:
import { Tag } from "../NewTag"
<Tag rounded={false}>Tag</Tag>
I've tried mapping the true/false states props individually, but I haven't found a way to produce the desired result.
props: {
rounded: figma.boolean('rounded?', {
false: false, // Any way to make this render `rounded={false}` ?
true: undefined
})
}
We use base components in our Design System, and we expose properties from nested components so they can be combined with properties from the main component.
We have a basic Icon
component with a Size
enum and an Icon ID
instance swap.
We use it in a .button-shape
base component as both an Icon
and a Trailing Icon
. We expose its props in this base component.
We then use the base button to build the actual Button
component, and we expose all its props (including the icon props). The final variants and states are defined at the main component level.
With this setup, I couldn't find a way to combine the .button-shape
props with the Button
props, since in code we only have a single Button
component without a base ButtonShape
. I can exclude Icon
, since we pass that as a child rather than via a prop.
I know we can combine multiple Figma components to a single React component, and likewise multiple React components to a single Figma component. But it would be great if we could also map props from nested instances to a single React component.
Something like this maybe:
figma.connect(
Button,
"https://www.figma.com/file/...",
{
props: {
// 👇 properties from main component in Figma
variant: figma.enum("Variant", {
Primary: "primary",
Secondary: "secondary",
// ...
},
disabled: figma.enum("State", {
Disabled: true,
}),
busy: figma.enum("State", {
Busy: true,
}),
// 👇 map properties from specific children to parent props
button_shape: figma.children(".button-shape", {
size: figma.enum("Size", {
Large: "large",
Medium: "medium",
// ...
}),
rounded: figma.boolean("Rounded"),
iconOnly: figma.boolean("Icon Only"),
label: figma.boolean("Icon Only", {
false: figma.string("↳ Label"),
true: undefined,
}),
icon: figma.boolean("Icon", {
true: figma.children("Icon"),
false: undefined,
}),
trailingIcon: figma.boolean("Trailing Icon", {
true: figma.children("Trailing Icon"),
false: undefined,
}),
}),
}
example: (props) => (
<Button
// these props are from the main component
variant={props.variant}
disabled={props.disabled}
busy={props.busy}
// these props are passed from `.button-shape` through `props.button_shape`
size={props.button_shape.size}
rounded={props.button_shape.rounded}
iconOnly={props.button_shape.iconOnly}
>
{props.button_shape.icon}
{props.button_shape.label}
{props.button_shape.trailingIcon}
</Button>
),
}
);
The current workaround I tried is to map both Button
and .button-shape
Figma components to the same Button
React component. But this is less than ideal since it ends up showing as nested <Button>
components.
Side note: I see the hierarchy is also not respected, since Icon
should be a child of the inner Button
next to the label.
figma.connect(
Button,
"https://www.figma.com/file/...[Button component]",
{
props: {
variant: figma.enum("Variant", {}),
disabled: ...
busy: ...
// simply map nested instances to a `children` prop
children: figma.children([".button-shape", "Icon", "Trailing Icon"]),
},
example: (props) => (
<Button variant={props.variant} disabled={props.disabled} busy={props.busy}>
{props.children}
</Button>
),
}
);
// also map .button-shape to Button
figma.connect(
Button,
"https://www.figma.com/file/...[.button-shape component]",
{
props: {
size: figma.enum("Size", {}),
rounded: figma.boolean("Rounded"),
iconOnly: figma.boolean("Icon Only"),
// ...
},
example: (props) => (
<Button size={props.size} rounded={props.rounded} iconOnly={props.iconOnly}>
{props.icon}
{props.label}
{props.trailingIcon}
</Button>
),
}
);
Excited to put forward my recommendation for React Native support.
I'm not sure how this would work, but it would be great to be able to dynamically remove props from the examples based on other boolean values.
In this example, when description?
is false
, the Figma Props UI is smart enough to hide the description
prop entirely, even though that prop still has a value. However, I'm not able to hide this prop in code, so the component snippet is wrong and will add text to the component that shouldn't be there at all.
Hey there - congrats on the launch, this is really exciting!
I have a question that I didn't really see an answer to in the docs. Is TypeScript and .tsx
extension the only way to use Code Connect currently? I'm trying to add this to a plain JavaScript project, and couldn't get it to run after renaming *.figma.tsx
to *.figma.jsx
.
Is this at all configurable? If not, would you consider adding such a feature at some point in the future?
Thanks team for providing this capability. We're really excited about starting to integrate this for our React Web and iOS SwiftUI component implementation. This is more a question of when we could expect the same support for Jetpack Compose to begin exposing the same capability for our Android implementation. 🚀
I believe the title says it all. I think support is planned in the roadmap, so is more on when it will happen.
Thanks for the great work!
the title says it all, i think.
Hit that 👍 below. It helps Figma people to decide what to prioritize and deliver next.
I see from your readme that you have support for React and SwiftUI but nothing about Angular. Do you support Angular, and if not, are the plans to support it in the roadmap?
Currently code-connect doesn't support Svelte, this issue is for tracking support for Svelte
Trying to publish
a sample component and I’m getting the following error for multiple components (not the component I’m trying to publish, but colocated components in the parent directory:
Error parsing story /Users/ramy/GitHub/metal-design-system/packages/component-library/src/components/Banner/Banner.stories.tsx: ParserError: "url" property not found in "design" object in story metadata
-> /Users/ramy/GitHub/metal-design-system/packages/component-library/src/components/Banner/Banner.stories.tsx:154:11
The url
prop is present and filled in the story file, but it’s pointing to an object in a different file, like so (we keep all the links in one place for Storybook for easier updating):
export default {
component: Banner,
decorators: [colorModeDecorator(), paddingDecorator()],
parameters: {
chromatic: { viewports: chromaticViewportParameters() },
design: {
type: "figma",
url: FigmaLinks.web.v1.Banner,
},
},
};
Guessing this is some kind of conflict with the design add-on?
It’s also unclear to me why it’s trying to do anything with those files since I don’t have a .figma.tsx
file for those. I’m only trying to publish one component but it’s returning this error for many unrelated components.
Happy to provide more details here!
Hi,
first of all awesome work!
I attended your announcement Zoom meeting and am in awe of the possibility of connecting code snippets to each component and its instances. While watching the demo, I was wondering if it would be possible to also connect modes to code. I asked this question in the meeting but was asked to share more information here.
So basically we set up our components with component-level variables and modes. This means we only have one instance per component and handle the rest with modes.
For example, our "Button" component is just one instance, and the different variants like "Primary", "Secondary" and"Tertiary" are three modes we created in a "Button - Variants" collection. Same for "Sizes" and "States".
In order for us to use code connect it would be great if there was a way to tell the code if for example the mode "Button - Variant: Primary" is selected and map the correct prop to the button in the code.
Let me know if you need more information or if anything is unclear in my explanation.
I would be happy to hear back from you!
Thank you!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.