Building a Unified Component Library
Solving design inconsistency and accelerating form development across 5+ PrimaryBid applications.
- Company
- PrimaryBid
- Role
- Senior React Engineer
- Scope
- Multiple Applications
- 5+ Apps
Unified across platform
- Accessible
Built on Radix primitives
- Faster
Development velocity
Context
The Problem
PrimaryBid had multiple applications serving different users such as administrators, brokers, retail investors.
All form-heavy, all built differently.
Forms looked and behaved differently across apps. Inconsistent UX.
Mixed styling (CSS Modules vs Emotion) and form implementations (React Hook Form vs custom). Maintenance was painful.
Constraints
The Challenge
Build one component library for all apps. Accessible, consistent, but flexible enough for the IPO app's specific needs.
Engineering
Technical Approach
Foundation
Radix UI for accessibility out of the box: ARIA, keyboard navigation, unstyled primitives. Non-negotiable for fintech.
Forms
React Hook Form as the standard, wrapping Radix primitives. One unified API for complex forms across all apps.
Styling
CSS Modules with a two-variable pattern: default styling plus project-specific overrides. Consistent by default, customizable without fighting the library.
Solution
Architecture
Two layers: primitives and form components.
Base components on Radix: Button, Input, Select, Dialog.
Composed primitives into form-ready fields. Label, input, error display wired up.
Customization mattered. The IPO app had different design needs, so CSS variables let teams override without breaking things.
Outcome
The Impact
- 1.Unified 5+ applications with consistent design language
- 2.Accessibility by default across all apps
- 3.Faster form development with clear standards (CSS Modules, React Hook Form)
- 4.Used in both internal tools and the customer-facing IPO app
Reflection
Lessons Learned
Developer experience drives adoption.
The library succeeded because it made developers' lives easier, not because it was mandated.
Layer your abstractions.
Primitives for flexibility, form components for speed. Teams chose what fit their needs.
Stack