Building Workbench

How we created the Timeline component

Josh Cusick
Gusto Design
15 min readJul 12, 2022

--

UI elements inside of Figma

Thanks to Jordan, Eric, Daniel, Lise, Juliann, and Amy for the help with this article.

The Design Systems team at Gusto has been working hard over the past three years to provide designers and engineers with a robust, extensive, and accessible design system called Workbench. But it wasn’t always this way.

A few years back there was a grassroots effort to deliver a more cohesive experience at scale in Gusto’s product. This manifested a component library that lived inside of Storybook.

The library was created to centralize existing components built for specific business needs and scenarios but it came with some tradeoffs. Components were shipped faster but were less modular and compositional. They solved immediate problems but were less flexible.

Gusto’s growth since the inception of our component library has introduced needs that its components cannot easily remedy.

These needs are addressed by investigating, evaluating, and validating how a new Workbench component can solve our customers’ evolving use cases. One of the components that needed to be rebuilt was our <StepList /> component.

The step list component inside of the Storybook preview website
Screenshot of the <StepList /> component inside Storybook

Building a component for a design system can be quite a tedious task. At Gusto, we follow a highly-collaborative, end-to-end component design process. This process continues to evolve, but for this component here were the steps:

  1. Project scoping
  2. Component research and auditing
  3. API/design explorations and reviews
  4. Accessibility research
  5. Design and engineering specs
  6. The Figma component build
  7. The React component build
  8. Usage guidelines and documentation
  9. Final checks and ship

This article covers how my team and I collaborated to build the <Timeline /> component which was born from <StepList />. I’d like to say a special thanks to Jordan Cutler (my engineering counterpart) and Juliann Wheeler (my manager) for working with me on this project.

The Timeline component usage documentation on the Workbench website
Our new <Timeline /> component in Workbench

Project scoping

The first phase of building a component requires that we understand as much of the problem as possible. The <StepList /> is basically an <ol> with <li>s. At Gusto, this component is commonly used to visualize the status of tasks.

A designer’s mock up of the step list component inside of Figma
Example of the <StepList /> in a tax registration flow from Jonathan Tran

Migrating a component from an old system to a new one provides a great opportunity to redesign that component and refactor its code.

We first need to understand any current or new use cases for said component. We solve this by auditing our app and conducting an exercise based on our customers and their needs.

Here are the findings from our exercise for <StepList />:

Customer journey and scenarios

When will the customer interact with this component?

  • On the app’s landing page.
  • Setting expectations within a new feature or process in the product.

Goals

What is the customer trying to accomplish with this component?

  • They want to see how many steps they need to finish a task.
  • They want to track the progress of a task and report it to someone.
  • They want to know how long a task will take.
  • They want to know if a step is required or optional.
  • They want to know the status of individual steps.
  • They want to know if they can assign a step to someone.
  • They want to be notified by Gusto when a step is completed either in-app or out-of-app.
  • They want to notify the admin of their organization of the status of individual steps.

Motivations

What is motivating the customer to use this component?

  • They need to complete a task.
  • They want to get paid or pay employees.
  • They want to be in compliance with state and federal law and Gusto.

Mindset

What headspace is the customer in while using this component?

  • They might feel overwhelmed with new information.
  • They might feel confident when they see all the steps laid out in front of them.
  • They might feel unsure that they have all the necessary documents or information to complete the steps.

This part is especially important because when a customer is stressed or overwhelmed, they may have trouble processing a lot of information. We need to simplify potentially stressful experiences as much as possible, while still ensuring we cover all use cases.

Research and auditing

At this point, we had a good understanding of what problems this component could solve. I next turned outwards to see how other design systems are building similar components.

I always want to ensure that we follow the best practices and build something ergonomic and familiar to designers and engineers. I do this by auditing around a dozen similar components’ APIs. This helps me to make recommendations and design decisions.

The term API is an acronym, and it stands for “application programming interface.”

“Think of an API like a menu in a restaurant. The menu provides a list of dishes you can order, along with a description of each dish. When you specify what menu items you want, the restaurant’s kitchen does the work and provides you with some finished dishes. You don’t know exactly how the restaurant prepares that food, and you don’t really need to.”

-Howtogeek.com

A Google spreadsheet of multiple component APIs
The audit of 12 APIs for my research

