Skip to main content
Radix UIReact Hook FormDesign System

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.

Design Inconsistency

Forms looked and behaved differently across apps. Inconsistent UX.

Technical Fragmentation

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.

Primitives

Base components on Radix: Button, Input, Select, Dialog.

Form Components

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

1.

Developer experience drives adoption.

The library succeeded because it made developers' lives easier, not because it was mandated.

2.

Layer your abstractions.

Primitives for flexibility, form components for speed. Teams chose what fit their needs.

Stack

Technologies Used

ReactTypeScriptRadix UIReact Hook FormCSS ModulesZodStorybook