Live data from Hacker News

Base Web, Uber’s New Design System for Building Websites in React

eng.uber.com

151–156 of 156 posts

Re: Base Web, Uber’s New Design System for Building Websites in React

#151
post #133

Earlier quoted context omitted.

I can appreciate that you guys weighed the tradeoffs and decided that giving users freedom to override arbitrary styles is worth the cost of whatever breakage might result from that decision as you upgrade the library. We're all engineers who build things to solve real world problems at the end of the day, and I don't have any of the context that led up to your decision, so I can't say for certain that I'd have weigh…

Right. We do exactly that as well. You can import all our styled subcomponents separately and then plug them back into render props. We just call it a bit differently - it's the "overrides" object prop and not a top level renderFoo prop. Example: https://baseweb.design/theming/understanding-overrides/#over... The ability to extend the styles is just a shortcut. If I want to change a border for some specific subcompon…

> But that's a lot of steps to just tweak a border, isn't it? Why not to just have "overrides.FooComponent.style" and let the library do the rest. This doesn't open more surface, just a quality of life API. Arguably you can run into the same type of style breakages when devs are restyling our subcomponents. They will not look inside of them every single time we release a new version.

The ability to arbitrarily override styles in every single component exposed through the library is exactly the crux of my concern outlined in my original post and later reply.

> "people are going to start using our components ways that we can't possibly ever fully anticipate" - That always happens no matter what you do! Unless you make your API super strict and then nobody will want to use your library. It's a delicate balance - keeping other teams moving fast and happy while not introducing breakages often.

Yes, there's definitely a balance to be struck here.

Opening up the API to arbitrary style overrides is sitting at one end of that spectrum, optimizing for short term user freedom/productivity and quick adoption of the component library over the long term maintainability of the library (every change becomes a potential breaking change), and with it, the ability of users to upgrade with confidence to take advantage of new changes and features.

However, the alternative to the wild west approach of arbitrary styling overrides isn't only to make an API so strict that it will never fit anybody's use cases outside of the ones it was originally designed for.

There exists a middle ground of providing an explicit API designed for specific use cases and then deliberately growing that explicit API to cover more use cases, informed by real world usage patterns, while taking care to make sure that those use cases are actually ones that make sense for the library to support long term (rather than built as one-off usage specific components), and that the resulting changes aligns with whatever styling consistency standards the library wants to enforce.

This approach affords maintainers an API surface to reason about and communicate breaking vs non-breaking styling changes to users, in exchange for short term speed of adoption because we're deliberately limiting the initial breadth of use cases the library can cover.

The former approach could definitely be the right tradeoff to make at this time given Uber's current circumstances.

Personally, I still have my doubts, after seeing how quickly this kind of API can break down even at a much smaller scale, but ruling that out without any context would be pure hubris on my part.

However, one caveat I'd like to add is moving from an explicit API to one that allows arbitrary overrides is easy, because adding an arbitrary overrides system is a non-breaking change, but going the other way is another story, because doing so would break everybody that relied on the overrides system to cover whatever use case the base API ever bothered to grow to cover, so it's not a decision to be made lightly. This is definitely not meant to imply that the team at Uber made the decision lightly, as I can tell from your thoughtful responses that you certainly did not, but rather as a word of caution to anyone else who's thinking about going this route.

Re: Base Web, Uber’s New Design System for Building Websites in React

#152

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.

We're building a very high-level component library ( EditableCard, FormModal, etc. ) at work with Ant Design and mobx. It helps us build our most common UIs very quickly, with very little lines of code, and improvements in one place are then deployed everywhere (like better error handling).

It's still very early / immature but I'd love to hear people's biggest confusions or gripes with it as it exists now:

https://mighty-justice.github.io/fields-ant/

Re: Base Web, Uber’s New Design System for Building Websites in React

#153
post #144

Earlier quoted context omitted.

I don't understand what you're trying to demonstrate with your example. Your TS(?) example is needlessly complicated, and syntactically invalid. Here's a better TS implementation: togglePanel = (panelToggle: bool) => this.setState({ panelToggle })

I agree, it wasn't a good example. More was (attempting) to make a point when inside a complex file, what I've seen. With long interface names mixed in with long variable names, contributing to larger files sizes than necessary. It varies depending on project/company. It's lowercase `boolean`.

You're right, sorry! I write TS every day at work but for some reason I sometimes forget which languages use bool and which use boolean ;)

Re: Base Web, Uber’s New Design System for Building Websites in React

#154
post #144

Earlier quoted context omitted.

I agree, it wasn't a good example. More was (attempting) to make a point when inside a complex file, what I've seen. With long interface names mixed in with long variable names, contributing to larger files sizes than necessary. It varies depending on project/company. It's lowercase `boolean`.

You're right, sorry! I write TS every day at work but for some reason I sometimes forget which languages use bool and which use boolean ;)

<3

Re: Base Web, Uber’s New Design System for Building Websites in React

#155
post #70

Earlier quoted context omitted.

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…

That feels a bit strange as a design philosophy; the point of components is that they encapsulate implementation and offer a simple, unambigious interface for configuration. If someone needs a component to do something it doesn't do, that's a sign that the primitives are wrong and the component needs to be refactored. Punting the solution back to product teams is prioritising short terms wins at the expense of long t…

I disagree- the default use case is still to use the components without overriding. Having a well defined mechanism for changing the component allows for consumers of the components to still get the main benefits of the component and the owners/maintainers have better visibility into what (if any) changes may need to be made to the core components.

A concrete example probably does a better job of explaining how this is used: https://medium.com/@dschnr/better-reusable-react-components-...

Referring to the Uber Freight RadioGroup and Tag Edit overrides from that article (not my article to be clear), those are cases where the vast majority of functionality from the original components satisfied the usage requirements, but a small tweak was needed to get the desired outcome. The override pattern is simply a way of building flexibility into the components and acknowledging that the users of the components may want to change them in ways that were not obvious to the component author. Those two examples may be fairly straightforward, but at what point do you stop with exposing the ability to change things? In our prior component library we saw a number of cases where teams wanted the ability to customize things that were more subtle, ie- changing the html element type on a subcomponent for a very specific purpose. This pattern came from observing the usage of our prior internal component library and talking with many of the internal consumers. It's probably not be a fit for everyone, but it works well for us.

Re: Base Web, Uber’s New Design System for Building Websites in React

#156
post #106

Earlier quoted context omitted.

https://gist.github.com/tajo/a84d96f248d454d1226e12bb07c8157...

That is not better. Just look at what you've created vs the idiomatic way of accomplishing the same thing with vanilla React. It's a new DSL on top of React that just adds unnecessary noise. It over complicates what should be a simple task. Why do I have to specify "List" twice? And what sort of magic is "component" performing? What are children now? Do they not exist anymore? And what does "overrides" mean in this c…

I think you're being overly harsh. Literally the only difference is

    overrides={{ Item: { component:
instead of:

    renderItem={
(personally I'd probably have a shortcut to allow leaving "{ component:" off though)

I don't think that's a bad tradeoff to render props support (plus prop/style overrides) support across your entire component library in a consistent way.

Post reply on HN