Using Icons
Icons from Figma
Our Figma Plugin export icon code from Figma, as a single React/TypeScript file, along with a helper <Icon /> component.
The icon export process removes all colour from the exported icons, replacing fill and stroke values with currentColor. As such, this process won’t work well for multi-colour icons.
Artworking
The export requires that icons have been artworked correctly, with these requirements:
- Icons must be defined as individual Figma components.
- Icons component names must be named
Icon/{name}, eg.Icon/User - Icons must live in the
⚛️ UI Kitpage
Exporting Process
Open the Plugin
In Figma Design Mode, navigate to ‘Plugins → From ED. → ED. Web Handoff’.
Preview Icons
Select ‘Icons’ from the sidebar. Verify that the icons display correctly.
![]()
Export
Click ‘Code Export’,
![]()
Copy and Paste
Copy and paste the output into your codebase, into a single file. If the icons are adjusted later, you can come back and repeat the process again, overriding the file.
Development
<Icon />
The generated file contains an Icon component. You can use this component like so:
import { Icon, IconClose } from '~/components/atoms/icons'
// Icon colour will inherit text color
<Icon name="plus" />
// Override icon colour
<Icon name="delete" className="text-red" />
// Render an icon directly
<IconClose />Note that in the example above, if icon is undefined, the <Icon /> component will render null.
IconName and IconRef
The IconName and IconRef types can be used for type-safety when creating components that accept icons as props.
Here’s an example of what the Figma plugin generates:
// The `IconName` type is a union of the icon names, lowercased.
export type IconName =
| "close"
| "dot"
| "down"
| "menu"
| "plus"
| "right"
| "circleClose"
| "circleMinus"
| "circlePlus"
// The `IconRef` type accepts either an icon name, or a JSX element like <svg />
export type IconRef = IconName | ReactElementYou can use the IconName like so:
import { type IconName } from '~/components/atoms/icons'
type Props = {
icon?: IconName
label: string
}
export function Button(props: Props) {
return <button>
<Icon name={props.icon} />
{props.label}
</button>
}
// Usage with an icon:
<Button icon="plus" title="Add" />
// Without an icon:
<Button title="Add" />
// ❌ TypeScript error:
<Button icon="jshfkajsdhfahsdf" title="Add" />Alternatively, if your component should also accept icons from other component libraries, or inline-svg, you can use IconRef instead.
import { type IconRef } from '~/components/atoms/icons'
type Props = {
icon?: IconRef
label: string
}
export function Button(props: Props) {
return <button>
<Icon name={props.icon} />
{props.label}
</button>
}
// Usage with an icon name:
<Button icon="plus" title="Add" />
// Usage with an icon component
<Button icon={<IconPlus />} title="Add" />
// Usage with an arbitrary SVG
<Button icon={<svg />} title="Add" />You can also create your own subset of icon names, based on some prefix:
export type CircleIcon = Extract<IconName, `circle${string}`>
// ^ type CircleIcon = "circleClose" | "circleMinus" | "circlePlus"const ICONS
Finally, you can also access the full set of icons using the ICONS variable that is exported.
import { ICONS } from '~/components/atoms/icons'
<select>
{Object.keys(ICONS).map(name => (
<option key={name} value={name}>{name}</option>
))}
</select>Icon Styles
For one of styles, you can just add className to the icon when it’s used.
<Icon name="delete" className="size-6 text-red" />You can also apply global styling to all icons, since an .icon class name is automatically added to every icon rendered with the <Icon /> component:
@layer components {
.icon {
@apply block flex-none aspect-square size-[1.5em];
}
}The example above ensures that icons don’t grow/shrink when used in a flex container, and scale up and down automatically based on font size (which you may or may not want).