A popular React component library with 104,000 GitHub stars is under fire for using 215 lines of code to build a radio button. Developer Paul published “The Incredible Overcomplexity of the Shadcn Radio Button” on January 20, 2026, sparking a Hacker News discussion with 355 points and exposing a fundamental tension in modern web development.
Here’s the controversy: shadcn/ui’s radio button requires Radix UI (seven files, 215 lines of React), the Lucide icon library, and 30 Tailwind utility classes. The same visual result? A native HTML input with 10 lines of CSS. This isn’t just about one component. It’s about an entire ecosystem that’s lost touch with HTML fundamentals in favor of over-abstracted frameworks.
The Technical Case: When Simple Gets Complicated
Paul’s critique is damning on technical grounds. shadcn’s implementation violates the First Rule of ARIA: “If you can use a native HTML element, do so.” Instead of input type=”radio”, the component uses button elements with ARIA roles, creating accessibility violations. Data backs this up: pages with ARIA averaged 41% more accessibility errors than pages without ARIA. The mantra? “No ARIA is better than bad ARIA.”
Worse, the component has functional bugs. It misses clicks in certain areas and doesn’t capture clicks between the label and button – making it objectively worse than native elements. Meanwhile, the alternative is trivial: appearance: none, ::before pseudo-elements, and the :checked pseudo-class accomplish the same result with zero dependencies and no JavaScript.
Why shadcn Succeeded Despite the Complexity
Here’s where it gets nuanced. shadcn/ui didn’t reach 104,000 GitHub stars and 560,000 weekly npm downloads by accident. It solved real problems that plague frontend development.
The copy-paste model is genuinely innovative. Instead of npm installing a dependency you’ll fight with for three years, you copy component source code directly into your codebase. You own it. No version conflicts. No forced updates when libraries break. For teams building design systems, shadcn democratized beautiful components without requiring a designer.
The pragmatic defense from Hacker News defenders is worth considering: “If you’re building something like Figma or Linear where you genuinely need accessibility primitives, the complexity pays for itself.” Historical context matters too – radio buttons weren’t fully styleable across browsers until recently. The abstraction layer solved legacy support problems.
But solving real problems doesn’t excuse using 215 lines for a radio button.
The JavaScript Fatigue Problem
The radio button controversy is a symptom of a broader crisis. Frontend developers in 2026 are experiencing collective burnout. Framework fatigue isn’t just a meme anymore – it’s a professional reality. Developers who raced to master React, Vue, and Svelte are quietly returning to vanilla JavaScript.
The emerging “vanilla-first” movement mirrors the mobile-first revolution that changed web design. Start simple. Add complexity only when justified. Frontend development, according to recent analyses, is failing because of “too many decisions, abstractions, and unnecessary complexity.” Massive JavaScript bundles, over-engineered state management, and tooling that requires tooling to understand tooling have created a maintenance nightmare.
One critical insight from the Hacker News debate captures the problem: “When all someone knows is React or other frameworks, things get overengineered. They didn’t realise it could be so much simpler if they just knocked it back a layer.”
The Education Gap Nobody Talks About
Modern frontend development has created a generation of developers who reach for 200-line React components before considering 10 lines of CSS. When abstraction becomes the default, understanding fundamentals becomes optional.
This creates fragile knowledge. Developers who can build complex applications but can’t style a radio button without a framework. Developers who “don’t know they can just use HTML.” That’s not a personal failing – it’s an ecosystem problem. We’ve built an industry where shadcn’s complexity seems reasonable because we’ve normalized over-engineering.
Tailwind’s contribution to this problem deserves mention. Critics accurately note that “Tailwind v4 still makes my HTML look like someone sneezed utility classes all over it.” Thirty utility classes for a single radio button isn’t elegant. It’s HTML bloat masquerading as developer experience.
Where This Leaves Us
shadcn/ui is both brilliant and dangerous. It made beautiful components accessible while making HTML knowledge optional. The copy-paste model is genuinely innovative. The ecosystem consistency argument has merit. For complex components like tree views or custom comboboxes, the abstraction layer makes sense.
But for a radio button? No. Using shadcn for basic HTML elements isn’t solving problems – it’s creating them. Bundle bloat. ARIA violations. Functional regressions. Developer skill gaps. Technical debt in codebases and in developer knowledge.
The uncomfortable prediction: Five years from now, we’ll look back at the 2020s frontend stack the same way we look at jQuery spaghetti code. A well-intentioned solution that created more problems than it solved. The pendulum is already swinging – vanilla-first adoption, framework fatigue, developers returning to fundamentals.
The real issue isn’t shadcn. It’s an ecosystem that values abstractions over understanding, popularity over correctness, and developer convenience over web standards. When 215 lines of React code seems like a reasonable solution for a radio button, we’ve lost the plot.
Sometimes the answer isn’t a framework. It’s just HTML.