Here are the APIs I looked at with Jordan:

  1. Ant Design
  2. Elastic UI
  3. Base Web
  4. Lighting Design System for React
  5. Colloid Design System
  6. MUI
  7. Orbit
  8. Duet Design System
  9. Spark Design System
  10. Carbon Design System
  11. KendoReact

I also included our old <StepList /> component and Jordan and I found a few accessibility issues to address.

After my audit was complete, I felt confident about what to propose for the component’s features. I also realized that we should probably call our component <Timeline /> and its children <TimelineStep /> s versus <StepList /> and <Step />. Normally I like to use a more common name, but our use cases heavily influenced the name change since time was a prominent factor in this component.

API/design explorations and reviews

This step is where the real fun begins. At this stage, we know where and how this component will be used, and how other design systems have built similar components.

Loaded with all this information, I started some design explorations in Figma and eventually built a prototype in CodeSandbox.

Some designers like to build prototypes in Figma or a similar tool, but I prefer to code where possible. This helps me to better understand any technical constraints and continue to grow my technical skillset.

Along with my prototype, I leaned on Jordan’s expertise to flesh out the API and code.

The initial API (in TypeScript) looked something like this:

interface TimelineStepProps {
children?: React.ReactNode;
status?: "inactive" | "active" | "partial" | "success";
title?: string;
subtitle?: string;
}
A coded prototype inside of CodeSandbox
The prototype that I built in Codesandbox

We use the composition model when it comes to constructing our components, leaving control up to the consumers. This results in minimal enforcement of our components and heavy reliance on guidance in our documentation. It also minimizes the number of props on the component.

So the above API (in TypeScipt) turned into:

interface TimelineStepProps {
children?: React.ReactNode;
status?: "inactive" | "active" | "partial" | "success"
̶t̶i̶t̶l̶e̶?̶:̶ ̶s̶t̶r̶i̶n̶g̶;̶
s̶u̶b̶t̶i̶t̶l̶e̶?̶:̶ ̶s̶t̶r̶i̶n̶g̶;̶
}

There really was no need to define title or subtile properties since we have a <Heading /> component that gives our consumers the flexibility to define the heading level with a level prop and font-size with a typePreset prop. This means that instead of constructing our <TimelineStep /> like this:

<li>
<h3>
<div>{title}</div>
<div>{subtitle}</div>
</h3>
{children}
</li>

we’d construct it like this:

<li>
{children}
</li>

and our consumers could compose like this:

<TimelineStep>
<Heading level={3}>
<HeadingText>Step title</HeadingText>
<HeadingSubtext>Step subtitle</HeadingSubtext>
</Heading>
{/* additional content goes here */}
</TimelineStep>

Again, less restrictive and more flexible.

Once I had some artifacts to show, I did a few reviews with product designers that I knew were going to use this component. They provided great feedback and context for us to leverage.

Accessibility research

If you want your digital experiences to be accessible, you have to do the work to produce accessible components.

Accessibility is always at the forefront when creating components. But we really dig deep while building and writing documentation. We lean heavily on W3C when making design and engineering decisions for our components. We also do accessibility testing including using screen readers on our components before shipping them.

Here are some of the accessibility considerations for <Timeline />:

  • The icon and its background meet the minimum requirements of a 3:1 contrast ratio for non-text content.
  • It is not recommended to skip steps or move in a non-linear direction. Each step’s status should be set to success before moving to the next step.
  • An h2 is recommended to describe what task the Timeline is outlining.
  • The Timeline implements an <ol> and the Timeline Step implements an <li>.
  • This component uses visuallyHidden text (and not aria-current) to announce to the screen reader the status of the step.
  • Wrap dates and times in a <time> element with an appropriate datetime.

Curious about our sources? Take a peek:

  1. W3C: Understanding Success Criterion 1.4.11: Non-text Contrast
  2. W3C: H48: Using ol, ul and dl for lists or groups of links
  3. W3C: Understanding Success Criterion 1.3.2: Meaningful Sequence
  4. W3C: Accessible Rich Internet Applications (WAI-ARIA) 1.1: Aria Current
  5. W3C: Labeling Controls: Note on hiding elements
  6. WebAIM: CSS in Action: Invisible Content Just for Screen Reader Users
  7. Go Make Things: Revisiting aria-label versus a visually hidden class
  8. MDN Web Docs: <time>: The (Date) Time element

Design and engineering specs

After a few feedback loops and reviews with product designers and my team, I created a design spec. This document contains a component blueprint and best practices. The design spec is the handoff artifact that I provide our engineers. They use it to build the component and populate our documentation site.

