Skip to content

Howto: code-connect with (icon) subcomponents #86

Closed

Description

@glomotion
  • Code Connect CLI version: 1.0.1
  • Operating system: MacOS: 14.5 (23F79)
  • Code Connect file, Figma design and/or relevant code snippet that could help us get more context (see below)

So our codebase applies icons in a slightly different way to MUI and the figma code-connect demo icon scripts etc.

Essentially, we have a root component, called Icon.

This icon component looks a bit like:

// simplified Icon.tsx
const icons = [
  "Add",
  "Alert",
  "Apple",
  ...
] as const;

export function Icon({ icon }: { icon: (typeof icons)[number] }) {
  const iconPaths = useSomeHookToGetSvgPathsData(icon);
  return <SvgIcon>{iconPaths}</SvgIcon>
}

Other components, like our <Button> component for example, support the Icon component as a subcomponent.
eg:

<Button>
  <Button.Icon icon="Apple" />
  Some text
</Button>

The Button.Icon subcomponent looks something like this:

export function ButtonIcon({ icon }: { (typeof icons)[number] }) {
  return <Icon style={{ /* some unique styles */ }} icon={icon} />;
}
ButtonIcon.displayName = 'Button.Icon';

This allows us to apply Button specific styles to the <Button.Icon /> subcomponent.

Im kinda struggling to work out how to get this to work within code-connect.

