4 ms·
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 m
by miksuv 7y ago
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/#override-the-entire-subcomponent https://baseweb.design/theming/understanding-overrides/#over...). 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 7y agoDo 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.
- ohadpr 7y agoThe folks behind Storybook created a product for that: https://hichroma.com/ https://hichroma.com/
- miksuv 7y agoWe 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.
- lewisl9029 7y agoI 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 weighed those tradeoffs any differently if I were in your shoes and have to cater to the whims of thousands of engineers with differing opinions on how things should be done. However, I have to disagree with your characterization of render props as "the freedom to completely replace the guts of your component". Offering a render prop API should be an explicit decision to fundamentally stop treating that branch of the render tree as part of the "guts of your component". It's a decision to delegate to users on how to best render that part of the component. Of course, you're right that in a vacuum, that would equate to throwing up our arms and asking users to figure it all out on their own as to how to implement the styling and functionality of that part of the tree. However, when we're the maintainer of a component _library_, we're in the unique position where we can provide additional, complementary components that provide styling and functionality for users to use to implement that part of the tree, composed with their own custom components when appropriate, without having to build everything from scratch. These components usually start out as the same components that used to reside in that part of the tree in the original parent component. By decoupling them from the parent, they're then immediately able to start providing their own explicit interfaces that can be evolved independently from the parent without risk of breaking usages on implementation detail changes. Of course, users are free to simply not use those components because they might not address whatever problem they need to solve. Rather than taking that as a failure of the approach, I'd take that as a triumph because it demonstrates that this approach gives users the flexibility to experiment with how best to solve their particular problems within the confines of the isolated subsection of the original component without affecting the maintainability of the component itself. And we as library maintainers are then able to examine the various custom components created for those use cases to see if any particular implementation is suitable for extracting directly into the library, or at least learn from them when building new reusable components to support those use cases officially (and users are free to choose to adopt those new components at their own pace, without any fear of things breaking under their feet). This is why I point to this approach as the middle ground. Component composition is a much more sustainable mechanism to provide to users for customization, in my opinion, compared to arbitrary overrides. In fact, if anything, I'd consider arbitrary overrides to be the nuclear option here, because once we start offering that option, people are going to start using our components ways that we can't possibly ever fully anticipate, so we end up having to _really_ throw up our arms as maintainers and start saying things like "We don't consider changed styles as a breaking change".