@zyphr-dev/inbox-react-native
v0.1.4
Published
React Native components for Zyphr notification inbox
Maintainers
Readme
@zyphr-dev/inbox-react-native
Native React Native components for Zyphr notification inbox with real-time updates, preference management, and theme support.
Looking for the web version? See
@zyphr-dev/inbox-reactfor React DOM components.
Installation
npm install @zyphr-dev/inbox-react-native
# or
yarn add @zyphr-dev/inbox-react-nativePeer Dependencies
react>= 17.0.0react-native>= 0.64.0
Quick Start
1. Generate a Subscriber Token (Server-Side)
// Express example
app.get('/api/inbox-token', async (req, res) => {
const response = await fetch('https://api.zyphr.dev/v1/subscriber-inbox/token', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ZYPHR_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ external_id: req.user.id }),
});
const { data } = await response.json();
res.json({ token: data.token });
});2. Add the Provider and Components
import {
ZyphrProvider,
InboxBell,
InboxPopover,
} from '@zyphr-dev/inbox-react-native';
function App() {
const [token, setToken] = useState('');
useEffect(() => {
fetch('/api/inbox-token')
.then(r => r.json())
.then(d => setToken(d.token));
}, []);
if (!token) return null;
return (
<ZyphrProvider subscriberToken={token}>
<YourApp />
</ZyphrProvider>
);
}
function Header() {
return (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text>My App</Text>
<InboxPopover />
</View>
);
}Provider Configuration
<ZyphrProvider
subscriberToken={token} // Required
apiUrl="https://api.zyphr.dev" // Default
wsUrl="wss://ws.api.zyphr.dev" // Default
realtime={true} // WebSocket updates (default: true)
theme="system" // 'light' | 'dark' | 'system' (default: 'system')
locale="en" // Date formatting locale (default: 'en')
demo={false} // Demo mode with mock data (default: false)
>
{children}
</ZyphrProvider>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| subscriberToken | string | -- | Required. Subscriber JWT |
| apiUrl | string | https://api.zyphr.dev | API endpoint |
| wsUrl | string | wss://ws.api.zyphr.dev | WebSocket endpoint |
| realtime | boolean | true | Enable real-time updates |
| theme | 'light' \| 'dark' \| 'system' | 'system' | Color scheme (uses Appearance API) |
| locale | string | 'en' | Locale for date formatting |
| demo | boolean | false | Render with mock data |
Theme Detection
Unlike the web version, 'system' theme uses React Native's Appearance API, which works natively on both iOS and Android.
Components
InboxBell
Bell icon button with unread count badge.
import { InboxBell } from '@zyphr-dev/inbox-react-native';
<InboxBell onPress={() => navigation.navigate('Inbox')} />
<InboxBell dot />
<InboxBell size={48} maxCount={50} />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onPress | () => void | -- | Press handler |
| style | ViewStyle | -- | Container style |
| dot | boolean | false | Show dot instead of count |
| maxCount | number | 99 | Max display count |
| bellIcon | ReactNode | -- | Custom bell icon |
| size | number | 40 | Button size |
InboxPopover
Modal-based notification feed triggered by a bell button.
import { InboxPopover } from '@zyphr-dev/inbox-react-native';
<InboxPopover />
<InboxPopover animationType="fade" />
<InboxPopover
visible={isOpen}
onVisibilityChange={setIsOpen}
trigger={<CustomButton />}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| visible | boolean | -- | Controlled visibility |
| onVisibilityChange | (visible: boolean) => void | -- | Visibility callback |
| style | ViewStyle | -- | Modal content style |
| categories | string[] | -- | Filter by categories |
| trigger | ReactNode | -- | Custom trigger element |
| animationType | 'slide' \| 'fade' \| 'none' | 'slide' | Modal animation |
| presentationStyle | string | 'pageSheet' | iOS modal presentation |
InboxFeed
Full notification list with tabs, pull-to-refresh, and infinite scroll via FlatList.
import { InboxFeed } from '@zyphr-dev/inbox-react-native';
<InboxFeed />
<InboxFeed categories={['alerts']} showArchived />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| categories | string[] | -- | Filter by categories |
| style | ViewStyle | -- | Container style |
| showArchived | boolean | false | Include archived |
| emptyState | ReactNode | -- | Custom empty component |
| renderItem | (notification, actions) => ReactNode | -- | Custom renderer |
NotificationItem
Single notification with priority styling, relative timestamps, and action buttons.
import { NotificationItem } from '@zyphr-dev/inbox-react-native';
<NotificationItem
notification={notification}
onPress={() => handlePress(notification)}
/>PreferencesPanel
ScrollView-based notification preference management with Switch toggles.
import { PreferencesPanel } from '@zyphr-dev/inbox-react-native';
<PreferencesPanel onSave={() => Alert.alert('Saved!')} />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| style | ViewStyle | -- | Container style |
| showGlobalPreferences | boolean | true | Show global toggles |
| channelLabels | Record<string, string> | -- | Custom labels |
| onSave | () => void | -- | Save callback |
| onError | (error: Error) => void | -- | Error callback |
| saveButtonText | string | 'Save Preferences' | Button text |
| channels | NotificationChannel[] | -- | Filter channels |
Hooks
All hooks work identically to the web version.
useInbox
import { useInbox } from '@zyphr-dev/inbox-react-native';
function NotificationScreen() {
const {
notifications, unreadCount, isLoading, hasMore, error,
markAsRead, markAllAsRead, archive, delete: remove, loadMore, refresh,
} = useInbox();
return (
<FlatList
data={notifications}
renderItem={({ item }) => (
<Pressable onPress={() => markAsRead(item.id)}>
<Text style={{ fontWeight: item.read_at ? 'normal' : 'bold' }}>
{item.title}
</Text>
</Pressable>
)}
onEndReached={() => hasMore && loadMore()}
onRefresh={refresh}
refreshing={isLoading}
/>
);
}useUnreadCount
import { useUnreadCount } from '@zyphr-dev/inbox-react-native';
function TabBadge() {
const { count } = useUnreadCount();
if (count === 0) return null;
return <View style={styles.badge}><Text>{count}</Text></View>;
}useRealTime
import { useRealTime } from '@zyphr-dev/inbox-react-native';
function ConnectionDot() {
const { connected } = useRealTime();
return <View style={{ backgroundColor: connected ? 'green' : 'red', width: 8, height: 8, borderRadius: 4 }} />;
}usePreferences
import { usePreferences } from '@zyphr-dev/inbox-react-native';
function CustomPreferences() {
const { preferences, updatePreference, savePreferences, hasChanges } = usePreferences();
// Build your own UI with the preference data
}Theming
The package includes a complete light/dark theme system using React context.
Using the Theme
import { useZyphrTheme } from '@zyphr-dev/inbox-react-native';
function CustomComponent() {
const theme = useZyphrTheme();
return (
<View style={{ backgroundColor: theme.colors.background }}>
<Text style={{ color: theme.colors.text, fontSize: theme.fontSize.md }}>
Styled with Zyphr theme
</Text>
</View>
);
}Theme Structure
interface ZyphrTheme {
colors: {
primary, primaryHover, primarySubtle,
background, backgroundSecondary, backgroundHover,
text, textSecondary, textMuted,
border, borderSubtle,
danger, dangerHover, success, warning, urgent, unreadDot,
skeletonBase, skeletonShine,
};
spacing: { xs: 4, sm: 8, md: 12, lg: 16, xl: 24 };
borderRadius: { sm: 6, md: 10, lg: 14 };
fontSize: { xs: 11, sm: 13, md: 15, lg: 17, xl: 20 };
}Custom Colors
Override the theme by importing the color palettes:
import { LIGHT_COLORS, DARK_COLORS } from '@zyphr-dev/inbox-react-native';
// Use as reference for your own themeDifferences from Web Version
| Feature | Web (inbox-react) | React Native (inbox-react-native) |
|---------|--------------------|------------------------------------|
| Styling | CSS + CSS variables | StyleSheet + theme context |
| Popover | Positioned div + backdrop | Modal component |
| Infinite scroll | IntersectionObserver | FlatList.onEndReached |
| Pull to refresh | Not built-in | FlatList.onRefresh |
| Links | window.open() | Linking.openURL() |
| Theme detection | window.matchMedia() | Appearance API |
| Toggles | Custom CSS checkbox | Native Switch |
| Focus trap | DOM focus management | N/A (native modal handles it) |
| Icons | Inline SVG | Unicode text (customizable via props) |
TypeScript
Full TypeScript support with exported types:
import type {
Notification,
ZyphrConfig,
ZyphrTheme,
ZyphrThemeColors,
UseInboxReturn,
} from '@zyphr-dev/inbox-react-native';Requirements
- React Native 0.64+ (for
Intl.RelativeTimeFormatsupport) - Expo SDK 52+ (if using Expo)
- iOS 13+ / Android API 24+
License
MIT
