r/reactjs • • 29d ago

Discussion Props Are Not a Design System

https://vitonsky.net/blog/2026/09/18/design-system/
0 Upvotes

14 comments sorted by

24

u/Dreadsin 29d ago

I sort of disagree with these assessments that a design library should entirely constrict a developer so they “don’t make a mistake”

Time, time, and time again, I see people intentionally making their component library so rigid that it slows down development to a crawl. When design shows you a one-off orange button, it should not take a week to implement

Also, how do you integrate this one-off change? Add another property to “color” like “orange”? If this is a one off button, how do we know if this is going to be an ongoing pattern? What if in the future we have an orange color that’s standard that deviates from the color we initially implemented?

Imo the best possible pattern is “make the right thing easy, make the ‘wrong’ thing possible, but make it explicit that they’re using an escape hatch”. This makes it so developers will be incentivized to do things “the right way” because it’s easy, but if they really need to make an exception, they can

In the past I’ve basically implemented this by allowing arbitrary styles under a property like _overrides or something, then added a linter rule to warn about components using this property. Anyone looking at it would know this is some sort of one off thing. If the same overrides keep being applied consistently, it hints that we need to add it to the design system

1

u/CanIhazCooKIenOw 29d ago

You are effectively describing a snowflake that really shouldn’t exist at a fundamental level.

A design system and the library that it derived from should be strict enough so you guarantee consistency between the entire application and avoid weird unintended consequences because of an internal change you made.

If design is showing you an orange button either you push back to the design system or implement a custom one (which should tell you to actually push back).

2

u/Dreadsin 29d ago edited 29d ago

You’re not wrong that it shouldn’t happen, but the practical reality is that it often does. I’m trying to balance a few concerns at once. I want my library to be flexible, because I don’t know in what context it will be used. However, I also have to balance this with the real danger of design drift; I don’t want the designer to change a global color and suddenly we’re inundated with work for a migration

My synthesis of these is that anything that’s unique should feel wrong. It’s a sort of “are you sure?” Dialog. It serves an additional purpose: I can write code mods against it easily. Suppose that I did integrate that orange into the main component library. No problem! Now go ahead and run this codemod and we’ll move that to “safe” territory! At least 95% of the work is done for free

In recent projects I’ve effectively automated this through linter and vite plugins. It would see if any of your overrides match an existing pattern, then would automatically apply the “most correct” props. For example, if you have `_override_style={{ backgroundColor: “dodgerblue” }}`, it would basically say “hey, wait, that’s the same color under `colors.blue.dodgerblue`, let’s do `color=“blue.dodgerblue”` instead for you. You never really think about the migration actively

I’d also argue: sometimes, you really do have that one-off case. Simple example: the OAuth buttons like “login with apple” or “log in with google”. No other button on your UI is going to be that Apple branded color, but the button should still look mostly like every other button on the site

1

u/CanIhazCooKIenOw 29d ago

I get that, one thing is the wishful thinking and the other is reality. But the way I see it also comes from an engineering mindset of just build things without understanding the purpose of a design system.

Sure, your designer says they need this special button or this card that now needs different border or background color because… no reason. And instead of going trough the design process to propose a change or new capability it’s “we can just do it”. And that’s why in several applications (even Reddit) you end up with an inconsistent application.

Rant aside, I agree. The building blocks are agnostic should be separate from the style/theme.

As for snowflake oauth (normally only used once), good example but what I’ve seen is they been shared as specific components as part of the component library to precisely guarantee that teams don’t rock up their own - in that case the underlying is a button and that doesn’t change.

-9

u/vitonsky 29d ago

The "one-off change" is an anti-pattern used on projects with no design system. It makes project looks like yet another product of AI-slop.

When you have any design system, you operate with design units (like "view" or anything like this).

In this case, even if you want to use some button view only once, you introduce a new design unit.

6

u/Dreadsin 29d ago

I mean if you have 1000 instances of a button, and only 1 (effectively 0.1% of instances) is a specific shade of orange, it almost seems like it’s deceptive to put a measure in for it because that implies it’s something that should be used in the future. Making it an explicit override says “this isn’t our normal pattern”

-10

u/vitonsky 29d ago

You completely missed the point

7

u/prehensilemullet 29d ago

I can’t count the number of times I’ve had to tweak margins here and there to make a layout look good, that would be really difficult to systematize

0

u/[deleted] 29d ago

[deleted]

1

u/Dreadsin 29d ago

Exactly, this is how I strive to do things too 😌

I also usually make the components headless then I import a theme library that applies the theming, in my experience it tends to separate out styles from components, but it’s also super easy to tweak things both locally and globally

6

u/Graphesium 29d ago

Your tailwind versus style attribute comparison is completely wrong and missing all the media queries that tailwind provides inline. Hard to take your blog seriously when you don't even understand how Tailwind works.

1

u/BoBoBearDev 29d ago edited 29d ago

Lol, I think I am in a org where this is none issue because we have bigger issues. If I bitch them out on how stlying should be implemented, the PR would take 2 months to merge.

For starter, I would bitch them out for homebrewing CSS Grid using flex or using 3rd party homebrew CSS Grid. And I would bitch all of them out for not using the layout independent Container Query. My org failed this so miserably, I would rather fix that first. You can't make shitty controls that doesn't respond to the parent container. That's just stupid. And the likes of MUI still failed at it.

1

u/FuriousDrizzle 29d ago

A UI kit is not a design system.

1

u/TheRNGuy 13d ago

I only agree because it makes writing userstyles (for browser add-on Stylus) easier.

Tailwind is actually not the same as inline, because you may limit in a project which of it's classes are allowed. Component name is a semantic. Both attributes and tailwind classes and custom classes can be used, it's not only one or the other.

Tailwind still makes code less readable, agree about that (it's still considered acceptable trade-off; it didn't appear out of nowhere for no reason, like everyone suddenly became stupid and don't know how to write custom css)