
Base Web, Uber’s New Design System for Building Websites in React - sgolestane
https://eng.uber.com/introducing-base-web/
======
insomniacity
I guess we can add Uber to this list of corporate frameworks...

[https://news.ycombinator.com/item?id=18235887](https://news.ycombinator.com/item?id=18235887)

[https://element.eleme.io/](https://element.eleme.io/)

[https://ant.design/](https://ant.design/)

[https://quasar-framework.org/](https://quasar-framework.org/)

[https://at-ui.github.io/at-ui/](https://at-ui.github.io/at-ui/)

[https://developer.microsoft.com/en-
us/fabric](https://developer.microsoft.com/en-us/fabric)

[https://vmware.github.io/clarity/](https://vmware.github.io/clarity/)

[http://appnexus.github.io/lucid/](http://appnexus.github.io/lucid/)

[https://ng-lightning.github.io/ng-lightning/](https://ng-
lightning.github.io/ng-lightning/)

[https://blueprintjs.com/](https://blueprintjs.com/)

[http://www.jetbrains.org/ring-ui/](http://www.jetbrains.org/ring-ui/)

[https://www.lightningdesignsystem.com/](https://www.lightningdesignsystem.com/)

[https://elastic.github.io/eui/](https://elastic.github.io/eui/)

[https://atlaskit.atlassian.com/](https://atlaskit.atlassian.com/)

~~~
wuliwong
You seem to trying to express a negative response to the fact that these
companies create design frameworks. I'm interested as to why you feel this
way?

~~~
Improvotter
>insert xkcd framework reference<

------
lewisl9029
The overrides pattern they describe sounds like a nightmare to maintain. It's
almost the exact opposite of how I'd design the API for a set of reusable
components: provide a minimal API surface to cover existing use cases, and
evolve the API deliberately to cover new use cases as they arise.

Allowing users to override arbitrary styling parameters is a recipe for
disaster in a reusable component, because once you start doing that, literally
any change you make to the component could become a breaking change for some
usage of it in the wild. There is no more explicit interface that users of the
component are expected to work with that you can hide implementation details
behind, as to afford you the ability to change those implementation details
without breaking users, because users can just reach into your implementation
details with those arbitrary parameters and change them at will, in a way
that's potentially incompatible with how you might want to evolve the
component in the future. As a side effect, any sense of brand/design
consistency you might want to enforce through a design system goes out the
window. Interestingly enough, this set of components use component-oriented
CSS-in-JS, which is a pattern developed specifically to provide style
isolation between components that wasn't possible (or at least not in a
foolproof way) with regular CSS, yet they chose to open that can of worms back
up through their API.

I've found that a much better middle ground is to deliberately accept React
nodes or render props in your components so that you can explicitly yield
control of rendering to users for specific, isolated pieces of the component,
like the contents of a modal or the individual options of a dropdown. This
gives users freedom to render what they need to render, but within the
confines of a consistent design framework that enforces overarching rules
around consistent use of spacing, colors, transitions, etc. And such an API
can still be evolved deliberately to support new use cases without the risk of
breaking users unintentionally.

~~~
miksuv
I get this concern and I used to have a very similar feeling about it. Uber
had an older React component library that was more locked down in a way you
pretty much described. Number one complain was "not easy to customize" and
that probably applies for every component library out there.

You describe render props as a "middle ground". For us, it is the last resort
/ nuclear option (as described here
[https://baseweb.design/theming/understanding-
overrides/#over...](https://baseweb.design/theming/understanding-
overrides/#override-the-entire-subcomponent)). You give the consumer all the
freedom to completely replace the guts of your component. Sure, nothing
provides more flexibility but at the same time, consumer has to do a lot of
heavy lifting - creating a whole new component.

However, developers usually want to tweak some small things. Maybe changing
some color or padding. Forcing them to swap the whole subcomponent through
render prop is an overkill and once they "opt-out" that way, they will never
get any updates from us since that part of component is completely replaced.

Of course, ideally we want them to always use the defaults but that's not how
real organizations with thousand of engineers and hundreds of apps work so we
rather let them customize but on our terms. We don't want to see them hacking
the styles through CSS selectors or "render prop" everything which equals not
using our visual components at all. It's a compromise we had to make to make
everyone reasonably happy.

Surprisingly, it's not a nightmare to maintain. We don't consider changed
styles as a breaking change and in last 6 months I haven't seen complains
about that. Although, it makes the Base Web codebase more complex and all
changes need to be thoughtful. But that's a cost that Base Web pays so other
teams don't have to.

~~~
btown
Do you use any sort of visual comparison tools or snapshotting in CI to catch
regressions caused by changes to Base? Seems like this would remove any
(technical) objections to having overrides.

~~~
miksuv
We currently use [https://screener.io/](https://screener.io/) for Base Web
itself and working on an app that should automatically crawl all our web apps,
analyze them and provide insights into how exactly our components are being
used. It should be open sourced eventually.

------
tomelders
Nope. This is replacing composition with configs for no good reason. It's like
the people who made Grunt and Webpack teamed up to ruin React for everyone.

~~~
Klathmon
I really hate dismissive comments like this.

They laid out pretty well what problems this is trying to solve, why they want
it that way, the benefits it has, and some of the tradeoffs it makes.

Saying it "replaces composition with configs for no good reason" is not only
wrong (they still heavily use composition here, it even makes it more powerful
in some ways from what I can tell so far), but also doesn't really mean
anything on it's own (at least to me it doesn't).

~~~
tomelders
Ok, fair enough. It was a drive by shooting of a comment. So here’s a more
considered criticism.

There’s already a way to overwrite props in react. Just use props.

If you need to expose the native API of the underlying element, do this (does
HN format code?)...

``` const {foo, ...native} = props;

<label {...native}> <p>{foo}</p> </label>

```

Combine that with default props and you’re good to go.

There’s already a way to allow components to take multiple types of children.

``` <Select render={ blah => { return <CustomOption>{blah}</CustomOption> }}
/> ```

And there’s already a multitude of ways to adapt styles based on props, the
most obvious of which is StyledComponents.

In addition, this highlevel config is brittle. It means parents must be
coupled to their children, and children coupled to their parents.

And where does this config end? How deep does the nesting of this
configuration go?

Here’s my opinion; if you think you need this sort of configuration to
properly wrangle your UI, then you’ve failed to grasp the point of React and
the true power of composition.

React components are just functions. Preferably pure functions. Once you strip
away the JSX, you should be left with something that resembles functional
programming (albeit taken to an extreme thanks to JSX’s goal of emulating
HTML). Props are parameters. We’ve all come across code where functions take
complex and convoluted objects as arguments that trigger an explosion of calls
that are near impossible to track or reason about.

This override solution is the first step in towards turning React into the
kind of tool that it usurped. It has the stench of ExtJs and it’s ilk.

This “solution” was created by people who believe all problems are better
solved by abstraction.

As programmers, our time is spent on the edge cases. Our text book prefect
algorithms and mathematically sound functions are exposed as frauds the second
they’re exposed to user input. Our carefully crafted UI libraries fall to
pieces when the designers choose to break their own rules.

For configuration to work, it requires god level foresight and will eventually
become Turing complete in itself.

Config is for the birds. Declarative code has always been the answer.

~~~
SubFuze
A big part of the goal with the overrides mechanism was to provide usable
components out of the box that could optionally be modified if something
needed to be changed for a given use case.

You can use the components as is, using props if you're ok with the out of the
box style/functionality/etc, without ever touching overrides. The overrides
provide a standardized interface to changing the component internals across
the entire component library.

That approach may be overkill for simple components that are trivally
composable (Card for example), but is incredibly powerful for a component like
Datepicker where you may want to change styles or functionality of a deeply
nested component without exposing a massive top level props interface.

~~~
tomelders
But you’re still creating a suite of components that can be composed to create
a specific instance of a date picker. Except with the override config, you’re
now complicating and limiting the simple and versatile concept of composition.

Your components now need to follow some pre established and short sighted
rules in order to understand how to manage their own children.

To use the example in the article, lets say you have an Option component, but
now you want a version of that component that takes two additional components
under certain conditions. E.g, an icon, and a checkbox? But only when one
specific Option has a specific combination of props?

How does this override system handle that? It doesn’t. Composition handles
that. But if components are created with this override system in mind, they
lose the ability to be composed in more complex ways than the designer of the
override system imagined.

~~~
tomelders
It turns out I was wrong about this, but not in a good way.

It appears you can pass functions to the config that render components, which
presumably can also take an override config which in turn can take a function
to render components and so on. So it's basically negating the entire point of
JSX. It's halfway between JSX and React.createElement. The worst of both
worlds.

------
mmckelvy
I've been searching for a basic React UI component system for awhile now.
There are a lot of systems available, but each one has significant drawbacks
to the point I end up just rolling my own.

I think an ideal system would have a core set of "unstyled" components with
the necessary functionality baked in. That way the overall aesthetic is up to
you, but a lot of the painstaking UI work (e.g. showing, hiding, and
highlighting elements in a dropdown menu or making sure a layout element
breaks properly on mobile) is already done.

From there you could build UI "kits" that use the core functionality but each
have a distinctive look and feel.

~~~
tomelders
For the past few years, i’ve been building “reusable component libraries” and
I can say with confidence that they’re a massive waste of time.

When you get into it, the UI usually the least difficult problem to solve in
an app. The real challenge is state management, control flow, and wrangling
sode effects.

Alas, people are still wedded to the idea that UI is where all the time is
wasted.

The truth is, it’s always been easy to put a button on a screen. But making
that button do something? That is a much bigger problem. I’d argue that 99% of
the effort of putting a button on a screen goes into implementing whatever
that button does. But stakeholders don’t understand that. They think buttons
just do the thing they do, so when it takes six weeks to put a button on
screen, they naturally assume that a reusable component library that includes
a button will somehow shave days and weeks off a project.

Which is why they gravitate towards UI libraries. And then they introduce a
new problem that wasn’t there before. They want us to use Material UI, but
they want us to make it look different. And they want a bunch of extra UI
elements to boot. So not only do we still have all the original problems of
creating an app, we’re now on the hook for turning some implementation of
Material UI into something that fits with with our architecture, but is also
completely different.

So while I hate UI libraries, I recognise that they’re something inflicted on
a team. So I’ve started work on a UI library designed specifically to address
this problem. It’s a UI library that’s meant to be changed and easily
customised by it’s consumers. It’s minimal functionality and minimal styling.
I’ll announce it here on HN when I think it’s ready. It may never be ready
because not only is it a difficult problem to solve, I’m also very lazy.

But anyway, I say all this because I hear what you’re saying, and I’m working
on it.

~~~
VoiceOfWisdom
FYI, Material UI is working on the issue as well [0].

[0]
[https://twitter.com/olivtassinari/status/1120818781058686979](https://twitter.com/olivtassinari/status/1120818781058686979)

------
topicseed
Finding a good React UX library is tough. None is ideal. Too heavy, too small,
too slow, too dirty.

Settled on ant.design for a while, not perfect but good enough.

~~~
dwaltrip
Any other good candidates? This is something I really need to look into soon.

~~~
chrischen
I've found Materia-UI to have the best code quality, most up-to-date. If you
don't like Material UI theming it's also easily overridable.

Downside of ant-design is that the library is huge (there was a bug recently
where the whole icon library was included in the bundle!), some of the
components have bugs, style/look is not easily modifiable.

~~~
topicseed
Love ant-design and currently, you can use tree shaking I believe. It is
otherwise a heavy lib for sure. Not great for B2C apps, but for B2B with
caching it should be okay if users have decent broadband speeds.

------
dmix
So this is basically a component framework ala [https://element.eleme.io/#/en-
US/component](https://element.eleme.io/#/en-US/component) with some theming
standards?

Edit: The drag and drop component is nice and looks well-built. I had to use
vue-draggable [1] for an app recently which was just a hacky Vue layer on top
of Sortable.js [2]. It's one thing I wished ElementUI supported natively.

[1]
[https://github.com/SortableJS/Vue.Draggable](https://github.com/SortableJS/Vue.Draggable)

[2]
[https://github.com/SortableJS/Sortable](https://github.com/SortableJS/Sortable)

------
jscholes
> drag and drop Lists are notoriously difficult to implement because browsers
> provide little help when developers have to build drag and drop
> interactions. Developers using Base Web have the peace of mind that keyboard
> navigation is reliable and works well with screen readers.

FYI, their drag and drop sample doesn't "work well with screen readers". It's
overly verbose and requires keyboard passthrough to operate. So maybe don't
take any web designers at their word when they say you can just use their
framework and forget about accessibility.

------
revskill
I'm surprised that many huge React libraries don't expose its core Context for
user to consume.

Context is the most important concept in React.

Actually, a library just need users to provide the right types of Context to
be flexible.

I'm tired of the "lock in" API, in which, it doesn't allow me to just get my
context data into its arguments API.

In this sense, you can consider Context as the local version of Redux.

~~~
gramstrong
As someone who stopped doing React development before Context became a
"thing", is it possible to ELI5 in a couple sentences why it is such an
important concept?

~~~
revskill
It's important, because you don't need to care about props vs state, instead,
just consume the context deep in your component tree.

One use case, is, suppose you have two independent contexts at two branches,
now, if you want to share those data to 3rd branch, you just create new
context with value from the first two contexts.

~~~
thereare5lights
This is starting to sound like the scope from Angular 1.

~~~
munchbunny
Contexts in React are like raw pointers in C++. There are reasons to use them,
but every time you do, it should raise eyebrows, because they are finicky,
complicated to reason about, and thus full of pitfalls.

------
jacobr
Nice, looks very well made.

It does force everyone in your organization to not only use React, but also
Styletron which might be a pretty large switch for some teams. Has this been a
problem?

I think this could lead to limited adoption in some organizations because
autonomies teams want to keep delivering with their current stack.

One idea I considered is to have an Atomic CSS library for theme stuff like
whitespace, color and typography, and compose those into components for React
or Svelte 3 or whatever is hot right now.

All other styling could be done with Styletron, styled components, or plain
CSS, whichever suits your team.

~~~
miksuv
Yep. React was adopted a long time ago and it is also now the "industry
winner", so no complaining there. Styletron is also older - created more than
two years ago.

However, CSS in JS is more controversial and there are some other more popular
libraries now. We keep monitoring them and at the same time we are bringing
the best features back into Styletron. Also, you could use BaseWeb+Styletron
and some other CSS solution for everything else. It's not a big deal
(Styletron has like 7kB). But all CSS in JS libs are very similar anyway.

So overall, Base Web was not a big tech switch, React and Styletron have been
already widely used.

------
Brajeshwar
Referencing and being inspired by someone‘s Design System is a good thing. Try
looking at a bunch of them to get a better perspective.

However, using someone's Design System may not always be a good choice.
Unless, they are lean, non-directional and are mostly patterns that you can
adapt to any tech stack or systems. For instance, Google’s Material Design
Philosophy is a good starting point and you can leverage it as your base
system. You’ll still need to understand the WHYs of the principles. Without
understanding the core principles and the WHYs, you’ll be dependent on it in
the wrong fashion.

Here is an example without trying to single it out from the other Design
Systems. Sometime back, I studied Ant.Design to see if I can adapt to a
massive product overhaul. Unfortunately, I realized that it is a system more
specific to the way AliExpress does and think about their design. And
technically it was in LESS (CSS Pre-Processor).

There are many good, well thought out systems. One being that of AirBNB’s
JavaScript styleguide.

Be inspired, and possibly start with a system that has fewer restrictions, a
lot of community activity behind it.

~~~
bradleyhb
What’s meant by non directional ?

~~~
Brajeshwar
Now, I'm not sure if I used the right vocabulary. I meant, it has constraints
which lead you one way in a singular path, their way.

------
habosa
Before even looking at the details ... why would I use this? Uber is not a
company that is known for great websites. They get (I'm guessing) 99%+ of
their usage through native apps. So why would I believe they're particularly
good at building for the web?

~~~
lucasmullens
It's probably got more engineers behind it than the vast amount of design
frameworks, given Uber's size. And some of the components feel pretty nice, so
maybe try looking at the details?

------
ahallock
Can you use this outside of React? I'm interested in the styles, but I'm not
using React.

~~~
yesimahuman
This is why Web Component interest is growing, especially w/ enterprises and
large teams. The killer app for WC's is building Design Systems that don't
force specific frontend framework decisions.

~~~
tdhz77
Do you have a source? I’d like to explore WC, but from what I have gathered WC
evangelist are dying out to React ecosystem.

------
underwater
The overrides system is weird, to say the least. Any consumer can change
styles and erbitrary HTML attributes deep inside a component's DOM tree

This breaks encapsulation. As an app developer how do I know my change will be
future proof? As a component developer how can I refactor a component or
change its behaviour without breaking my consumers?

It feels like stuffing the worst parts of jQuery and old-school CSS back into
React.

------
petraeus
Why do they call it a "design system" instead of a framework .. you know like
99% of the web does

~~~
impostir
React is the framework and their design system uses a specific set of rules
within the React framework to build consistent end UI/UX.

~~~
warent
React is not a framework. It's just a view library.

~~~
TheRealPomax
React is a view library, _with an opinionated methodology_ and congrats: now
you have a framework.

------
hsavit1
Unfortunately the accordion component is not smooth at all. Otherwise, a
valiant effort.

------
aphextron
CSS-in-JS is an unmaintainable disaster. Write your SCSS, keep it modular, and
import it as a JS object with sass-loader.

~~~
chrischen
CSS-in-JS allows for easy JS-based code-splitting (if you've got that setup)
and inlining critical CSS on the page.

~~~
aphextron
>CSS-in-JS allows for easy JS-based code-splitting (if you've got that setup)
and inlining critical CSS on the page.

All of this can be accomplished without keeping your source of truth in JS
config files. SCSS or CSS files can easily be loaded with Webpack and imported
into your code. Then you're not giving up the simple yet powerful
expressiveness of CSS selectors for a nightmare of nested JS objects.

~~~
chrischen
Generally CSS is loaded into your code where you require them but has to be
extracted into a single bundle.

If you want to it _truly_ be loaded into your code where you use it, then CSS-
in-JS is the solution and does this for you.

It sounds like the main gripe you have is with syntax, and that's not really
required with CSS-in-JS. The 'nightmare of nested js objetcts' can be hidden
in the implementation. In fact, many libs (such as emotion) allow you to write
CSS syntax using babel macros to preprocess this into javascript.

------
sbhn
Horay, finally, where do i throw my money,

------
d357r0y3r
Imagine creating this beast of a "framework" and not even using TypeScript or
Flow. What are you thinking?

Edit: It does use Flow.

~~~
mmckelvy
Sigh. I really wish people would just accept the fact that JavaScript is a
dynamically typed language and stop making things unnecessarily difficult.

~~~
Klathmon
That's why I love Flow and Typescript so much. They are as opt-in as you want
them to be.

I've seen a team use typescript, but have zero types in most of their files,
they just used it from libraries to get some IDE autocomplete and some very
small typing on core areas.

------
Theodores
This article makes a lot of noise about Uber's commitment to accessibility. So
I am led to believe that this new React gizmo is fully accessible.

Yet Uber can't be bothered to make efforts to get basic accessibility right on
the page that tells us this.

The main content is not in a <main> element, this <main> element being the
landmark that tells people using assistive technologies where the main content
is.

Then the navigation links, e.g. in the footer are not in <nav> elements.

The code sample in the middle is an image. It should be in a <figure>,
<pre>formatted and in a <code> block for accessibility.

It is a bit hypocritical to write an article about how wonderful your product
is for accessibility and not make it accessible.

~~~
lhorie
Those are issues with the CMS being used to host the blog. The blog has been
around for a long time and isn't using BaseWeb.

What you're suggesting is that when someone releases a library with a
commitment to accessibility, they are also responsible to reach out to some
completely unrelated comms-focused team, take over their CMS workflow, rewrite
it entirely with the new framework, and only then make a blog post about the
thing you were trying to talk about.

~~~
Theodores
It is not difficult to put a <figure> in Wordpress with some code inside it.

Some things you either have or you don't. Accessibility is one of those
things. Either you think it is actually important or you don't.

The Uber comms team also need to be living and breathing accessibility. It is
part of what comms is about.

~~~
lhorie
Who is "you"? Me personally, the team behind BaseWeb, the comms team, Uber as
a whole? Companies by definition can't "care" since they are emotionless
entities, so you must mean a physical person. But physical people within a
large organization might care about different things with different degrees of
priority or be prevented from doing the best thing (tm) for various reasons.
But we all already knew that.

------
warent
My favorite part about Base Web is that it's broken.

How to reproduce:

1\. Visit the official website
[https://baseweb.design/](https://baseweb.design/)

2\. Click "Welcome" on the sidebar.

3\. "An unexpected error has occurred."

No thanks, Uber. Your community of broscience engineers permanently lost me as
a customer after the Susan Fowler writeup, and I'm not interested in your
buggy technology either.

~~~
stronglikedan
Cannot reproduce.

~~~
warent
It's probably because I'm using uMatrix and it's blocking something "critical"
that breaks when you try to visit the Welcome page.

~~~
Klathmon
Wait so you are blocking their javascript then claiming it's broken?

I was curious, and I just went in and tried blocking the google analytics,
google tag manager, and everything from cdn.jsdelivr.net, and even some random
scripts (like the commons.js file), and everything still worked fine as far as
I could tell...

~~~
warent
It's loading the first-party scripts (all 58 of them), but there must be even
more delivered by a CDN that it requires.

[https://i.imgur.com/iGqwpWR.png](https://i.imgur.com/iGqwpWR.png)

------
wsdfsayy
It looks pretty nice. My pet peeve with "modern" web design is that it has
become, objectively, very effeminate. Uber tends to leans more neutral to
slightly masculine.

