@hoddy-ui/core
v2.5.46
Published
Core rich react native components written in typescript
Downloads
430
Maintainers
Readme
@hoddy-ui/core
The complete UI component library for React Native and Expo applications
A comprehensive, production-ready UI component library that follows Material Design principles with a modern twist. Built with TypeScript and optimized for React Native and Expo applications.
✨ Features
- 🎨 20+ Production-Ready Components - From basic buttons to complex forms
- 🌗 Dark Mode Support - Automatic theme switching with system preference detection
- 🔧 TypeScript First - Full type safety and IntelliSense support
- ⚡ Performance Optimized - Minimal bundle size with tree shaking
- 🎯 Accessibility Ready - WCAG compliant components
- 🔌 Highly Customizable - Extensive theming and configuration options
- 📱 Cross Platform - Works seamlessly on iOS and Android
📦 Installation
npm install @hoddy-ui/core
# or
yarn add @hoddy-ui/corePeer Dependencies
Install the required peer dependencies:
npm install @expo/vector-icons @react-native-async-storage/async-storage @react-navigation/native expo-navigation-bar expo-system-ui react-native-safe-area-context react-native-size-matters react-native-reanimatedOr with yarn:
yarn add @expo/vector-icons @react-native-async-storage/async-storage @react-navigation/native expo-navigation-bar expo-system-ui react-native-safe-area-context react-native-size-matters react-native-reanimatedImportant: Make sure to follow the react-native-reanimated installation guide for platform-specific setup as it requires additional configuration for iOS and Android.
🚀 Quick Start
Basic Setup
- Initialize the library (optional but recommended):
import { initialize } from "@hoddy-ui/core";
initialize({
// Google Maps API key for Locator component
googleMapApiKey: "your-google-maps-api-key",
// Edge-to-edge display (affects Android navigation bar styling)
edgeToEdge: false,
// Custom colors
colors: {
primary: {
main: "#6366f1",
light: "#818cf8",
dark: "#4f46e5",
},
},
// Typography settings
typography: {
fontFamily: "Inter-Regular",
fontWeights: {
400: "Inter-Regular",
500: "Inter-Medium",
600: "Inter-SemiBold",
700: "Inter-Bold",
},
},
});- Wrap your app with the theme provider:
import React from "react";
import { UIThemeProvider } from "@hoddy-ui/core";
import App from "./App";
export default function Root() {
return (
<UIThemeProvider>
<App />
</UIThemeProvider>
);
}- Start using components:
import React from "react";
import { View } from "react-native";
import {
Typography,
Button,
TextField,
Animator,
useColors,
useFadeAnimation,
} from "@hoddy-ui/core";
export default function HomeScreen() {
const colors = useColors();
return (
<View style={{ padding: 20, backgroundColor: colors.white[1] }}>
<Animator type="fade" duration={1000}>
<Typography variant="h4" color="primary" gutterBottom={20}>
Welcome to Hoddy UI!
</Typography>
</Animator>
<Animator type="slide" direction="up" delay={200}>
<TextField
label="Email Address"
variant="outlined"
keyboardType="email-address"
gutterBottom={16}
/>
</Animator>
<Animator type="grow" delay={400}>
<Button
title="Get Started"
variant="contained"
color="primary"
onPress={() => console.log("Button pressed!")}
/>
</Animator>
</View>
);
}⚙️ Configuration
Global Configuration
Use the initialize function to configure the library globally:
import { initialize } from "@hoddy-ui/core";
initialize({
// Google Maps API key for map components
googleMapApiKey?: string;
// Custom color palette overrides
colors?: {
primary?: { main: string; light?: string; dark?: string };
secondary?: { main: string; light?: string; dark?: string };
// ... and more color options
};
// Enable edge-to-edge display mode
edgeToEdge?: boolean;
// Typography settings
typography?: {
// Primary font family
fontFamily?: string;
// Font family mappings for each weight (Android support)
fontWeights?: {
100?: string;
200?: string;
300?: string;
400?: string;
500?: string;
600?: string;
700?: string;
800?: string;
900?: string;
};
};
});Configuration Example
initialize({
googleMapApiKey: "AIzaSyBxxxxxxxxxxxxxxxxxxxxxx",
edgeToEdge: true,
colors: {
primary: "#007AFF",
secondary: "#34C759",
},
typography: {
fontFamily: "Inter",
fontWeights: {
400: "Inter-Regular",
500: "Inter-Medium",
600: "Inter-SemiBold",
700: "Inter-Bold",
},
},
});Note: The fontWeights property is particularly useful for Android devices where different font weights require separate font family files. This allows you to map each weight (100-900) to its corresponding font family name.
Theme Configuration
The theme system automatically detects system preferences and can be controlled programmatically:
import { useTheme } from "@hoddy-ui/core";
function ThemeToggle() {
const { themeState, themeDispatch } = useTheme();
const toggleTheme = () => {
themeDispatch({
type: themeState.mode === "dark" ? "light" : "dark",
});
};
return (
<Button
title={`Switch to ${themeState.mode === "dark" ? "Light" : "Dark"} Mode`}
onPress={toggleTheme}
/>
);
}🎨 Theming System
Using Hooks
Access theme colors and state throughout your app:
import { useColors, useTheme } from "@hoddy-ui/core";
function MyComponent() {
const colors = useColors();
const theme = useTheme();
return (
<View
style={{
backgroundColor: colors.white[1],
borderColor: colors.primary.main,
}}
>
<Typography color={theme === "dark" ? "white" : "dark"}>
Current theme: {theme}
</Typography>
</View>
);
}Color Palette
The library includes a comprehensive color system:
const colors = {
// Primary colors
primary: { main: "#007AFF", light: "#5AC8FA", dark: "#0051D5" },
secondary: { main: "#FF3B30", light: "#FF6B6B", dark: "#D70015" },
// Neutral colors
white: ["#FFFFFF", "#F8F9FA", "#E9ECEF"],
black: ["#000000", "#212529", "#495057"],
// Semantic colors
success: { main: "#28A745", light: "#34CE57", dark: "#1E7E34" },
error: { main: "#DC3545", light: "#E74C3C", dark: "#C82333" },
warning: { main: "#FFC107", light: "#FFD54F", dark: "#FF8F00" },
// Utility colors
textPrimary: { main: "#212529" },
textSecondary: { main: "#6C757D" },
divider: { main: "#DEE2E6" },
};🧩 Components
Layout & Structure
SafeAreaView- Safe area wrapper for different devicesGrid&GridItem- Flexible grid layout systemFormWrapper- Form container with validation support
Navigation & Status
AdaptiveStatusBar- Theme-aware status bar- Navigation utilities via hooks
Typography
Typography- Comprehensive text component with variants (h1-h6, body1-body2, caption)
Form Components
TextField- Material Design text input with variantsTextField2- Alternative text field designOTPInput- One-Time Password input with auto-advance and paste supportLocator- Location picker with Google Maps integration
Interactive Elements
Button- Primary action buttons with variantsIconButton- Icon-only buttonsLinkButton- Text-based link buttons
Feedback & Communication
FlashMessage- Toast notifications and alertsAlertX- Customizable alert dialogsSpinner- Loading indicators
Data Display
Avatar- User profile images and placeholdersList,ListItem,ListItemText- List components
Overlays & Modals
Popup- Modal dialogs and bottom sheets
Animation
Animator- Layout animations and transitions
📖 Component API Reference
Typography
A versatile text component supporting multiple variants and styling options.
Props:
| Prop | Type | Default | Description |
| -------------- | --------------------------------------------------------------------------------- | --------- | ----------------------------- |
| variant | "h1" \| "h2" \| "h3" \| "h4" \| "h5" \| "h6" \| "body1" \| "body2" \| "caption" | "body1" | Text style variant |
| color | string | "dark" | Text color from theme palette |
| align | "left" \| "center" \| "right" | "left" | Text alignment |
| gutterBottom | number | 0 | Bottom margin in pixels |
| fontWeight | number | 400 | Font weight |
| textCase | "uppercase" \| "lowercase" \| "capitalize" | null | Text transformation |
Example:
<Typography variant="h4" color="primary" gutterBottom={20}>
Welcome to Hoddy UI
</Typography>Button
A comprehensive button component with multiple variants and states.
Props:
| Prop | Type | Default | Description |
| ---------- | ------------------------------------- | ------------- | -------------------------- |
| title | string | - | Button text |
| variant | "contained" \| "outlined" \| "text" | "contained" | Button variant |
| color | string | "primary" | Button color from theme |
| size | "small" \| "medium" \| "large" | "medium" | Button size |
| disabled | boolean | false | Disabled state |
| loading | boolean | false | Loading state with spinner |
| onPress | () => void | - | Press handler |
| start | ReactNode | - | Leading icon/element |
| end | ReactNode | - | Trailing icon/element |
Example:
<Button
title="Submit"
variant="contained"
color="primary"
loading={isLoading}
onPress={handleSubmit}
/>IconButton
A button component that displays only an icon.
Props:
| Prop | Type | Default | Description |
| ----------------- | --------------------- | ------------ | ------------------------- |
| icon | string | - | Icon name |
| iconType | "material" \| "ion" | "material" | Icon library to use |
| size | number | 24 | Icon size in pixels |
| color | string | "dark" | Icon color from theme |
| bg | boolean | false | Show background circle |
| elevation | number | 0 | Shadow elevation |
| disabled | boolean | false | Disabled state |
| onPress | () => void | - | Press handler |
| style | ViewStyle | {} | Icon style overrides |
| containerStyles | ViewStyle | {} | Container style overrides |
Example:
<IconButton
icon="star"
iconType="ion"
size={28}
color="primary"
bg={true}
elevation={2}
onPress={() => console.log("Starred!")}
/>LinkButton
A text-based button component for navigation or secondary actions.
Props:
| Prop | Type | Default | Description |
| ------------ | ------------ | -------- | --------------------- |
| title | string | - | Button text |
| color | string | "blue" | Text color from theme |
| fontSize | number | 12 | Font size |
| fontWeight | string | "400" | Font weight |
| disabled | boolean | false | Disabled state |
| onPress | () => void | - | Press handler |
| style | TextStyle | {} | Text style overrides |
Example:
<LinkButton
title="Forgot Password?"
color="primary"
fontSize={14}
onPress={() => navigation.navigate("ForgotPassword")}
/>TextField
A Material Design text input component with comprehensive features.
Props:
| Prop | Type | Default | Description |
| -------------- | -------------------------------------- | ------------ | --------------------- |
| label | string | - | Input label |
| variant | "outlined" \| "filled" \| "standard" | "outlined" | Input variant |
| value | string | - | Input value |
| onChangeText | (text: string) => void | - | Change handler |
| placeholder | string | - | Placeholder text |
| error | boolean | false | Error state |
| helperText | string | - | Helper/error text |
| disabled | boolean | false | Disabled state |
| multiline | boolean | false | Multiline input |
| start | ReactNode | - | Leading icon/element |
| end | ReactNode | - | Trailing icon/element |
Example:
<TextField
label="Email Address"
variant="outlined"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
error={!!emailError}
helperText={emailError}
/>OTPInput
A specialized input component for One-Time Password entry with auto-advance, paste support, and backspace handling.
Props:
| Prop | Type | Default | Description |
| ---------- | ------------------------------------- | ------------ | -------------------------------- |
| length | number | 6 | Number of OTP digits |
| onChange | (value: string) => void | - | Change handler for OTP value |
| value | string | "" | Current OTP value |
| variant | "outlined" \| "text" \| "contained" | "outlined" | Input variant style |
| spacing | number | 1 | Spacing between input boxes |
| size | number | 45 | Size of each input box in pixels |
Features:
- Auto-advance: Automatically moves to next input after digit entry
- Paste support: Handles pasting of complete OTP codes
- Backspace handling: Moves to previous input on backspace
- Number-only input: Automatically filters non-numeric characters
- Customizable styling: Supports different variants and sizes
Example:
const [otp, setOtp] = useState('');
<OTPInput
length={6}
value={otp}
onChange={setOtp}
variant="outlined"
size={50}
spacing={2}
/>
// Usage with form validation
<OTPInput
length={4}
value={otp}
onChange={(value) => {
setOtp(value);
if (value.length === 4) {
verifyOTP(value);
}
}}
variant="contained"
/>Locator
A location picker component with Google Maps integration.
Props:
| Prop | Type | Default | Description |
| -------------------- | ---------------------------------- | ------------- | -------------------------- |
| onLocationSelected | (location: LocationType) => void | - | Location selection handler |
| label | string | - | Input label |
| variant | "contained" \| "outlined" | "contained" | Input variant |
| location | LocationType | - | Current location |
| country | string | "ng" | Country code for search |
| error | boolean | false | Error state |
Example:
<Locator
label="Select Location"
onLocationSelected={(location) => setSelectedLocation(location)}
country="us"
/>SafeAreaView
A safe area wrapper component that handles device-specific safe areas.
Props:
| Prop | Type | Default | Description |
| ---------- | ----------- | ------- | ------------------------- |
| children | ReactNode | - | Child components |
| style | ViewStyle | {} | Container style overrides |
Example:
<SafeAreaView style={{ backgroundColor: "white" }}>
<YourContent />
</SafeAreaView>AdaptiveStatusBar
A status bar component that automatically adapts to the current theme.
Props:
| Prop | Type | Default | Description |
| ------------- | --------- | ------- | ------------------------------------- |
| translucent | boolean | false | Whether the status bar is translucent |
Example:
<AdaptiveStatusBar translucent={true} />AlertX
A customizable alert component for displaying important messages.
Props:
| Prop | Type | Default | Description |
| -------------- | --------------------------------------------- | ------------- | ------------------------- |
| type | "info" \| "warning" \| "success" \| "error" | "info" | Alert type |
| variant | "contained" \| "outlined" | "contained" | Alert variant |
| title | string | - | Alert title |
| body | string | - | Alert message |
| gutterBottom | number | 0 | Bottom margin in pixels |
| style | ViewStyle | {} | Container style overrides |
Example:
<AlertX
type="success"
title="Success!"
body="Your profile has been updated successfully."
gutterBottom={20}
/>Avatar
A component for displaying user avatars with support for images, labels, or default icons.
Props:
| Prop | Type | Default | Description |
| --------- | --------------------------- | ------------- | --------------------------- |
| source | ImageSourcePropType | - | Image source |
| label | string | - | Text label (first letter) |
| size | number | 48 | Avatar size in pixels |
| color | string | "dark" | Background color from theme |
| variant | "contained" \| "outlined" | "contained" | Avatar variant |
| style | ViewStyle | {} | Container style overrides |
Example:
<Avatar
source={{ uri: 'https://example.com/avatar.jpg' }}
size={64}
/>
<Avatar
label="John Doe"
color="primary"
size={48}
/>Grid & GridItem
Flexible grid layout components for organizing content.
Grid Props:
| Prop | Type | Default | Description |
| ---------- | ----------- | ------- | ------------------------- |
| children | ReactNode | - | GridItem components |
| spacing | number | 1 | Spacing between items |
| style | ViewStyle | {} | Container style overrides |
GridItem Props:
| Prop | Type | Default | Description |
| ------------ | ---------------------------------------- | ------- | ------------------------- |
| children | ReactNode | - | Item content |
| col | number | 2 | Number of columns to span |
| alignItems | "center" \| "flex-start" \| "flex-end" | - | Item alignment |
| spacing | number | 1 | Item spacing |
| style | ViewStyle | {} | Item style overrides |
Example:
<Grid spacing={2}>
<GridItem col={2}>
<Typography>Full width item</Typography>
</GridItem>
<GridItem col={4} alignItems="center">
<Typography>Quarter width item</Typography>
</GridItem>
<GridItem col={4}>
<Typography>Another quarter width</Typography>
</GridItem>
</Grid>FormWrapper
A wrapper component that provides keyboard handling and scrolling for forms.
Props:
| Prop | Type | Default | Description |
| ------------------------ | ------------------------------- | ------------------ | --------------------------- |
| children | ReactNode | - | Form content |
| mode | "scroll" \| "static" | "scroll" | Wrapper mode |
| behavior | KeyboardAvoidingView behavior | Platform-dependent | Keyboard avoidance behavior |
| keyboardVerticalOffset | number | 10 | Keyboard offset |
| contentContainerStyle | ViewStyle | {} | ScrollView content style |
| style | ViewStyle | {} | Container style |
| onScroll | (event) => void | - | Scroll event handler |
Example:
<FormWrapper mode="scroll" keyboardVerticalOffset={20}>
<TextField label="Name" />
<TextField label="Email" />
<Button title="Submit" />
</FormWrapper>List, ListItem & ListItemText
Components for displaying structured lists of data.
List Props:
| Prop | Type | Default | Description |
| ---------- | ----------- | ------- | ------------------------- |
| children | ReactNode | - | ListItem components |
| style | ViewStyle | {} | Container style overrides |
ListItem Props:
| Prop | Type | Default | Description |
| ---------- | ------------ | ------- | ------------------------- |
| children | ReactNode | - | Item content |
| link | boolean | false | Show arrow indicator |
| divider | boolean | false | Show bottom border |
| onPress | () => void | - | Press handler |
| index | number | 1 | Item index for animations |
| style | ViewStyle | {} | Item style overrides |
ListItemText Props:
| Prop | Type | Default | Description |
| ---------------- | ----------------- | ------- | ------------------------- |
| primary | string | - | Primary text |
| secondary | string | - | Secondary text |
| divider | boolean | false | Show bottom border |
| primaryProps | TypographyProps | {} | Primary text props |
| secondaryProps | TypographyProps | {} | Secondary text props |
| style | ViewStyle | {} | Container style overrides |
Example:
<List>
<ListItem link onPress={() => navigate("Profile")}>
<ListItemText primary="Profile Settings" secondary="Manage your account" />
</ListItem>
<ListItem divider>
<ListItemText primary="Notifications" />
</ListItem>
</List>Popup
A modal component for overlays, dialogs, and bottom sheets.
Props:
| Prop | Type | Default | Description |
| ------------------------ | ------------------- | ------- | ------------------------- |
| open | boolean | - | Whether popup is visible |
| onClose | () => void | - | Close handler |
| title | string | - | Popup title |
| children | ReactNode | - | Popup content |
| sheet | boolean \| number | false | Bottom sheet mode/height |
| bare | boolean | false | Hide header and padding |
| keyboardVerticalOffset | number | - | Keyboard avoidance offset |
| onModalShow | () => void | - | Callback when modal shows |
| onModalHide | () => void | - | Callback when modal hides |
| style | ViewStyle | {} | Container style overrides |
Example:
<Popup
open={isOpen}
onClose={() => setIsOpen(false)}
title="Confirm Action"
sheet={400}
onModalShow={() => console.log("Modal is now visible")}
onModalHide={() => console.log("Modal is now hidden")}
>
<Typography>Are you sure you want to delete this item?</Typography>
<Button title="Delete" color="error" />
<Button title="Cancel" variant="outlined" />
</Popup>Spinner
A loading indicator component with customizable appearance.
Props:
| Prop | Type | Default | Description |
| ------------ | -------------------- | ----------- | ------------------------- |
| size | "small" \| "large" | "large" | Spinner size |
| color | string | "primary" | Spinner color from theme |
| label | string | - | Loading text |
| fullscreen | boolean | false | Cover entire screen |
| style | ViewStyle | {} | Container style overrides |
Example:
<Spinner size="large" color="primary" label="Loading..." fullscreen={true} />Animator
A unified component that provides a single interface for all animation types with generic props. Built with react-native-reanimated for optimal performance and smooth animations.
Features:
- Single Component: One component handles all animation types
- Generic Props: Consistent prop naming across all animations (e.g.,
closeAfterinstead of animation-specific names) - Modular Hooks: Animation logic is separated into individual custom hooks
- Type Safety: Full TypeScript support with proper typing
- Performance: Built with react-native-reanimated for native performance
- Smooth Animations: Runs on the UI thread for 60fps animations
Requirements:
Requires react-native-reanimated as peer dependencies. Make sure to follow the react-native-reanimated installation guide for platform-specific setup.
Generic Props:
All animation types support these generic props:
| Prop | Type | Default | Description |
| ------------ | --------------------------------------------------------------------------- | ------- | ------------------------------------------------------------- |
| type | "fade" \| "grow" \| "slide" \| "blink" \| "float" \| "roll" \| "thrownup" | - | Animation type |
| duration | number | 500 | Animation duration in milliseconds |
| delay | number | 0 | Delay before animation starts |
| closeAfter | number \| null | null | Time after which the exit animation starts (null for no exit) |
| style | ViewStyle | {} | Additional styles for the animated view |
Animation-Specific Props:
Slide Animation:
direction:"up" \| "down" \| "left" \| "right"initialValue: Custom initial position value
Grow Animation:
initialScale: Starting scale (default: 0)
Blink Animation:
blinkDuration: Duration of one blink cycleminOpacity: Minimum opacity valuemaxOpacity: Maximum opacity value
Float Animation:
closeDuration: Duration of exit animationfloatDistance: Distance to float up/downfloatDuration: Duration of one float cycle
Roll Animation:
initialTranslateY: Initial vertical positioninitialRotate: Initial rotation value
Examples:
// Fade animation
<Animator type="fade" duration={1000} closeAfter={3000}>
<Text>This will fade in and out</Text>
</Animator>
// Slide animation
<Animator type="slide" direction="up" duration={800} closeAfter={2000}>
<View>This will slide up from bottom</View>
</Animator>
// Grow animation
<Animator type="grow" initialScale={0.5} duration={600}>
<Button>This will grow from 50% scale</Button>
</Animator>
// Blink animation (continuous)
<Animator type="blink" blinkDuration={1000} minOpacity={0.3}>
<Icon>This will blink continuously</Icon>
</Animator>
// Float animation
<Animator type="float" floatDistance={20} floatDuration={2000} closeAfter={5000}>
<View>This will float up and down</View>
</Animator>
// Roll animation
<Animator type="roll" initialRotate="45deg" duration={800}>
<Image>This will roll and rotate</Image>
</Animator>
// Thrown up animation
<Animator type="thrownup" delay={500} closeAfter={4000}>
<Notification>This will spring up from bottom</Notification>
</Animator>Available Animation Types:
- fade: Simple fade in/out using opacity (native performance)
- grow: Scale-based growth animation with easing
- slide: Directional slide animations from screen edges
- blink: Continuous opacity blinking with repeat
- float: Floating up/down motion with fade effects
- roll: Combined rotation and translation effects
- thrownup: Spring-based upward animation with physics
All animations run on the UI thread for optimal performance and smooth 60fps animations.
Using Animation Hooks Directly:
You can also use the animation hooks directly for custom implementations with react-native-reanimated:
import { useFadeAnimation, useSlideAnimation } from "@hoddy-ui/core";
import Animated from "react-native-reanimated";
const MyComponent = () => {
const { animatedStyle } = useFadeAnimation({
duration: 800,
closeAfter: 2000,
});
return (
<Animated.View style={animatedStyle}>
<Text>Custom animated content</Text>
</Animated.View>
);
};Performance Benefits:
With react-native-reanimated, all animations:
- Run on the UI thread for better performance
- Maintain 60fps even during JavaScript thread blocking
- Use native drivers automatically
- Support worklets for complex animation logic
- Provide smooth gestures and interactions
Migration from Legacy API:
Replace old individual animation components:
// Old way
<AnimatedFade fadeOutAfter={2000}>
<Text>Content</Text>
</AnimatedFade>
// New way
<Animator type="fade" closeAfter={2000}>
<Text>Content</Text>
</Animator>FlashMessage
Display toast notifications and alerts.
Props:
| Prop | Type | Default | Description |
| ---------- | --------------------------------------------- | -------- | ---------------------- |
| message | string | - | Message text |
| type | "success" \| "error" \| "warning" \| "info" | "info" | Message type |
| duration | number | 3000 | Display duration in ms |
| position | "top" \| "bottom" | "top" | Message position |
Usage:
import { showMessage } from "@hoddy-ui/core";
// Show a success message
showMessage({
message: "Profile updated successfully!",
type: "success",
});🔧 Hooks
useColors
Access the current theme's color palette:
import { useColors } from "@hoddy-ui/core";
function MyComponent() {
const colors = useColors();
return (
<View style={{ backgroundColor: colors.primary.main }}>
{/* Component content */}
</View>
);
}useTheme
Access and control the current theme:
import { useTheme } from "@hoddy-ui/core";
function ThemeAwareComponent() {
const { themeState, themeDispatch } = useTheme();
const toggleTheme = () => {
themeDispatch({
type: themeState.mode === "dark" ? "light" : "dark",
});
};
return <Button title="Toggle Theme" onPress={toggleTheme} />;
}useNavScreenOptions
Get theme-aware navigation screen options:
import { useNavScreenOptions } from "@hoddy-ui/core";
function MyScreen() {
const screenOptions = useNavScreenOptions("stack");
// Use with React Navigation
return (
<Stack.Screen name="Home" component={HomeScreen} options={screenOptions} />
);
}Animation Hooks
Access animation logic directly for custom implementations using react-native-reanimated:
useFadeAnimation
import { useFadeAnimation } from "@hoddy-ui/core";
import Animated from "react-native-reanimated";
function FadeComponent() {
const { animatedStyle } = useFadeAnimation({
duration: 800,
closeAfter: 2000,
});
return (
<Animated.View style={animatedStyle}>
<Text>This will fade in and out</Text>
</Animated.View>
);
}useSlideAnimation
import { useSlideAnimation } from "@hoddy-ui/core";
import Animated from "react-native-reanimated";
function SlideComponent() {
const { animatedStyle } = useSlideAnimation({
direction: "up",
duration: 600,
initialValue: 100,
});
return (
<Animated.View style={animatedStyle}>
<Text>This will slide up</Text>
</Animated.View>
);
}useGrowAnimation
import { useGrowAnimation } from "@hoddy-ui/core";
import Animated from "react-native-reanimated";
function GrowComponent() {
const { animatedStyle } = useGrowAnimation({
duration: 500,
initialScale: 0.5,
});
return (
<Animated.View style={animatedStyle}>
<Text>This will grow from 50% scale</Text>
</Animated.View>
);
}Other Animation Hooks
useBlinkAnimation- For continuous blinking effectsuseFloatAnimation- For floating up/down motionuseRollAnimation- For rotation and translation effectsuseThrownUpAnimation- For spring-based upward animations
All animation hooks accept similar configuration objects with properties like duration, delay, and animation-specific options. They return animatedStyle objects that work with Animated.View from react-native-reanimated for optimal performance.
🎯 Advanced Usage
Custom Theme Provider
Create your own theme provider with custom configurations:
import { UIThemeProvider, initialize } from "@hoddy-ui/core";
// Initialize with custom configuration
initialize({
fontFamily: "CustomFont-Regular",
colors: {
primary: { main: "#FF6B6B" },
secondary: { main: "#4ECDC4" },
},
});
function App() {
return (
<UIThemeProvider>
<YourAppContent />
</UIThemeProvider>
);
}Form Validation Example
import React, { useState } from "react";
import { View } from "react-native";
import { TextField, Button, FormWrapper } from "@hoddy-ui/core";
function LoginForm() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [errors, setErrors] = useState({});
const validate = () => {
const newErrors = {};
if (!email) newErrors.email = "Email is required";
if (!password) newErrors.password = "Password is required";
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = () => {
if (validate()) {
// Handle form submission
}
};
return (
<FormWrapper>
<TextField
label="Email"
value={email}
onChangeText={setEmail}
error={!!errors.email}
helperText={errors.email}
keyboardType="email-address"
/>
<TextField
label="Password"
value={password}
onChangeText={setPassword}
error={!!errors.password}
helperText={errors.password}
secureTextEntry
/>
<Button
title="Login"
onPress={handleSubmit}
variant="contained"
color="primary"
/>
</FormWrapper>
);
}📱 Platform Compatibility
- React Native: ≥ 0.71.8
- Expo: SDK 48+
- iOS: 11.0+
- Android: API 21+ (Android 5.0)
- TypeScript: ≥ 5.0.4
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
📄 License
MIT © Hoddy Inc
🔗 Links
Need help? Open an issue or check out our examples.
