minflow

Guide

Introduction

minflow is a React component library built from scratch in a single minimalist design language. min is the restraint and flow is the motion, and the whole point is that those two are the same decision made twice. Every one of the 68 components here obeys the same handful of rules, which is what lets them sit together without the screen turning into noise.

Why it exists

I have never been able to leave an interface alone. I will use something for a week, and by the end of it I am not looking at the screen any more, I am looking at the one underneath it: the same thing with two thirds removed and the part I actually came for sitting quietly in the middle. That picture is very clear to me. It is also, apparently, not available anywhere.

For years I tried to buy it. I would install a component library, get three screens in, and find myself arguing with it. Not because any of them are bad, they are the work of people far more patient than me, but because each one has already made the decisions I wanted to make. One wraps everything in a card. One ships forty greys and no opinion about which of them means less important. One animates nothing at all, and the next animates everything on the same curve, so a tooltip and a full-screen dialog arrive with exactly the same urgency. Each override I wrote took me further from their design without getting me any closer to mine.

Eventually the honest thing was to admit I was not shopping for a library. I was shopping for a design language, and I already had one. It just lived in my head, where nobody else could install it.

So I stopped looking and started building. Not a theme, not a wrapper around someone else's primitives, but the whole thing from the token layer up: every colour, every radius, every millisecond decided once and then held. I wanted a system where restraint was structural rather than a style you could opt out of, and where motion was not decoration bolted on at the end but the way the interface tells you what just happened.

I will not pretend this is better than what you are already using. It is more specific. It is one person's taste applied 68 times without flinching, and that consistency is the actual product. If the picture in your head looks anything like the one in mine, this should feel less like adopting a library and more like finding one that already knew what you meant.

Shekhar Singh, AI Architect. LinkedIn

How it is built

A token layer, before a single component

Every colour, size, radius, and duration in the library is a named token, and components reference them only. Not one component contains a hex value or a stock palette colour, which is a measured claim rather than an aspiration. It is what lets a reader repaint the entire system from five slots without a single component knowing it happened.

Motion is a vocabulary, not a number

There are no hand-picked durations anywhere. A transition names what it is, and the name decides how long it takes: a press is quick because it is feedback, a panel is slow because it is a place. Exits always run faster than entrances, because waiting to leave feels like a bug. When a reader asks for reduced motion the whole system stills, including the parts the operating system alone would not have reached.

Every scale is audited, not eyeballed

Three radii, three icon sizes, six type steps, one 4px spacing grid, a named ladder for stacking order. Anything off the scale is either pulled onto it or written down as an exception with a reason. Contrast was not trusted to the stylesheet either: the numbers came from painting each pair onto a canvas and reading the pixels back, in both themes.

You get source, not a dependency

Components are pulled in one at a time through the shadcn registry and land in your own tree as files you own and can edit. There is no version of this library that you have to wait on me to change. The token layer is the only thing that has to arrive first, because everything else styles itself entirely through it.

Nothing counted as done until it was watched

Each component was driven through a real browser with real clicks, real typing and real scrolling, then screenshotted in the state it claimed to reach, in both themes and at three widths. It was built the way I work now, in a tight loop with an AI pair, which only holds up because almost nothing here is a matter of opinion by the time it ships. A value is on the scale or it is not. A pair clears 4.5:1 or it does not.

What it borrows

Nothing here was invented from nothing. These are the four debts worth naming.

Swiss typography, for the grouping

The decision to have no cards, no dividers, and no section backgrounds is not a minimalist affectation. It is how print has always grouped things: with space, alignment, and type weight. A rule drawn around a group is an admission that the spacing underneath it failed.

Linear, for inline over modal

The idea that an object should be created exactly where it will live, starting as a ghost row that asks only for a name. Everything else gets filled in later, in place. There is no Create button anywhere in this system, and that is the reason why.

Apple, for the physics

Motion that behaves like a material rather than a timeline: interruptible, spring-driven under the hand, and spatially consistent so a thing that opened from a corner closes back into it. The stacked-card pattern, where older items tuck behind the newest and fan out on a tap, is lifted from iOS almost unchanged.

The NN/g elements glossary, for the scope

It was used as the checklist of what a complete interface library actually owes you, rather than shipping the fifteen components everyone ships and calling it a system. That is how the count reached the number it did, and why some of the stranger entries exist at all: the wheel picker, the pie menu, the 2D matrix pad.

The rules

Colour is hierarchy, not decoration

One accent-marked element per view, and it marks the single thing that matters most. Neutrals carry roughly ninety-five percent of every screen. Status colours mean status and nothing else, so a green tick always means done and never means decorative.

Space is the container

No cards, no panels, no bordered tables, no section backgrounds. Grouping is done with space and alignment the way print does it, and everything sits directly on the canvas. Elevation exists only for surfaces that come and go: popovers, dialogs, sheets.

Icons before words

Repeated and toolbar actions lose their labels and keep their meaning through a glyph, an accessible name, and a tooltip. Stripping the text never strips the message, and hit targets stay at forty pixels even when the glyph is sixteen.

Inline over modal

Objects are created where they will live. A ghost row becomes a draft asking only for a name and commits on Enter, with every other field fillable later, in place. There is no Create button anywhere in the system.

Motion you notice but never wait on

Every deliberate transition runs through motion.dev on one shared scale: fast feedback under pointer actions, slow and smooth for reveals and panels. Nothing bounces, nothing spins except loaders, and the whole system stills when a reader prefers reduced motion.

Two fonts, and theming cannot touch them

Inter carries everything functional; Nunito is reserved for titles and focal numbers. The palette is user-settable across five slots, and the compiler that applies it emits colour properties only, so changing your colours can never restyle your type.

Read the source, or change it

minflow is open source. Every component on this site is a single file you can read in a couple of minutes, and the design rules above are written down in the repository so a contribution can be argued about on the merits rather than on taste. Issues and pull requests are welcome, and so is telling me a rule is wrong.

Next

Install the library, then browse the components. Every component page carries its own variations with guidance on which one to reach for.