@myatthirikhin/chat-react-native
v0.1.0
Published
Vendor-neutral React Native chat UI for @myatthirikhin/chat-core. Works in Expo and bare React Native CLI.
Downloads
161
Readme
@myatthirikhin/chat-react-native
Chat UI for React Native. Zero Expo dependencies — works unchanged in Expo and bare React Native CLI.
pnpm add @myatthirikhin/chat-core @myatthirikhin/chat-react-native react-native-svgQuickstart
import { ChatClient } from '@myatthirikhin/chat-core';
import { createSupabaseChatProvider } from '@myatthirikhin/chat-supabase';
import { ChatProvider, ConversationList, ChatScreen } from '@myatthirikhin/chat-react-native';
const chat = new ChatClient({ provider: createSupabaseChatProvider(supabase) });
await chat.connect({ id: userId, name: 'Ana' });
export default function App() {
return (
<ChatProvider client={chat}>
<ChatScreen conversationId={id} myId={userId} />
</ChatProvider>
);
}That's a working chat. Everything else is optional.
<ChatProvider>
One component supplies everything the UI needs, so nothing reaches for a global.
| Prop | Required | What it does |
|---|---|---|
| client | ✅ | The ChatClient. |
| theme | | Your tokens mapped onto ChatTheme. Defaults to a neutral light theme. |
| resolveUsers | | Turns member ids into names and avatars — the SDK doesn't own a users table, you do. |
| filePicker | | Omit and the composer has no attach buttons. |
| recorder | | Omit and the composer has no mic button. |
<ChatProvider
client={chat}
theme={toChatTheme(myAppTheme)}
resolveUsers={async (ids) => (await db.users(ids)).map(u => ({ id: u.id, name: u.fullName, image: u.avatar }))}
filePicker={expoFilePicker}
recorder={expoRecorder}
>Media is optional on purpose. A consumer who installs no media modules gets a text-only composer
rather than a crash — see @myatthirikhin/chat-expo for ready-made implementations.
Components
| | |
|---|---|
| <ChatScreen> | A whole conversation: history, live updates, typing, composer |
| <ConversationList> | The inbox, kept live |
| <MessageList> <MessageBubble> <Composer> <ConversationRow> <TypingIndicator> <Avatar> | The pieces, for building your own |
Both screens take render overrides rather than making you fork them:
<ChatScreen
conversationId={id}
myId={me}
renderMessage={(message, isMine) => isMine ? <MyBubble {...} /> : null} // null → built-in
onPressAttachment={(a) => openInMyViewer(a.url)}
/>Hooks
Use these if you want none of the components:
useMessages(conversationId, myId) // { messages, loading, hasMore, loadOlder, send, retry }
useConversations() // { conversations, loading, reload }
useTyping(conversationId) // { typingUserIds, notifyTyping, stopTyping }
usePresence(userIds) // Record<string, Presence>
useChatUsers(userIds) // Record<string, ChatUser> — cached resolveUsers
useChatClient() useChatTheme() useChatMedia() useChatStyles(factory)useMessages handles the parts that are easy to get wrong: keyset pagination, optimistic sending
keyed by clientId so a retry can't duplicate, live merge, and re-reading history after a
reconnect.
Theming
ChatTheme is deliberately narrow — 13 colors, 4 spacings, 4 radii, 4 text styles — because that
is exactly what these components read. Map your tokens once:
const chatTheme: ChatTheme = {
colors: { accentPrimary: t.brand, bubbleIn: t.card, bubbleOut: t.brandTint, /* … */ },
spacing: { xs: 4, sm: 8, md: 12, lg: 16 },
radius: { sm: 8, md: 10, lg: 16, pill: 999 },
typography: { body: { fontSize: 16 }, button: { fontSize: 16, fontWeight: '600' }, /* … */ },
};Why react-native-svg and not @expo/vector-icons
@expo/vector-icons is an Expo module. Requiring it would mean a bare React Native CLI consumer has
to run npx install-expo-modules and raise their iOS deployment target to 16.4 — a real cost for
eight glyphs.
So the icons are inline SVG paths, and react-native-svg doubles as the gradient renderer for
Avatar. One peer instead of two, and it's the same dependency Stream's own RN SDK requires.
Peers
"react": ">=18.0.0",
"react-native": ">=0.74.0",
"react-native-svg": ">=14.0.0"Nothing else. No Expo, no vendor chat SDK, no navigation library.
License
MIT
