(Forge) Bridge over troubled water

John Price
Harry's Engineering
7 min readJun 14, 2022
Photo by Chris Becker on Unsplash

When we used to think about the process of going from digital design to a fully functional webpage, the word “handoff” frequently came up. The handoff was when a digital designer gave her complete, fully annotated, never-changing, pixel accurate website design to a front-end developer who would recreate her precise design in code.

Just as automobile designers carefully crafted their creations in clay before handing them off to engineers who had to figure out how to build it, web designers and web developers frequently crafted their work in two distinct worlds with a “handoff” being the only connection between the two. A fragile connection due to very little HTML and CSS standards between browsers; handoff was never a one-time thing and often became a laborious task of iteration and compromise resulting in CSS hacks and workarounds.

Applications like Adobe Dreamweaver were created to help designers use a WYSIWYG (What You See Is What You Get) editor to build and export their designs to HTML files. The results of these design-to-code tools have been hit and miss at best. Some would export using inline CSS and others still stuck to tables for layout. Either way the resulting HTML was very difficult to maintain, especially when browsers were updated and introduced more inconsistencies.

Much has changed since those days. Tools, technologies and workflows have evolved significantly; enabling front-end developers and designers to work much more collaboratively. The ubiquity of mobile internet and the the introduction of HTML5 created standards that established foundations for a consistent language shared by both developers and designers. Later, the rise of component-based UI development shifted our approach and enabled the two disciplines to truly work together to produce design systems and component libraries which can function as scalable, reusable web page building blocks and make handoff a thing of the past.

So how can design and engineering communicate more efficiently to enable rapid development of frontend components?

At Harry’s we wanted to extend this “shared language” of design and code components that helped put handoff in the rear view mirror. Starting with our brand-agnostic library of React components known as “Forge UI”. This consists of many of the common components used across all of our brand websites like Buttons, Badges and Tabs. Because they are brand-agnostic they are un-opinionated on how they are styled and displayed to the user, but they check all the best-practices-boxes: they’re accessible, secure and functional. These components get their styles from a “ThemeProvider” wrapping around the entire page.

<ThemeProvider theme={$theme}>
...
<ForgeButton>Click me</ForgeButton>
...
</ThemeProvider>

Based on the theme passed to the ThemeProvider, the button could have Harry’s branding, Flamingo branding, or something else entirely (including branding for products we haven’t invented yet!).

The color picker component styled in three different themes. This component allows the designer to specify whether the color label should be displayed, the type style and color, the padding between the label and the color targets, the spacing between the colors, the color chip height and width, the color and width of the “selected state” indicator, and the radius of the color chip (square, round or anything in between). Even space between the color and selected state outline can be specified!

Where does the brand theme come from?

The design team specifies styles and properties in a Figma-based “Brand Starter Kit”, which includes all of the designs for each component and all of their respective variants. Variants are an awesome way for a brand to have multiple styles of a single component (think “Primary” button, “Secondary” button, etc.). A designer can change how an accordion component looks on different pages just by using different variants (for example, one variant may have a grey background which opens with an icon on the top left, while another may use an off-white background which opens using an icon on the top right).

In the “old days” this theme data may have been painstakingly created by an engineer who pored over design specs, creating component property values based on what they’re deriving from a designer’s “specs”. At Harry’s, the designer creates the theme directly from within Figma using our very own Figma plugin known as Forge Bridge. Apart from defining style values and token names for color, typography, and drop shadows, each component in the Starter Kit has clearly defined properties so the designer knows what attributes can be changed. When the designer gets all the styles and component variant properties set the way they want, they simply run the Forge Bridge plugin, which exports a theme file that’s structured like this:

{
colors: { map of available colors and ranges },
typography: { available typographic styles },
components: {
button: {
variants: {
'default': {
backgroundColor: 'rgba(0,0,0,0.5)',
...other properties...
}
}
}
}
...other component definitions...
}

Because it’s generated by the designer in the Figma file itself, there’s no ambiguity associated with color or typographic values. Even all the icons (and their colors!) are defined in the design file and exported with Forge Bridge. The theme file is also a TypeScript file, which makes it easy for engineers to use a Forge UI component due to code completion, type safety and the ability to only use known variants, icons, colors and typography.

How are the variants specified?

When building a new component for the plugin, the design and engineering teams decide what style properties can be changed between variants. A component definition is created within the theme provider package detailing the properties and we run a script to generate typings for the plugin to pick up.

{
displayName: 'MyNewComponent',
properties: {
state: ['normal', 'disabled'],
},
styles: {
typography: {
displayName: 'Typography',
get: STYLE_NAMES.TYPOGRAPHY,
},
backgroundColor: {
displayName: 'Background Color',
get: STYLE_NAMES.FILL,
}
}
}

When we next run the plugin in development it will pick up our new component as a type, which can be assigned to a Figma node. Because we specified the properties that can be changed by selecting a specific variant, we can link the styles to the selected Figma element. Typography includes the font style, letter spacing, colors and line heights.

The Forge Bridge plugin showing properties that can be changed for the button component

A designer can specify these properties for every variant of a component within Figma, or make use of inheritance. Inheritance is really useful when a lot of the properties are the same across several component variants with only one or two differences. For example, a button might have a different background color, but properties like padding and corner radius might be the same across all of them. Inheritance makes it very easy for a designer to make changes to a component that all inherited components will also receive.

The blue areas represent “inherited” properties, while the orange is an override for the selected variant

Having a library of UI components with clearly delineated, editable properties makes updating styles or creating new variants incredibly easy, and it can all be done in Figma. Need a new blue call-to-action button for a hero module? No problem: the designer can just create a new button variant style in Figma, run the plugin, give the new theme file to update the codebase and BOOM — done. Need to change that blue color defined as Primary/1 to a different shade that passes AAA accessibility? The designer just needs to change the color value assigned to the name “Primary/1”, and the exported theme file will change all instances of Primary/1 to the new color.

While Forge Bridge makes style and component updates a breeze, it really shines when used in the service of creating a new brand from scratch. Once all the color and typography is defined and the components are styled, the designer and developer have a library of branded components that can be used in both design layouts and in code.

So what has this solved?

By working together to define the styling properties, designers and engineers develop a common language for describing a component’s parts. Typically teams have different words for the same thing; are the words near a text box a “Label” or a “Hint”? Is the component we are working on called a “Hero”, a “Module”, “Banner” or even a “Full width image”? By creating components and defining properties collaboratively, the shared language adds value well beyond the process of creating the component itself.

Forge Bridge (and the processes it engenders) also makes it easier for our cross-geo brands to use single React components that use distinct themes to manage their stylistic and property differences. For example, in our Harry’s North America site we have buttons that have different styling from our International site. If we wanted to make the styles the same — and as long as they are both using the Forge UI component under-the-hood — the only engineering work required would be to update the theme file.

Forge UI and Forge Bridge also make it easy for engineers to keep their component versions up to date. In an older library we have components versioned independently, meaning that we could be using v1.3 of a button component, alongside v2.5 of an accordion component. Keeping track of these different versions can be tricky — especially when you have over 15 different components! To solve this, our Forge UI components are in a separate Lerna-managed repo which keeps all versions in sync. So if you are using v1.11 of the theme provider, and you upgrade to v1.12, then you simply need to upgrade your components to v1.12 as well.

The Forge Bridge plugin is still in active development, but it’s enabled us to create new, performant components that can be quickly styled and easily integrated into the web experiences of our existing brands. The library consists of scores of components, from breadcrumbs to quantity pickers to star ratings. While we continually add additional components to the library, we also have big plans for the future that extend beyond atomic-level components. This includes integration with our CMS platform, managing full-page layouts, and lots of general performance improvements. Stay tuned!

--

--