Vishal.dev
Back
Shelf — React Component Library & Design System — live site preview
Full-Stack

Shelf — React Component Library & Design System

Professional design system with 100+ accessible components, interactive playground, dark/light themes, and publishable npm package — built on Base UI primitives with shadcn conventions.

Next.js 16TypeScript 5React 19Tailwind CSS 4Base UIFramer MotionRechartstsupLucide React
100+
Components
9
Categories
WCAG 2.1
Accessibility
Tree-shake
Bundle strategy

Domain Knowledge

What problem this project solves

Design systems solve the consistency problem: when multiple developers build features, visual and behavioral consistency degrades without shared primitives. Shelf provides a foundation layer that enforces consistent spacing, typography, color usage, and interaction patterns. Base UI primitives handle the accessibility complexity (focus management, ARIA attributes, keyboard navigation) so component consumers don't have to think about it. The publishable package format means teams can install it as a dependency rather than copying component files.

Architecture

How the system is structured

The system is structured as a monorepo with the component library as the core package and the documentation site as a consumer. Components follow a composable pattern: atomic primitives (Button, Input) compose into compound components (DatePicker, Select) which compose into page-level patterns (LoginForm, DataTable). Theme management uses CSS custom properties with a persisted toggle. The build pipeline uses tsup for ESM output with proper exports map and .d.ts generation. Documentation uses Next.js App Router with MDX-like content for per-component pages.

Data Model

Schema design and data flow

Component variants are defined using class-variance-authority (cva) with typed props. Theme tokens are CSS custom properties organized by category (colors, spacing, typography, shadows). Component state (open/closed, active/inactive, disabled) maps to visual variants through Tailwind classes. The playground state manages component previews with live prop editing.

Key Challenges

Hardest problems encountered

The hardest challenge was making components fully accessible while keeping the API simple. Base UI handles complex accessibility patterns (dialog focus trapping, combobox keyboard navigation, accordion ARIA) but the component wrapper had to expose these capabilities without leaking complexity. Theme consistency across 100+ components required strict token usage — no hardcoded colors, only CSS variables. The tsup build required careful package.json exports configuration to support both ESM imports and TypeScript path resolution.

Scaling Strategy

How the system grows

Tree-shaking ensures consumers only bundle used components. CSS variables enable theme customization without JavaScript overhead. Component lazy-loading is supported via dynamic imports. The documentation site uses ISR for fast page loads. The playground uses code splitting to avoid bundling all component previews upfront.

Security

Defense-in-depth approach

No runtime security concerns — the library is static UI primitives. XSS prevention is handled by React's built-in escaping. The documentation site has no server-side data processing. The npm package is signed and published with version pinning.

Failure Handling

Resilience and recovery

Component error boundaries prevent individual component failures from crashing the page. The documentation site has fallback rendering for failed MDX compilation. The playground catches and displays component errors inline. Build failures are reported with specific component and file references.

Observability

Monitoring and debugging

Bundle size tracking per component in the build output. Accessibility audit results displayed per component. TypeScript strict mode catches type errors at build time. Visual regression testing is planned for theme changes.

Trade-offs

Engineering decisions and alternatives

Base UI over Radix UI for stronger unstyled primitive support. Tailwind CSS 4 over CSS Modules for developer velocity and consistency. tsup over Rollup for simpler configuration with equivalent output. Framer Motion over CSS animations for complex interaction patterns. Recharts over D3 for React-native chart components.

Architecture Decisions

Key choices and what was rejected

Decision
Chosen
Rejected
Component primitives
Base UI (unstyled, accessible)
Radix UI (less flexible unstyled API)
Styling
Tailwind CSS 4 with CSS variables
CSS Modules (inconsistent naming)
Build tool
tsup (ESM + .d.ts)
Rollup (complex configuration)
Package format
Publishable npm with exports map
Copy-paste components (no versioning)

Senior-Level Topics

Concepts this project explores

Design System ArchitectureComponent Composition PatternsAccessibility (WCAG 2.1)CSS Custom PropertiesTree-Shaking OptimizationMonorepo StructureBuild Tooling (tsup)Theme Engine Design