1. 12:29 11/10/2026
**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.