The decision to start developing a new Bloom design system and component library was made in response to challenges supporting new jurisdictions as Bloom grew. Over time, we have made a few architectural shifts in our component library, which are documented below.

Remove backend dependencies

When Bloom was first created, it only supported jurisdictions in the Bay Area, and our internal React component library called ui-components (UIC) did not have any external consumers. The look and feel of these jurisdictions were almost identical. Bloom’s ui-components library at this early stage was not really a component library in the true sense at all, or setup to be open-source in an easy way.

It contained a lot of page content from the public and partners sites, and a lot of business logic specific to Bloom. In fact, the component library had a direct dependency on Bloom’s backend. If you were a consumer outside of Bloom and you wanted to pull in our ListingCard component, for example - you had to also pull in our entire backend, because were expecting a Listing to match the data model of a Bloom listing. This was not ideal for a consumer like DAHLIA, who as they pulled in ui-components, were getting a bunch of Bloom business logic they didn’t need.

One of our first significant changes was to remove this dependency on our backend package to make the components more agnostic to any consumer’s project, in an attempt to remove some business logic.

Pull package out of core

Another challenge at this stage was that ui-components existed as a folder within the Bloom repository. When outside consumers wanted to contribute, this meant they had to understand the full landscape of Bloom if they wanted to make a change to ui-components, as they would also have to uptake their changes from wherever Bloom was using those components.

We made a change to pull ui-components our of Bloom’s core repository and into a separate repo that published it as a separate package. Then, when consumers wanted to contribute, they only had make changes in the ui-components repository to do so, which made it much easier to support outside collaboration.

Component-level styles

The first jurisdiction we started working with outside of the Bay Area was Detroit. Detroit required a different look and feel than our jurisdictions in the Bay Area, and we discovered that we did not have the architecture to do that easily. We needed to be able to theme our components.

A first attempt at this was with what we called “V2 Styles” (previous documentation on this effort lives here). As we moved away from Tailwind, we introduced a set of design system tokens prefixed with --bloom, and on a per-component basis, a set of tokens specific to the styling of that component. For example, the UIC button has a generic class .button , and a set of component tokens at that level, like --label-font-size and --label-font-weight. If a consumer wanted to customize the styling of the Button, you would do the following override in your implementation, and it would only apply to buttons:

.button {
	--label-font-size: 2rem;
	--label-font-weight: 600;
}

In the UIC Storybook, the components that we ended up converting to V2 styles all have their stories marked with the 🚩 symbol.

This was a great step in a theme-able direction, but still proved to be tedious to manage, and required a lot of duplicative overrides.

When we started working with Detroit, a team from Google was responsible for the development, and we did not have much insight into their workflow. We had hoped that the contribution model would look like the Detroit team forking Bloom core, and then if they needed a customization made to a UIC component, they would contribute it first into UIC and then uptake their own change. Unfortunately, as a result of UIC not significantly supporting theme-ability and customizability, and because of how quickly they had to move, they ended up creating their own local version of UIC within their repo.

This caused a lot of issues, namely that their version did not stay up to date with updates and fixes going into UIC, but it also resulted in them having a local version of UIC that had diverged significantly, mostly just to handle styling updates and overrides that UIC didn’t support.

V2 component-level styles weren’t enough.

Questions about the future

Given the experience we’d had working with UIC as our work and clients evolved, we ended up in a tough spot reconciling Detroit, and reflected on how our design system and component library needed to change to support the future of Bloom, and to better support open source contributors. Some of those questions were: