UI Components
UI Components
Section titled “UI Components”Purpose
Section titled “Purpose”The UI Components library provides reusable, styled components that ensure visual consistency and accelerate development across the Zelta Chat app.
When to Use:
- Building new screens or features
- Need consistent styling and behavior
- Implementing common UI patterns (buttons, inputs, modals)
Public API
Section titled “Public API”Button Component
Section titled “Button Component”Location: src/components-next/button/
Props:
interface ButtonProps { title: string; onPress: () => void; variant?: 'primary' | 'secondary' | 'outline' | 'ghost'; size?: 'small' | 'medium' | 'large'; disabled?: boolean; loading?: boolean; leftIcon?: React.ReactNode; rightIcon?: React.ReactNode; style?: StyleProp<ViewStyle>;}Usage:
import { Button } from '@/components-next';
<Button title="Send Message" onPress={handleSend} variant="primary" loading={isSending} leftIcon={<SendIcon />}/>ActionTabs Component
Section titled “ActionTabs Component”Location: src/components-next/action-tabs/
Props:
interface ActionTabsProps { tabs: TabItem[]; activeTab: string; onTabChange: (tab: string) => void;}
interface TabItem { id: string; label: string; count?: number;}Usage:
import { ActionTabs } from '@/components-next';
<ActionTabs tabs={[ { id: 'open', label: 'Open', count: 5 }, { id: 'resolved', label: 'Resolved', count: 12 }, ]} activeTab={activeTab} onTabChange={setActiveTab}/>Spinner Component
Section titled “Spinner Component”Location: src/components-next/spinner/
Props:
interface SpinnerProps { size?: 'small' | 'medium' | 'large'; color?: string;}Usage:
import { Spinner } from '@/components-next';
<Spinner size="medium" color="#3b82f6" />BottomSheet Components
Section titled “BottomSheet Components”Location: src/components-next/sheet-components/
Components:
BottomSheet- Container for bottom sheet modalsBottomSheetHeader- Header with title and close buttonBottomSheetContent- Scrollable content area
Usage:
import { BottomSheet, BottomSheetHeader, BottomSheetContent } from '@/components-next';
<BottomSheet visible={isVisible} onClose={handleClose}> <BottomSheetHeader title="Filter Options" onClose={handleClose} /> <BottomSheetContent> {/* Content */} </BottomSheetContent></BottomSheet>List Components
Section titled “List Components”Location: src/components-next/list-components/
Components:
ListItem- Basic list item with icon and textListSection- Section header for grouped listsListSeparator- Visual separator between items
Behavior and Constraints
Section titled “Behavior and Constraints”Accessibility
Section titled “Accessibility”All components support accessibility features:
- Screen reader labels
- Touch target sizes (minimum 44x44pt)
- Color contrast ratios (WCAG AA)
- Keyboard navigation (where applicable)
Responsiveness
Section titled “Responsiveness”Components adapt to:
- Different screen sizes (phones, tablets)
- Platform differences (iOS vs Android)
- Orientation changes
Performance
Section titled “Performance”- Memoized components prevent unnecessary re-renders
- Optimized for lists with
FlashListintegration - Minimal re-renders with
useMemoanduseCallback
Testing
Section titled “Testing”Component Tests
Section titled “Component Tests”import { render, fireEvent } from '@testing-library/react-native';import { Button } from '@/components-next';
describe('Button', () => { it('should call onPress when tapped', () => { const onPress = jest.fn(); const { getByText } = render(<Button title="Click" onPress={onPress} />);
fireEvent.press(getByText('Click'));
expect(onPress).toHaveBeenCalled(); });
it('should be disabled when loading', () => { const onPress = jest.fn(); const { getByText } = render( <Button title="Click" onPress={onPress} loading /> );
fireEvent.press(getByText('Click'));
expect(onPress).not.toHaveBeenCalled(); });});Further Reading
Section titled “Further Reading”- Theme System - Styling guidelines
- Message Components - Chat-specific components