@mongrov/ui
v0.4.2
Published
Shared UI primitives and compositions for React Native / Expo — Text, Button, Card, Input, and more
Readme
@mongrov/ui
Shared UI primitives and components for React Native applications. Built with NativeWind/Tailwind CSS support.
Installation
npm install @mongrov/ui
# or
pnpm add @mongrov/uiPeer Dependencies
npm install react react-native uniwindFeatures
- Primitives: Base components (Button, Text, Card, Skeleton, Separator)
- State Components: EmptyState, ErrorState, LoadingState
- Status Components: StatusBadge, SyncIndicator, ConnectionIndicator, NetworkBanner
- Auth Components: SocialLoginButton, SSOButton, AuthDivider, TenantPicker
- Renderers: Headless components for messages, attachments, and reactions
Usage
Primitives
import { Button, Text, Card, CardHeader, CardTitle, CardContent } from '@mongrov/ui';
function MyComponent() {
return (
<Card>
<CardHeader>
<CardTitle>Welcome</CardTitle>
</CardHeader>
<CardContent>
<Text variant="body">Hello, world!</Text>
<Button label="Get Started" onPress={() => {}} />
</CardContent>
</Card>
);
}Text Variants
import { Text } from '@mongrov/ui';
<Text variant="h1">Heading 1</Text>
<Text variant="h2">Heading 2</Text>
<Text variant="body">Body text</Text>
<Text variant="muted">Muted text</Text>
<Text variant="code">Code text</Text>Button Variants
import { Button } from '@mongrov/ui';
<Button variant="default" label="Default" onPress={() => {}} />
<Button variant="destructive" label="Delete" onPress={() => {}} />
<Button variant="outline" label="Outline" onPress={() => {}} />
<Button variant="ghost" label="Ghost" onPress={() => {}} />
<Button loading label="Loading..." onPress={() => {}} />State Components
import { EmptyState, ErrorState, LoadingState } from '@mongrov/ui';
// Empty state
<EmptyState
title="No items"
subtitle="Add your first item to get started"
action={{ label: 'Add Item', onPress: () => {} }}
/>
// Error state
<ErrorState
title="Something went wrong"
message="Failed to load data"
onRetry={() => refetch()}
/>
// Loading state
<LoadingState message="Loading..." size="large" />Status Components
import { StatusBadge, SyncIndicator, ConnectionIndicator, NetworkBanner } from '@mongrov/ui';
// Status badge
<StatusBadge label="Active" variant="success" />
<StatusBadge label="Pending" variant="warning" />
<StatusBadge label="Error" variant="error" />
// Sync indicator
<SyncIndicator status="syncing" />
<SyncIndicator status="idle" label="All synced" />
<SyncIndicator status="error" />
// Connection indicator
<ConnectionIndicator status="connected" />
<ConnectionIndicator status="connecting" />
<ConnectionIndicator status="disconnected" />
// Network banner
<NetworkBanner isConnected={false} message="No internet connection" />Auth Components
import { SocialLoginButton, SSOButton, AuthDivider } from '@mongrov/ui';
// Social login buttons
<SocialLoginButton provider="apple" onPress={() => signInWithApple()} />
<SocialLoginButton provider="google" onPress={() => signInWithGoogle()} />
<SocialLoginButton provider="github" onPress={() => signInWithGithub()} />
// SSO button
<SSOButton
onPress={() => signInWithSSO()}
providerName="Okta"
loading={isLoading}
/>
// Auth divider
<AuthDivider text="or continue with" />Tenant Picker
For multi-tenant applications, use TenantPicker and TenantSelector:
import { TenantPicker, TenantSelector } from '@mongrov/ui';
const tenants = [
{ id: 'tenant-1', name: 'Acme Corp', description: 'Main organization' },
{ id: 'tenant-2', name: 'Beta Inc', description: 'Secondary org' },
];
function TenantSettings() {
const [showPicker, setShowPicker] = useState(false);
const [selectedTenant, setSelectedTenant] = useState(tenants[0]);
return (
<>
{/* Inline selector button */}
<TenantSelector
tenant={selectedTenant}
onPress={() => setShowPicker(true)}
placeholder="Select organization"
/>
{/* Modal picker */}
<TenantPicker
visible={showPicker}
tenants={tenants}
selectedId={selectedTenant?.id}
onSelect={(id) => {
setSelectedTenant(tenants.find(t => t.id === id) || null);
setShowPicker(false);
}}
onClose={() => setShowPicker(false)}
title="Select Organization"
/>
</>
);
}Message Renderer
Headless component for rendering chat messages:
import { MessageRenderer, useMessageRenderer } from '@mongrov/ui';
function ChatMessage({ message }) {
return (
<MessageRenderer
message={message}
currentUserId="user-1"
renderContent={({ content }) => <Text>{content}</Text>}
renderDeliveryStatus={({ status }) => <StatusIcon status={status} />}
renderReactions={({ reactions }) => <ReactionBar reactions={reactions} />}
/>
);
}Attachment Renderer
import { AttachmentRenderer } from '@mongrov/ui';
<AttachmentRenderer
attachment={attachment}
renderImage={({ url, name }) => <Image source={{ uri: url }} />}
renderVideo={({ url }) => <VideoPlayer url={url} />}
renderAudio={({ url }) => <AudioPlayer url={url} />}
renderDocument={({ url, name }) => <DocumentLink url={url} name={name} />}
/>Reaction Picker
import { ReactionPicker, EMOJI_CATEGORIES } from '@mongrov/ui';
<ReactionPicker
quickReactions={['👍', '❤️', '😂', '😮', '😢', '😡']}
currentReactions={message.reactions}
onSelect={(emoji) => addReaction(emoji)}
onRemove={(emoji) => removeReaction(emoji)}
/>API Reference
Primitives
| Component | Props | Description |
|-----------|-------|-------------|
| Button | label, variant, size, loading, disabled, onPress | Pressable button |
| Text | variant, className | Typography component |
| Card | className | Card container |
| CardHeader | className | Card header section |
| CardTitle | className | Card title text |
| CardDescription | className | Card description text |
| CardContent | className | Card content section |
| CardFooter | className | Card footer section |
| Skeleton | className | Loading placeholder |
| Separator | orientation, className | Visual separator |
State Components
| Component | Props | Description |
|-----------|-------|-------------|
| EmptyState | title, subtitle, icon, action | Empty list state |
| ErrorState | title, message, onRetry | Error display |
| LoadingState | message, size | Loading indicator |
Status Components
| Component | Props | Description |
|-----------|-------|-------------|
| StatusBadge | label, variant | Status indicator badge |
| SyncIndicator | status, label | Sync status display |
| ConnectionIndicator | status | Connection status |
| NetworkBanner | isConnected, message | Network status banner |
Auth Components
| Component | Props | Description |
|-----------|-------|-------------|
| SocialLoginButton | provider, onPress, loading, disabled | Social login button |
| SSOButton | onPress, providerName, label, loading, disabled | Enterprise SSO button |
| AuthDivider | text | Divider with text |
| TenantPicker | visible, tenants, selectedId, onSelect, onClose, title | Modal tenant picker |
| TenantSelector | tenant, onPress, placeholder | Inline tenant selector |
License
MIT
