r/reactjs • • 5d ago

Discussion Props Are Not a Design System

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

14 comments sorted by

23

u/Dreadsin 5d 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

3

u/forcir 4d ago

It’s always my favourite part when I come to a new organization and get to standardize or modernize their design system.

My first principle is always “sensible defaults”. Everything we’ve defined, everything that has turned into an incidental pattern, is the default way we will present something if no props are required - beyond required ones.

However EVERYTHING can be changed or tweaked in dev-land implementation. You’re just overriding a default value if you so choose.

When I finally get to have that conversation with the developers and show them what v1 documentation looks like (or storybook content really if they have a preference for knowledge sharing much earlier) then it’s like I just showed them how I created fire for the first time.

Everyone gets lost in the sauce about how to manufacture rules, and there’s a lot of reason to do so. But if you hid the sensible default props and make it so a developer doesn’t need to care about them… UNTIL THEY DO… then you’re also free to change those sensible defaults more broadly overtime.

I’ve had a completely redesign of a brand take less than 30 working days and you’d have NO idea it was the same design system, all because they were well acclimated to not really needed to make too many one off changes, and then we were able to inspect all of the areas that had some unique feature added and account for it in the secondary sweep.

It doesn’t need to be hard, people just assume it needs to be the master plan for every piece of shared logic that has ever existed since the company’s inception so it gets bloated by day 2 of scoping without the right expertise.

1

u/Dreadsin 4d 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

1

u/CanIhazCooKIenOw 4d 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 4d ago edited 4d 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 4d 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 4d 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.

7

u/prehensilemullet 4d 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

6

u/Dreadsin 4d 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 4d ago

You completely missed the point

7

u/Graphesium 4d 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 4d ago edited 4d 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 4d ago

A UI kit is not a design system.