Until today, the below code-connect file was kinda working within FIGMA:
(the below code no longer renders anything for code-connect inside FIGMA, when either of the "Icon Left" or Icon Right" toggles are enabled inside of figma. No errors happen when the below code is published to figma, however 🤔 ).

// packages/react/src/components/Clickable/Buttons/Button.figma.tsx
import { figma } from "@figma/code-connect";

import { Button } from "@/components/Clickable/Buttons";

const FIGMA_URL =
  "https://www.figma.com/design/oHsoXoDsvnhjlbpzSIbHvU/BIOME?node-id=2-3486&m=dev";

const COMMON_PROPS = {
  children: figma.string("Label"),
  size: figma.enum("Size", {
    Large: "large",
    Medium: "medium",
    Small: "small",
  }),
  disabled: figma.enum("State", {
    Disabled: true,
  }),
  leftIcon: figma.boolean("Icon Left", {
    true: <Button.Icon icon="Apple" />,
    false: undefined,
  }),
  rightIcon: figma.boolean("Icon Right", {
    true: <Button.Icon icon="Apple" />,
    false: undefined,
  }),
};

const imports = ["import { Button } from '@biom3/react'"];
const example = ({
  fullVariant,
  children,
  size,
  disabled,
  leftIcon,
  rightIcon,
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
}: any) => {
  return (
    <Button variant={fullVariant} size={size} disabled={disabled}>
      {leftIcon}
      {children}
      {rightIcon}
    </Button>
  );
};

figma.connect(Button, FIGMA_URL, {
  variant: { Variant: "Primary" },
  props: {
    ...COMMON_PROPS,
    fullVariant: figma.enum("Type", {
      Fatal: "primary/fatal",
      Inverse: "primary/inverse",
      Default: "primary",
    }),
  },
  imports,
  example,
});

/* ... more figma.connect() statements */

However the downside of the above was obviously that the <Button.Icon /> subcomponent was always simply using icon="Apple" - instead of whatever icon was actually being set in figma. :(

Is there:

  1. a way to evolve the code connect above, so that the icon="" prop being passed to <Button.Icon> is the actual icon name in figma?
  2. any ideas why the code above no longer works inside of figma? Any known bugs/outages etc?

Activity

  1. changed the title [-]How to get code connect working with icon subcomponents[/-] [+]How to get code connect working with (icon) subcomponents[/+] on Jul 3, 2024
  2. changed the title [-]How to get code connect working with (icon) subcomponents[/-] [+]Howto: code-connect working with (icon) subcomponents[/+] on Jul 3, 2024
  3. changed the title [-]Howto: code-connect working with (icon) subcomponents[/-] [+]Howto: code-connect with (icon) subcomponents[/+] on Jul 3, 2024
  4. added
    under discussionThe Code Connect team is currently discussing this request
    on Jul 3, 2024
  5. jyyang0 commented on Jul 3, 2024

    @jyyang0

    Hey @glomotion, thanks for the report -- for the issue of the code connections not being displayed, this is an issue we're currently aware of and in the process of fixing, I'll post an update when it is resolved

    As for the issue with your icons -- As you've identified here, in code connect we only parse your code so currently it will not have a connection to a property in code. The way you would implement this depends on how the icons are setup -- Are the icons their own components in Figma? If so, if the icon itself has a Code Connect associated with it, you could use a figma.children("Left Icon") (If the icon is just a nested instance) or the figma.instance (If the icon is an instance swap property) helpers in order to represent the nested code.

    However, let me know if your components are set up differently.

  6. glomotion commented on Jul 4, 2024

    @glomotion
    Author

    OK so I have done a bit more digging, and have gathered a bit more info on the structure of the actual icon entities themselves inside figma (by making some JSON api calls and looking at the data which comes back)

    Screenshot 2024-07-04 at 2 43 10 PM

    Basically, the designers have setup a page full of "COMPONENT_SET" entities. Each one has a name: eg the name of the Icon.

    // component set JSON:
    {
      id: '16204:38405',
      name: 'Notification',
      type: 'COMPONENT_SET',
      ...
    }
    

    Inside each icon component set, there are 2 children:

    children: [
        {
          id: '16204:38406',
          name: 'Bold=Yes',
          type: 'COMPONENT',
         ...
        }, {
         id: '16204:38409',
          name: 'Bold=No',
          type: 'COMPONENT',
          ...
        }
    ]
    

    Notice how the child components have nothing in their JSON about the fact they they are icons, and that they are variants of the "Notification" icon.

    Somehow, these component_set > component entities, need to be mapped to their equivalents in code, which look like:

    <Icon icon="Notification" variant="regular" />
    // or
    <Button.Icon icon="Nofitication" variant="bold" />
    // or 
    <MenuItem.Icon icon="Notification" />
    // etc etc

    Basically, over a dozen components across our design system actually support the <Icon /> component as a child subcomponent. So constructing a script to make a CodeConnect for every single icon, of every single possible subcomponent, seems a bit crazy. Thus, i'm hoping there is another way. 😅

  7. karlpetersson commented on Jul 4, 2024

    @karlpetersson

    Hey @glomotion, thank you for this feedback. Agree that this seems far from ideal. We're currently thinking about how we can make connecting icons both easier and at the same time cover more use cases. I don't have anything concrete to share right now, but I'll bring this to the team to discuss and keep you posted!

  8. glomotion commented on Aug 16, 2024

    @glomotion
    Author

    hey there @karlpetersson - just wondering if there is any updates you can share here yet? 🥺 Would still really love to try and get code connect integrated within our figma icons etc.

  9. karlpetersson commented on Sep 4, 2024

    @karlpetersson

    Hi @glomotion - this is currently a high priority for us to resolve, and while it likely won't be ready for the coming release, we're aiming to support this asap.

  10. slees-figma commented on Oct 18, 2024

    @slees-figma

    Hey @glomotion! We've released some APIs in 1.2.0 to improve Code Connect for icons. For your example, you could initially connect icons as normal:

    figma.connect("icon", {
      props: {
        iconId: "something",
        variant: figma.enum("Variant", {
          "regular": "regular",
          "bold": "bold",
        })
      },
      example: ({ iconId }) => <Icon id={iconId} />
    })

    Then use the new .render() API to get access to those icon props and render different JSX for each of your "parent" components, e.g. Button.Icon:

    figma.connect("parent", {
      props: {
        leftIcon: figma.boolean('Icon Left', {
          true: figma
            .instance('IconInstance')
            .render<{
              iconId: string
              variant: 'regular' | 'bold'
            }>(({ iconId, variant }) => <Button.Icon icon={iconId} variant={variant} />),
          false: undefined,
        }),
      },
    })

    Let us know if you experience any issues getting set up here! For more info, see the docs: https://github.com/figma/code-connect/blob/main/docs/react.md#installation

  11. seanmq commented on Feb 4, 2025

    @seanmq

    Then use the new .render() API to get access to those icon props and render different JSX for each of your "parent" components, e.g. Button.Icon:

    figma.connect("parent", {
    props: {
    leftIcon: figma.boolean('Icon Left', {
    true: figma
    .instance('IconInstance')
    .render<{
    iconId: string
    variant: 'regular' | 'bold'
    }>(({ iconId, variant }) => <Button.Icon icon={iconId} variant={variant} />),
    false: undefined,
    }),
    },
    })
    Let us know if you experience any issues getting set up here! For more info, see the docs: https://github.com/figma/code-connect/blob/main/docs/react.md#installation

    Hi @slees-figma , any plan to make this .render() API available for Web Component integration (@figma/code-connect/html)?

  12. plasticmind commented on Feb 17, 2025

    @plasticmind

    @slees-figma Seconding the request from @seanmq — trying to get access to the name of the icon in a nested instance (which is an individual component):

    and thinking render might help us accomplish this.

    See #245 for more details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    under discussionThe Code Connect team is currently discussing this request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions