clarityvision-react-native-components
v0.2.27
Published
Base components for building react native apps on clarity vision
Maintainers
Readme
clarityvision-react-native-components
Reusable React Native components for Clarity Vision — built on the Claritybase design system.
Themed primitives + 50+ components (forms, navigation, feedback, display) with consistent intent colors, size tokens, and a deep-merge override system so each app can customize without forking.
Install
yarn add clarityvision-react-native-components
# or
npm install clarityvision-react-native-componentsPeer dependencies
Install these in the consuming app:
yarn add react-native-svg react-native-safe-area-context| Peer | Why |
| --------------------------------- | ---------------------------------------------------- |
| react, react-native | Required. |
| react-native-svg | Tabler icons, CircularProgress, future SVG visuals.|
| react-native-safe-area-context | Optional. Recommended for SafeAreaView use. |
After installing on iOS:
cd ios && pod installIf
pod installfails with a CocoaPods version mismatch, see example/Gemfile for the working pin (CocoaPods>= 1.16+nkffor Ruby 3.4).
Setup
Wrap your app with ThemeProvider. If you use toasts, also wrap with ToastProvider.
import {
ThemeProvider,
ToastProvider,
} from 'clarityvision-react-native-components';
export default function App() {
return (
<ThemeProvider mode="light">
<ToastProvider position="top">
<YourApp />
</ToastProvider>
</ThemeProvider>
);
}Theming
Every color, font, radius, spacing, and border value is a token. Override only what you want:
<ThemeProvider
mode="dark"
theme={{
typography: { fontFamily: 'Inter' },
colors: {
light: { bg: { brandSolid: '#FF6B00' } },
dark: { bg: { brandSolid: '#FF8A33' } },
},
radii: { md: 12 },
}}
>
...
</ThemeProvider>Read the resolved theme inside any component:
import { useTheme } from 'clarityvision-react-native-components';
function MyView() {
const theme = useTheme();
return (
<View backgroundColor={theme.colors.bg.brand}>
<Text color={theme.colors.text.brand}>Hello</Text>
</View>
);
}Components
All components support intent (brand / success / warning / error / neutral) where it makes
sense, plus the standard layout props (margin*, padding*, flex, etc.). See each component's
TypeScript interface for the full prop list.
Primitives
View, Text, TouchableOpacity, ScrollView, Image — themed RN wrappers with inline layout props.
<View flex={1} padding={16} backgroundColor={theme.colors.bg.primary}>
<Text size="lg" weight="semibold" color={theme.colors.text.primary}>
Hello
</Text>
</View>Buttons
Button, IconButton, Fab, SocialButton.
<Button text="Save" intent="success" onPress={save} />
<Button text="Continue" rightIcon={<IconArrowRight />} onPress={next} />
<IconButton icon={<IconDots />} variant="ghost" accessibilityLabel="More" onPress={...} />
<Fab icon={<IconPlus />} text="Compose" onPress={...} />
<SocialButton provider="google" onPress={signInWithGoogle} fullWidth />Inputs
Input, InputPassword, InputSearch, InputPhoneNumber, InputAmount, InputOTP.
<Input label="Email" placeholder="[email protected]" value={email} onChangeText={setEmail} error={err} />
<InputPassword label="Password" value={pw} onChangeText={setPw} />
<InputPhoneNumber
defaultCountryCode="+234"
value={phone.number}
onChangeText={setPhone} // → { countryCode, number }
enabledCountries={['NG', 'GH', 'KE']}
/>
<InputAmount defaultCurrency="USD" value={amount.amount} onChangeText={setAmount} />
<InputOTP length={6} value={code} onChange={setCode} onComplete={verify} />Form widgets
CheckBox, CheckCircle, Radio, ToggleSwitch, Counter, Slider, RangeSlider, Dropdown.
<CheckBox label="Accept terms" value={accept} onChange={setAccept} />
<CheckCircle label="Option" description="Subtitle" indeterminate />
<ToggleSwitch label="Notifications" value={on} onChange={setOn} size="md" />
<Counter value={qty} onChange={setQty} min={0} max={10} />
<Slider value={vol} onChange={setVol} min={0} max={100} step={5} />
<RangeSlider values={range} onChange={setRange} minDistance={5} />
<Dropdown
label="Country"
value={country}
onChange={setCountry}
options={[{ label: 'Nigeria', value: 'NG' }, ...]}
searchable
/>Navigation & layout
Tabs, BottomTabs, Stepper, Accordion, Divider, Modal, BottomSheet, CountryModal,
DropdownMenu, Tooltip.
<Tabs value={tab} onChange={setTab} items={[
{ value: 'overview', label: 'Overview', content: <Overview /> },
{ value: 'activity', label: 'Activity', content: <Activity /> },
]} />
<BottomTabs items={[
{ value: 'home', label: 'Home', icon: ({ color }) => <IconHome color={color} />, content: <Home /> },
...
]} />
<Stepper active={step} steps={[
{ label: 'Account', content: <AccountForm /> },
{ label: 'Verify', content: <VerifyForm /> },
]} />
<Accordion items={[
{ id: 'q1', title: 'What is this?', content: <Text>...</Text> },
]} multiple />
<BottomSheet show={open} onClose={...} snapPoints={['25%', '60%', '90%']} snapIndex={snap} />
<DropdownMenu trigger={<MoreButton />} items={[
{ label: 'Edit', icon: <IconEdit />, onPress: ... },
'separator',
{ label: 'Delete', icon: <IconTrash />, destructive: true, onPress: ... },
]} />
<Tooltip
trigger={<Button text="?" />}
title="Heads up"
description="Tooltips can be rich coachmarks."
primaryAction={{ label: 'Got it' }}
/>Display
Badge, Tag, Avatar, AvatarGroup, Card, ProgressBar, CircularProgress, Stat, ListItem,
EmptyState.
<Badge label="New" intent="brand" leftIcon={<IconStar size={12} />} />
<Tag label="Pending" intent="warning" onClose={remove} />
<Avatar name="Franklin Nwanze" status="online" />
<AvatarGroup max={4} items={[{ name: 'Alice' }, { name: 'Bob' }, ...]} />
<Card variant="elevated" onPress={open}>...</Card>
<ProgressBar value={62} showLabel labelPosition="right" />
<CircularProgress value={85} size={88} showLabel />
<Stat label="Revenue" value="$12,453" trend={{ value: 12.5 }} />
<ListItem title="Alice" subtitle="[email protected]" leading={<Avatar name="Alice" />} />
<EmptyState icon={<IconInbox size={48} />} title="No messages" />Feedback
Spinner, Alert, ToastProvider + useToast.
<Spinner size="md" intent="brand" />
<Alert intent="success" title="Saved" description="Your changes have been saved." />
const toast = useToast();
toast.success('Saved!');
toast.error('Something went wrong');
toast.show({ message: 'Upload paused', intent: 'warning', duration: 0 }); // stickyFile upload & waveform
FileUpload, FileItem, FileTypeIcon, Waveform (+ generateWaveformData helper).
This lib renders the UI; consumers wire their own picker (react-native-document-picker,
expo-document-picker, etc.) to onPickPress.
<FileUpload
variant="big"
state="uploading"
file={{ name: 'Q3.pdf' }}
progress={62}
onPickPress={pickFile}
/>
<Waveform data={amplitudes} progress={position} onSeek={seek} />Helpers
import {
// Theme
useTheme, defaultTheme, deepMerge,
// Countries
getCountries, getCountryByCode, getCountryByCallingCode, getFlagEmoji,
searchCountries, filterCountries,
// Currencies
getCurrencySymbol, formatAmount, parseAmount,
// Files
formatBytes, getFileExtension,
// Color intents
resolveIntent,
// Misc
defined,
} from 'clarityvision-react-native-components';Example app
A live playground exists in example/ — exercises every component in light + dark mode.
yarn install
cd example/ios && pod install && cd ../..
yarn workspace clarityvision-react-native-components-example start
yarn workspace clarityvision-react-native-components-example ios
# or androidContributing
License
MIT
Built with create-react-native-library.