The Timeline design spec inside of Figma
The design spec for <Timeline /> inside of Figma

Working through this documentation helps us to flush out all the details and semantics before the final build. The design spec covers:

  1. Anatomy and component blueprint (sizing, padding, margins, etc.)
  2. Design tokens
  3. Best practices and examples
  4. Customer problems the component should solve

Alongside my design spec, Jordan built out his engineering spec. The eng spec covers:

  1. Semantic tags
  2. DOM (Document Object Modal)
  3. API
  4. Slots and composable areas
  5. Auxiliary components and props
  6. How might an engineer might use it
  7. Known use cases
  8. CSS considerations
  9. Accessibility factors
  10. Interactivity

The Figma component build

We now are ready to construct our component. Jordan went to work on his final build in React and I built the component inside of Figma.

As I mentioned earlier, we like to leverage composition with our components, but we are more opinionated regarding our Figma components. We do this for ease of use, convenience, and guidance.

To be more designer-centric in Figma, we opt to use title casing for our component and prop names, separate compound words, and omit brackets. So in code, we would write <Timeline /> and <TimelineStep />and in Figma, we’d just write Timeline and Timeline Step.

Let’s review Timelineand Timeline Step inside of Figma:

Hovering over the Timeline component inside of Figma. The tooltip reads, “Timeline is a group of steps in a prescribed order with statuses that reflect progress. Adjustable subcomponents: Timeline Step.”
What a designer sees when searching “timeline” inside of Figma’s asset pannel

Out-of-the-box, Timeline handles some logic and lets the user define a step count from 3 to 10.

The API for Timeline inside of Figma
The Figma API for Timeline

In the image below, the left side is what Timeline looks like once dragged onto a designer’s canvas in Figma, and on the right is how an engineer might compose it in code.

A design and code example of Timeline
(From left) the Timeline inside of Figma and how it could be composed in code

If a designer needs more than 10 or less than 3 steps (which is not recommended) — they can import the Timeline Step component and compose their own Timeline.

Hovering over the Timeline Step component inside of Figma. The tooltip reads, “Adjustable subcomponents: Heading, Placeholder Box, Button, Link, Tag.”
What a designer sees when searching “timeline” inside of Figma’s asset pannel

The Timeline Step in Figma is quite a bit more configurable than Timeline. I try to anticipate all the common use cases for a component and enforce guidance through props.

Let’s break down the API:

The API for Timeline Step inside of Figma
The Figma API for Timeline Step

The Action prop

I always sort the props in Figma from A-Z. So let’s start with Action.

The Action prop is a boolean that adds either a Button or a Link depending on what the Status is defined as.

The API for Timeline Step inside of Figma. The Action prop is highlighted.
The Action prop inside of Figma

To maintain our action hierarchy, we only recommend rendering a single primary button in Timeline at a time. Designers don’t have to worry about which style to select since the type of action will change for them in Figma when they configure the Status prop.

Examples of Timeline Step inside of Figma
Examples of Timeline Step inside of Figma with different actions

If Action is true and:

  • If Status="Inactive" then no Buttonor Linkis rendered.
  • Or if Status="Active" then a primary Button is rendered.
  • Or if Status="Partial" then a primary Button is rendered.
  • Or if Status="Success" then a Link is rendered.

Keep in mind, in code, these actions would either be links styled as buttons or vice versa depending on if the user is completing something on the page or being taken to a new page.

The Placeholder prop

My workaround for children in Figma is to pass in a prop called Placeholder which acts as a catch-all.

The API for Timeline Step inside of Figma. The Placeholder prop is highlighted.
The Placeholder prop in Figma

We don’t want designers to “break” components inside Figma. Doing so would result in not being in sync with the Design System and its updates. When Placeholder is true a component called Placeholder Box is rendered and all content is cleared except for the Headingcomponent. This allows designers to swap in a local component.

A GIF of swapping out the Placeholder Box component for a local component inside of Figma
An example of swapping out the Placeholder Box component for a local component inside of Figma

The Status prop

In addition to determining what type of action to render, the Status prop handles the styling of the circle and line next to the step’s content.

