Creating the ultimate flexibility via Container components in React

We’ve recently open-sourced our design system, called Garden.

I wrote a Twitter thread on some of the cool stuff we’ve done that could be very useful as a starter for other people.

So here’s that thread with some extra goodies, in article form.

We’ve utilised a really cool pattern, based on the render prop pattern, to create some primitive components that can help anyone get started.

Component structure

In Garden we divide our components into 3 parts:

Image showing how our components are structured: Element, Container & View

Container components

We’ll drill down into the container component concept as this is the most useful to folks not directly developing on the Zendesk platform.

They’re UI-less components that provide a render callback. They provide state and prop getters, which you can then spread onto the correct components.

Container components have full WAI-ARIA, keyboard navigation and RTL support baked in.

They’re heavily inspired by downshift and the great work Kent C. Dodds and co. have done. I highly recommend you read the downshift announcement post.

A simple TextField Component

Let’s start simple, here we have a text field in our own styling.

We have high abstraction components built on top of our own container components.

In order to use this as a starting base for your own work, you can use our FieldContainer component, which TextField is built upon.

Demo using FieldContainer to build your own accessible version of TextField

A fairly contrived demo, what does it offer? Inspect the code via dev tools. You get the correct WAI-ARIA properties applied to the rendered elements, and the label has the for attribute, which corresponds with the input id.

Screenshot of the TextField component showing the WAI-ARIA attributes applied

Full keyboard support

With all our components in Garden you get keyboard navigation for free, so let’s up the ante and create tabs.

All our keyboard interactivity is matched by the guidelines specified in WAI-ARIA Authoring Practices 1.1, which is an excellent resource with really insightful demos.

Using the arrow keys once the tab list receives focus, you can easily change tab selection and then activate a tab by using enter or spacebar.

While the code seems verbose, it’s an incredibly powerful foundation to build on top of.

My recommendation is to wrap this logic into your own high abstraction component for friendlier consumption. See our own <Tabs /> component for an example.

Single selection model

Behind the scenes of the TabsContainer component, we have the all-powerful SelectionContainer that handles keyboard navigation and a single selection model.

A single selection model means that your UI has a container where only one sub-item can be selected at a time. A listbox, tree, and tablist all fall under what we would define as a single selection model.

Here you can create an interactive list completely controlled by the keyboard, that can handle vertical or horizontal flow, and the UI controls act as expected.

To really see the power of SelectionContainer, check out what we can do with our Menu and Select components.

There’s a whole heap of gems in here that can get you building more accessible components quickly and easily.

One last demo. I’ve taken the SelectionContainer demo and created a keyboard accessible chat window.

This is by no means best practice when it comes to creating an accessible chat, but provides a good reference to see how you can use our Container component to build upon.

If you are an a11y pro, I would love to know what I missed or what could be improved to make the chat demo a top notch example.

We hope this work gives you some new ideas to play with.

We look forward to seeing how people utilise our container components to help build more accessible UIs.

Props to my colleagues who’ve done excellent work to get this into the shape it is: Austin Green, Jonathan Zempel, Allison Shaw, Shelby Corbella.