**Why a Shared Component Library Matters** When you have both a web and a mobile application built with React, duplicating UI components leads to inconsistent design, extra maintenance effort, and slower feature delivery. A single, well‑structured component library lets you write each component once, then reuse it across platforms. This approach also encourages design consistency, simplifies testing, and accelerates onboarding for new developers. **Key Principles to Follow** - **Define a clear contract** – Use TypeScript interfaces to describe props that work on both platforms. This makes the library self‑documenting and catches type mismatches early. - **Separate platform‑specific logic** – Keep rendering logic generic, but allow platform checks (`Platform.OS`) where native APIs are required. - **Leverage design tokens** – Centralize colors, spacing, typography, and shadows in a theme object. Components read from this token store, so a single design update propagates everywhere. - **Write comprehensive tests** – Unit tests cover logic; visual regression tests verify appearance on each platform. - **Document with live examples** – Storybook or similar tools can render the same component in web and native stories, giving developers instant feedback. **Step‑by‑Step Implementation** 1. **Create the package** ```bash mkdir shared-components cd shared-components npm init -y npm install typescript @types/react @types/react-native ``` Set up `tsconfig.json` with `isolatedModules` and target `es2015`. 2. **Define shared types** ```typescript // src/types.ts export interface ButtonProps { title: string; onPress: () => void; variant?: 'primary' | 'secondary'; disabled?: boolean; } ``` 3. **Implement the component** ```typescript // src/Button.tsx import React from 'react'; import { TouchableOpacity, Text, Platform, StyleSheet } from 'react-native'; import { ButtonProps } from './types'; import { useTheme } from './theme'; export const Button: React.FC<ButtonProps> = ({ title, onPress, variant = 'primary', disabled }) => { const theme = useTheme(); const backgroundColor = variant === 'primary' ? theme.colors.primary : theme.colors.secondary; const textColor = theme.colors.text; const iosProps = Platform.OS === 'ios' ? { accessibilityRole: 'button' } : {}; return ( <TouchableOpacity style={[styles.button, { backgroundColor }, disabled && styles.disabled]} onPress={onPress} disabled={disabled} {...iosProps} > <Text style={[styles.text, { color: textColor }]}>{title}</Text> </TouchableOpacity> ); }; const styles = StyleSheet.create({ button: { padding: 12, borderRadius: 8, alignItems: 'center' }, text: { fontSize: 16, fontWeight: '600' }, disabled: { opacity: 0.5 }, }); ``` 4. **Add a web implementation** ```typescript // src/web/Button.tsx import React from 'react'; import { ButtonProps } from '../types'; import { useTheme } from '../theme'; export const WebButton: React.FC<ButtonProps> = (props) => { const theme = useTheme(); const { title, onPress, variant = 'primary', disabled } = props; const style = { backgroundColor: variant === 'primary' ? theme.colors.primary : theme.colors.secondary, padding: 12, borderRadius: 8, textAlign: 'center', opacity: disabled ? 0.5 : 1, }; return ( <button style={style} onClick={onPress} disabled={disabled}> {title} </button> ); }; ``` 5. **Export a unified name** ```typescript // src/index.ts export { Button } from './Button'; export { WebButton } from './web/Button'; ``` **Using the Library** - **Web app** ```tsx import { WebButton } from 'shared-components'; ``` - **Native app** ```tsx import { Button } from 'shared-components'; ``` Both imports point to the same component definition, ensuring a single source of truth. **Best Practices for Long‑Term Success** - Keep the library small and focused. If a component becomes platform‑specific, split it into separate packages. - Automate publishing with CI/CD so updates are available instantly. - Encourage contributors to add new components by following the existing TypeScript and styling patterns. - Periodically audit the component tree for dead code and refactor as needed. By following these steps, you’ll create a robust, maintainable component library that bridges React web and React Native, saving time and preserving a cohesive user experience across all your products.