The API for Timeline Step inside of Figma. The Status prop is highlighted.
The Status prop in Figma
  • If Status="Inactive" the border-color of the circle is $salt-700, the background-color of the circle is $salt-100, the line’s border-style is dashed, and the line’s border-color is $salt-700.
  • If Status="Active" the border-color of the circle changes to $kale-800.
  • If Status="Partial" a half circle with the background-color of $kale-800 is rendered inside of the circle and the border-color of the circle changes to $kale-800.
  • If Status="Success" the background-color of the circle changes to $kale-800, the line’s border-style changes to solid, the line’s border-color changes to $kale-800 and the Check icon is rendered inside the circle with a color of $salt-100. If the step is the last step, there is no line.
Examples of Timeline Step inside of Figma
Examples of Timeline Step inside of Figma with different states

The Step Order prop

The Step Order prop is only relevant in the edge cases where a designer needs more than 10 steps but less than 2. This prop handles the styling and conditional rendering of the line next to the step’s content.

The API for Timeline Step inside of Figma. The Step Order prop is highlighted.
The Step Order prop in Figma
  • If Step Order="First" a line is only rendered below the circle
  • If Step Order="Middle" a line is rendered both above and below the circle.
  • If Step Order="Last" a line is only rendered above the circle and the padding-bottom of the step’s content is set to 0px.
Examples of Timeline Step inside of Figma with different orders

In reality, we would not provide a prop for this case in code, rather, in our Timeline.css we could write something like this:

/* hides line on last step */
li:nth-last-child(1) .timeline-step_progress-line {
display: none;
}
/* removes padding from bottom on last step */
li:nth-last-child(1) .timeline-step_content {
padding-bottom: 0;
}

The Tag prop

The Tag prop is a boolean that adds a Tag.

The API for Timeline Step inside of Figma. The Tag prop is highlighted.
The Tag prop in Figma

The name of this prop initially came from our <CardHeader /> component where we have a predefined slot for a <Tag /> or multiple <Tag />s called tags. In code, we would pass <Tag /> or multiple <Tag />s to <CardHeader /> like:

<Card>
<CardHeader
illustration={<PalmTree />}
tags={<Tag variant="filled">New</Tag>}
<Heading level={3}>Location tools</Heading>
</CardHeader>
<CardBody>
{...}
</CardBody>
<CardFooter>
{...}
</CardFooter>
</Card>

Which would render:

Card component example using the Tag component
<Card /> example using a <Tag />

I only identified the need for a single Tag in Figma so I stuck with the name Tag for the prop.

A composed Timeline example in Figma
Examples of Timeline inside of Figma with a tag inside the first step

In code, we’d simply pass a <Tag /> into the children slot, but it helps our designers to provide them with this option.

The React component build

The title of this step is a bit deceptive since prototyping is done earlier to determine how feasible the designs are. So, by this stage, Jordan had already built his own <Timeline /> prototype and he went to work on finalizing the build. In this final build, he ensured that:

  • The API was consistent and aligned with developer expectations.
  • The component met or exceeded WCAG 2.1 AA standards.
  • Competitive research was leveraged.

Usage guidelines and final documentation

Our documentation aims to provide clear guidance on component usage, accessibility, and implementation. We combine the design and engineering specs as well as add some additional context such as accessibility notes and resources. Once we are confident with a working draft, we share out with the broader design systems team for review. After collecting feedback and making changes, our documentation is ready.

The accessibility section of the Timeline documentation inside of the Workbench website
The accessibility section on the <Timeline /> page in Workbench

Final checks and shipping

Before we ship the component in Figma and code, we perform final checks.

Inside of Figma, we check for:

  • Consistent layer names
  • Consistent prop names and prop orders
  • Typos
  • Variant testing
  • Propper layout
  • Responsiveness
  • Common use cases
  • Customization

The lead engineer on the component will perform extensive accessibility and performance testing including:

Depending on the component some of the following may not apply.

  • Screenreader testing across browsers.
  • Responsiveness and reflow testing across browsers.
  • Checking and confirming the accessibility attributes such as the name, description, and role.
  • Creating examples of how a consumer would consume the component.
  • Testing any animations, and creating interactive examples.
  • Checking the different variation combinations. Testing the happy, unhappy, and very happy paths.
  • If the component is using a flex or grid layout ensuring it behaves appropriately when scaling.
  • Testing different types of content and the content overflow.
  • Testing error states.
  • Testing mouse and keyboard interactions e.g. hover, focus, disabled, etc.
  • Testing on a mobile device e.g iPhone or Android.
  • Testing voice control.

Ready to ship

