Hi, my name is Kathleen McMahon and I’m here today to tell you how Gatsby and MDX makes component library documentation… smoothly inclusive Before we begin, let’s get some details out of the way

My slide deck will be posted on Notist, including links to resources I briefly touch upon. The full URL will be available later today on Twitter.

You can follow me at. Resource11 on Twitter, Instagram, and GitHub.
Before we dig into Gatsby and MDX, let’s back up so I can introduce myself better…

I’m a Principal Engineer at CarGurus

And I race bikes… very badly.

Mostly you’ll see me in costume, racing two laps to your six, at the back of the pack, on a singlespeed. Mostly. Unless something happens.

Like… a pandemic kicking in our doors. Then your racing season is postponed.

So while I’m an engineer, and a super slow bike racer…

…I’m a super fan of design systems — especially the component library parts!

Before working for CarGurus, I was the Tech Lead for O’Reilly Media’s design system.

While I was there, I learned a lot about streamlining component libraries, and optimizing documentation.

If you’ve never worked on a design system, let’s just say… There are a lot of moving parts.

And if your core team is small — and you’re rebooting your component library — you really have to choose your focus. And… rely on your contributors.

In our case, our focus was business logic out, accessibility in. We fixed our colors, our components, our patterns, and rebooted our docs.

Once that was done, we realized that a part of our system was becoming a hindrance for our team, and a barrier to entry for our contributors: our documentation.

Our process was spread across two projects: the design-system repo, and the design-system-docs repo.

In the design-system repo, the documentation content was stored…

…in two locations.

While the docs repo held the site scaffolding…

…and docs layout components.

To get up and running, you had to follow a detailed series of steps to sync, run scripts, grab files, parse information, generate data, and render the docs to a React app. Phew!

Just getting starting working with these repos was overwhelming for new contributors to say the least…

But wait there’s more!

The scripts were set up in such a way that you had to write your Markdown in a very specific order for your content to show up in the docs.

Your Button heading could be paired with an intro paragraph, but only one paragraph.

Same with your variants. Only one paragraph, and then a code block.

Best practices had to be written as an unordered list. Always.

Same with the Related components section. Always an unordered list.

So while our docs scripts were great for of generating color swatches and details about which props were available in components…

The process was not great for creating our component documentation.

Which frustrated everyone.

One mistake, and parts if not whole chunks of documentation would be missing on the component pages. We had the freedom of using markdown, yet weren’t taking advantage of it.

This was a serious cognitive lift, even for someone who is very familiar with the codebase

Now imagine if you have a new contributor to your project…? Not exactly a welcoming experience.

We decided to review our process and see what wasn’t working.

One of our biggest issues: we chose to show one component variant at a time, rather than all at once.

This forced users to access a select menu over and over to compare variants, which increased the time they needed to look up information. It didn’t make sense.

In retrospect, that decision was about as questionable as a recipe that combines Jello with shellfish

We decided that it was time to make our docs contribution process more user friendly, in terms of the structure, and how we authored.

Especially the component example pages. We wanted the users to have confidence that whatever content they wrote in a docs page

…would make it into that docs page.

If we made our docs more user friendly, we’d have more contributors rather than fewer.

We considered our options for making our docs better, and decided upon Gatsby for a few reasons.

Gatsby gave us a way to migrate all our main documentation pages right into the site without much fuss.

Gatsby provides a Webpack and Babel config similar to create-react-app, so we could start with a scaffolded project, and extend as needed. And…

Gatsby supports MDX, so we could write component documentation using Markdown, import React components right in the file, and it just works. Even better, MDX compiles down into…

Semantic HTML. Which in turn, gives the site…

Improved accessibility. Better support for users that rely on assistive technology to access the docs.

If a design system is promoting inclusivity in general — and it really should — it follows that inclusive docs makes sense.

As a bonus, with Gatsby we streamlined our setup from two repos to one, and…

Reduced the amount of CLI commands

Dramatically.

The default setup for Gatsby is great, however, we needed to make some adjustments so Gatsby worked for our needs.

In the gatsby-config file…

we added gatsby-plugin-postcss to support PostCSS…

gatsby-plugin-compile-es6-packages to support our design system package…

gatsby-plugin-mdx, so the site would recognize MDX files.

gatsby-remark-autolink-headers, to generate auto links for page headings for better screen reader and keyboard support…

gatsby-plugin-page-creator to create pages from the src/pages folder…

And gatsby-plugin-filesystem so we could pull in our data file, and…

…point Gatsby to the folder where all our component MDX files lived.

In the gatsby-node file…

we added a GraphQL query to find the component MDX content

And a createPage action to generate routes and pages for the component docs.

In the gatsby-browser file…

…we added things we wanted to apply throughout the site, like our global CSS styles and the wrap-root-element component.

The wrap-root-element component acts as a wrapper around the site’s root element…

…And imports MDXProvider. This way, the entire site would recognize MDX content.

We had to do one extra thing for our component docs page template, though.

Since our component MDX files were located outside of the src/pages folder, MDXRenderer needed to wrap the contents of our component page template. Otherwise, the MDXs file would render…

…like this in the browser.

Now that our layout template used MDXRenderer, our component MDX pages…

…would render as we want in the browser.

Now we could pop in React components next to the code blocks…

…And they would render, no problem.

We could even wrap a Button component with a DisplayBox component

And add a more cohesive look to the component/code block pairing

If we wanted to add a props table to show which props can be used with the component…

…and created a component that pulled in data to render as a table component…

…Popped that component into the docs MDX file, passed in the name of the component to render…

Voila! The docs would show a props table.

For the component Dos and Don’ts…

We used to have to write out an unordered list in the Markdown file.

And the list rendered like this.

With MDX support, we instead created a custom component that renders unordered lists.

We could pass in a dosList and a dontsList array into the component…

…and BOOM. A nicely-styled dos/don’ts list.

Code blocks. Markdown has great code block support. MDX makes those even more powerful, so we were psyched to add this feature.

You can override the styling of a code block in an MDX file with a custom code block, or even display different types of code blocks.

You can use prism-react-renderer in a custom CodeBlock component and import a theme with good color contrast…

…wrap your code block and theme it…

…Import that into your wrap-root-element along with the preToCodeBlock util…

…And override the default pre styling at the app level by passing it in as a component to the wrapRootElement.

So now when you write a code block in MDX…

Instead of the baseline styling…

…the custom code block will render with syntax highlighting.

Fun fact: you can pass in a prop to that code block and do really cool things if you use custom code blocks!

For example, if you abstract this MDX into a DRYer pattern into our custom CodeBlock component…

… and pass the displaybox prop into the CodeBlock…

If you add the displaybox prop to the code block in MDX…

You’ll get a display box paired with a code block.

What about if you want your code block to be an editable code block?

You can add a react-live option in the component.

…and show component inside a displayBox pairing with an editable code block…

… so if you add the react-live prop to your MDX code block…

…You’ll get an editable block, and see your changes in real time.

… So if we write something like this… this is what you see in the app.

[open live demo]

Here’s a side-by-side example of the three options, the live editable code block is the top block here.

So to wrap up…

If your documentation setup is brittle, your contributors will flee…

But Gatsby…

And MDX…

…Helps make your docs inclusively smooth in both setup and execution.

Then your contributors will return…

…and will be happy to be part of your team.

Thank you.

https://noti.st/resource11

Slide deck posted after the talk @resource11 Twitter | Instagram | GitHub