Crafting Component API, Together

How to unify anatomy and props across code and design tools

Nathan Curtis
Jul 17 · 8 min read

A design system aspires to achieve a shared vocabulary between designers and developers. As we build visual style and UI components, we make many decisions about how a feature is composed and configured.

  • What is its name?
  • How is each element organized and named in a hierarchy?
  • What options can be configured, and at what level is each exposed?
  • How might smaller parts be modularized to reuse elsewhere?
  • How does this thing interact with other things that call or contain it?

Answers lead to a formal Application Programming Interface (API) to establish how to control how a feature works. During these conversations, practitioners often bemoan “naming is hard.” Backchannel messages evoke emoji like 😩, 🙄, and 😤 . Nevertheless, such decisions, models and conventions are a big part of what makes design systems work.

API has long been the developer’s domain. Yet, if design systems deliver a shared vocabulary across libraries built in and documented for developers and designers, shouldn’t a API be as similar as possible in code and design tools? This is hard when teammates have divergent mental models and distinct mediums that (decreasingly?) constrain them to build differently.

Design tools have long enabled composition and configuration of components in a manner different than code. Designers have tinkered with API in design tools for years, although they haven’t called it API. Their practice has been crude, disconnected. Sketch’s symbol overrides come to mind, forcing odd properties and wacky layers so distinct from how code works. Results weren’t great, only went so far, and enabled a convenient, lazy excuse to avoid trying to improve a shared language. “Why bother,” they’d claim, “if half measures don’t help translate choices efficiently from one tool to another?” I get it, except for the lazy part.

The mood shifts. Design systems are doing much better in sharing an API across design and dev, due in part to rapid advances in design tools. For example, Figma’s Variants opened minds to concretely mirror how code works in designer tools. To realize a shared API, cross-disciplinary teams must identify what to include, when to fit API into a workflow, where to author together, and how behaviors change as a result.

What to include in component API drafts

It’s unrealistic to think an API will be robust, stable and complete before coding starts. However, my experience suggests there’s plenty a team can normalize early. We’ve found success focusing on three topics: anatomy, properties, and layout.

Component anatomy aligned across Figma layers and code markup
Component anatomy aligned across Figma layers and code markup

1. Anatomy

Anatomy establishes the hierarchy of elements and groups that map to web markup, object composition, and Figma layers. Anatomy should also reveal needed subcomponents likely requiring their own properties as well as dependencies on other more atomic things.

CODE MARKUP
-----------
<Card metadata="" title="">
<CardMedia> (extends <Image>)
<CardDescription>
(slot) </CardDescription>
<CardActionsArea>
(slot to add Button, IconButton, or TextLink) </CardActionsArea>
</Card>

For example, a developer sketching a modular Card component may rough out a structure where some elements (such as title) are handled by properties, and other elements (such as CardActionsArea) are composible.

FIGMA LAYERS
------------
Card
]-[ .Card (as Base Figma component)
CardImage (extends Image as subcomponent)
[-] CardContent
]-[ TitleArea
Subtitle
Title
Body
]-[ Actions
Button
Button

On the other hand, a designer mapping an anatomy to Figma layers may outline a similar yet different anatomy. Some intent is Figma specific, such as a “tie fighter” (]-[) or “inset” ([-]) to anticipate auto-layout spacing or prepending a . for a base component or subcomponent.

Yet, these rapid drafts expose divergence both realistic and avoidable. Differences include element names (metadata vs. subtitle, body vs. description), hierarchy (are actions contained by or a sibling of content?), and subcomponents (CardMedia vs. CardImage).

Component properties aligned in Figma Variants and code props
Component properties aligned in Figma Variants and code props

2. Properties

Both developer and design tools should evoke consistent property names, option names, and defaults.

Figma only:- State
- default
- hover? (recommend: include)
- focus? (recommend: include)
- error
- errorHover? (recommend: omit)
- disabled
- readOnly
Both Figma & code:- required (false - default, true)
- inlineLabel (false - default, true)
- helperTextPlacement (right, bottom - default)
Code only:- ariaLabel
- disabled (in Figma, use States)
- error (in Figma, use States)
- errorEvent
- errorText (in Figma, update text shown when in State=Error)
- helperText (in Figma, show/hide and update text)
- id
- label (use .Label element)
- readOnly (false - default, true) (in Figma, use States)
- width

For example, both tools can evoke the same Dropdown properties for inlineLabel (a boolean toggle) and helperTextPlacement (two named options: right or bottom). On the other hand, a coded component may enable some states via properties and other are triggered only via interaction. In that case, it may be desirable to consolidate both property- and interaction-triggered states in a single menu for designers in Figma while sustaining consistent option labels. Finally, it’s very common for code to include (many?) more properties, such as aria-label and id.

3. Layout

While less tangible than anatomy and properties, it’s important to relate those choices to element-by-element width, height, spacing, fluidity, and responsive breakpoints.

Width
- Desktop: 1440px
- Desktop/Tablet: 1024px
- Tablet: 768px
- Mobile: 368px

Admittedly, these notes are less structured and vary considerably across components. It’s been tough to establish a template for drafting them. However, we’ve always found it useful to run through the anatomy, element by element and group by group, to discuss and take notes on how items are contained and fluidly lay out under varying conditions across tools.

When to fit API into a design system workflow

Since 2016, EightShapes has evolved how we deliver features with our clients starting from two core steps: designers deliver Design to developers that Code. The process has expanded over years, adding steps and refining substeps to Plan, Spec (the approved design), Document (design guidelines), produce Design Assets (such as Figma variants) reused by other designers, and Release the feature.

Feature development workflow for visual style and UI components across designers and developers
Feature development workflow for visual style and UI components across designers and developers

A few years ago, we recognized a transitional moment some teams call “The Handoff” when the linear path of “design” diverges to produce many things. This moment sets in motion designer(s) and developer(s) down what can be increasingly isolated tasks in different tools, sometimes across platforms (like web, iOS, and Android). In the design system I currently lead currently, a designer hands off the same design spec to five distinct people that produce outputs in different places! As a result, it’s critical to normalize an API before individuals get too far into production.

For small teams: an activity within task(s)

For some small teams, normalizing an API can be done as one collaborating designer and one collaborating developer sync early in production. We’ve had success assigning this work to a developer to draft a proposal, the whole squad critiques, and the assigned designer speaks to impacts to design tools and documentation.

For simpler workflows where one designer does all design tasks, embed the API moment in the Code task
For simpler workflows where one designer does all design tasks, embed the API moment in the Code task

For many makers and/or outputs: a dedicated, formal task

On the other hand, precede production with a formal API step when handing off to 2+ developers or designers. This task shouldn’t take long, and is done when “producers have discussed shared concerns and agreed on a provisional API direction across outputs.” Sure, some designers or developers may be eager to get started before the API task is done. If so, each must acknowledge refactoring may be needed as consensus on the API comes into focus.

For many participants producing many outputs, consider a quick but dedicated API task
For many participants producing many outputs, consider a quick but dedicated API task

Starting from what exists: evaluate during planning

Starting from an existing catalog like Material UI has become quite a theme (pun intended!). Evaluating an existing API when Planning feature work is essential. Here, the conversation isn’t just to align developer and designer outputs, but also to identify constraints the team must live within or break away from in the adopted library.

Incorporating API analysis as an early planning activity
Incorporating API analysis as an early planning activity

Similarly, another team migrating from Sketch to Figma used a Figma API step to evaluate existing design specs, existing Sketch symbols, and — by far most importantly — code that already exists. Injecting the step enabled each designer to involve developers to review and confirm before building. Was it painstaking? It felt that way at first, but saved considerable time and improved alignment as the team canvased the catalog.

Incorporating Figma API planning to synthesize disparate inputs prior to migrating from Sketch
Incorporating Figma API planning to synthesize disparate inputs prior to migrating from Sketch

Where to draft an API

The developer assigned to code a component often takes the first pass at an API. On the other hand, I’m an architect by trade and find myself constantly drafting API and coaching industrious front-end aware designers to do the same. No matter who starts the exercise, an API draft should be:

…composed in a visible tool. The draft must be findable and editable by everyone. For some teams, Google Docs or Office365 suffices. Other teams favor Jira or Asana. Discipline-specific tools — a code file or a Figma page—have proven less cross-functionally inclusive.

A Card component API draft proposal, as prepared by a developer for team review in Google Docs
A Card component API draft proposal, as prepared by a developer for team review in Google Docs

started from a template. Includes familiar structure, implies conventions (such as how to list property options), and embed hints.

API Draft Template made in the Asana task management app for a from-Sketch migration
API Draft Template made in the Asana task management app for a from-Sketch migration
API Draft Template made in the Asana task management app for a from-Sketch migration

…critiqued as a group. Once drafted, it’s healthy to critique an API as a multi-disciplinary team. Conversations last anywhere from 15 minutes to an hour per component, based on complexity. Expect to work through a few sessions before team members get the hang of it.

…available for asynchronous review. Not everyone attends every discussion, yet every downstream assignee should an opportunity to comment on a proposed API. For features serving a wide shared need, a core team may also invite the design and/or development community to review, often via a request for comments via Slack or Teams.

Epilogue: How crafting API changes behaviors

Teams using this approach gradually acclimate to composing an API together. Divergence does occur as teams learn by making. Teams effectively aligning API across outputs exhibit behaviors like:

  1. Developers invite designers to collaborate on properties and anatomy, rather than gatekeeping something historically their domain.
  2. Design specs drift toward API constructs, with sections of Anatomy and “Variants” (organizing some properties) grounding handoff.
  3. Developers and designers naturally connect as outputs evolve. Coding reveals technical constraints. Design spec deficiencies arise. Designers in Figma hit walls that can’t quite mimic how code works. Let’s talk about it.

This reinforces the reality that drafting API early isn’t (just) to minimize divergence. It’s also to anchor collaborative expectations and behaviors between designers and developers via a shared starting point. Happy APIing, you lovely cross-functional teams!

EightShapes

A collection of stories, studies, and deep thinking from…