Now that we have our Figma component, coded component, and documentation, we release. It’s important to let our designers and engineers know when new components are available, so we will publish this news in a Slack channel, inside of the Figma release notes, and in our newsletter.

<Timeline /> replacing <StepList /> in the previously mentioned tax registration flow from Jonathan Tran

Final thoughts

If you have made it this far in the article, thank you! We appreciate you taking the time to learn about our work. While we have a well-defined process, we know that we can always improve and are ever-evolving.

Stay tuned for updates by following this publication on Medium and show your support by clicking the 👏 “clap” button and leaving a comment!

Sources

  1. Ferdinandi, C. (2020, July 21). Revisiting aria-label versus a visually hidden class. Go Make Things. Retrieved July 7, 2022, from https://gomakethings.com/revisting-aria-label-versus-a-visually-hidden-class/
  2. Hoffman, C., & Duino, J. (2021, August 12). What is an API, and how do developers use them? What Is an API, and How Do Developers Use Them? Retrieved July 7, 2022, from https://www.howtogeek.com/343877/what-is-an-api/
  3. Meta Platforms, Inc. (n.d.). Composition vs inheritance. React. Retrieved July 7, 2022, from https://reactjs.org/docs/composition-vs-inheritance.html
  4. Perrier, J.-Y., et al. (2022, May 20). CSS Grid Layout — CSS: Cascading Style Sheets: MDN. CSS: Cascading Style Sheets | MDN. Retrieved July 11, 2022, from https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout
  5. Perrier, J.-Y., et al. (2022, May 27). CSS flexible box layout — CSS: Cascading style sheets: MDN. CSS: Cascading Style Sheets | MDN. Retrieved July 11, 2022, from https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout
  6. Perrier, J.-Y., et al. (2022, May 27). Introduction to the DOM — web apis: MDN. Web APIs | MDN. Retrieved July 7, 2022, from https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction
  7. W3C. (n.d.). Accessible Rich Internet Applications (WAI-ARIA) 1.1. Web Accessibility Initiative (WAI). Retrieved July 7, 2022, from https://www.w3.org/TR/2017/REC-wai-aria-1.1-20171214/#aria-current
  8. W3C. (n.d.). H48: Using OL, UL and DL for lists or groups of links. Web Accessibility Initiative (WAI). Retrieved July 7, 2022, from https://www.w3.org/TR/WCAG20-TECHS/H48.html
  9. W3C. (n.d.). Labeling controls. Web Accessibility Initiative (WAI). Retrieved July 7, 2022, from https://www.w3.org/WAI/tutorials/forms/labels/#note-on-hiding-elements
  10. W3C. (n.d.). Understanding Success Criterion 1.3.2: Meaningful Sequence. Web Accessibility Initiative (WAI). Retrieved July 7, 2022, from https://www.w3.org/WAI/WCAG21/Understanding/meaningful-sequence
  11. W3C. (n.d.). Understanding Success Criterion 1.4.10: Reflow. Understanding success criterion 1.4.10: Reflow. Retrieved July 7, 2022, from https://www.w3.org/WAI/WCAG21/Understanding/reflow.html
  12. W3C. (n.d.). Understanding Success Criterion 1.4.11: Non-text Contrast. Web Accessibility Initiative (WAI). Retrieved July 7, 2022, from https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html
  13. W3C. (n.d.). Web content accessibility guidelines (WCAG) 2.1. W3C. Retrieved July 12, 2022, from https://www.w3.org/TR/WCAG21/
  14. WebAIM. (n.d.). CSS in Action Invisible Content Just for Screen Reader Users. WebAIM. Retrieved July 7, 2022, from https://webaim.org/techniques/css/invisiblecontent/
  15. Wilhelm, A. (2021, June 30). Gusto is now offering pieces of its service to other companies via API. TechCrunch. Retrieved July 11, 2022, from https://techcrunch.com/2021/06/30/2171608/
  16. Xue, F. (2022, March 4). : The (date) time element — HTML: Hypertext markup language: MDN. MDN Web Docs. Retrieved July 7, 2022, from https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time
  17. YouTube. (2018). React already did that — Developer ergonomics in 2018 — Dylan Schiemann — JSConf Us 2018. YouTube. Retrieved July 7, 2022, from https://www.youtube.com/watch?v=lHRuIA7cyU0&t=489s.

--

--

Josh Cusick
Gusto Design

Design systems are my thing. Prev Gusto & Microsoft