This is an Expo project created with create-expo-app.
-
Install dependencies
yarn install
-
Start the app
npx expo start
In the output, you'll find options to open the app in a:
- development build
- Android emulator
- iOS simulator
- Expo Go, a limited sandbox for trying out app development with Expo
You can start developing by editing the files inside the app directory. This project uses file-based routing.
When you're ready, run:
yarn run reset-projectThis command will move the starter code to the app-example directory and create a blank app directory where you can start developing.
The theme system is the foundation of the UI, providing consistent styling across the app.
Core values that define the visual identity:
- Colors: Brand colors, feedback colors, text colors, etc.
- Typography: Font families, sizes, weights, etc.
- Spacing: Consistent spacing scale
- Shadows: Elevation levels for depth
The ThemeProvider component provides theme context to the app:
// Example usage
import { ThemeProvider } from "@/theme";
export default function App() {
return (
<ThemeProvider>
<YourApp />
</ThemeProvider>
);
}Custom hooks for accessing theme values:
useTheme(): Access the entire theme objectuseColors(): Access the theme colorsuseTypography(): Access the typography stylesuseSpacing(): Access the spacing scaleuseShadows(): Access the shadow valuesuseDarkMode(): Check if dark mode is active
// Example usage
import { useTheme, useColors } from "@/theme";
function MyComponent() {
const theme = useTheme();
const colors = useColors();
return (
<View
style={{
padding: theme.spacing.md,
backgroundColor: colors.background.default,
}}
>
{/* Component content */}
</View>
);
}Base components with theme integration:
ThemeView: Themed replacement for ViewThemeText: Themed replacement for TextThemeImage: Themed replacement for ImageThemeTouchable: Themed replacement for TouchableOpacityThemeButton: Configurable button componentThemeInput: Themed text input component
// Example usage
import { ThemeView, ThemeText } from "@/components/core";
function MyComponent() {
return (
<ThemeView padded rounded elevation={2}>
<ThemeText variant="h2">Hello World</ThemeText>
</ThemeView>
);
}Specialized components for specific UI patterns:
Card: Container with elevation and rounded cornersTag: Label with optional icon and close buttonSearchInput: Search input with icon and clear buttonArticleCard: Card for displaying article informationFilterTabs: Horizontal tabs for filtering contentActionMenu: Modal menu for item actionsNoItemsFound: Empty state component
// Example usage
import { Card, Tag, SearchInput } from "@/components/ui";
function MyComponent() {
return (
<Card>
<SearchInput placeholder="Search..." />
<Tag label="Important" active />
</Card>
);
}A themed replacement for the standard View component.
<ThemeView
backgroundColor="string" // Optional custom background color
elevation={0 - 5} // Optional shadow elevation (0-5)
padded={true | "xs" | "sm" | "md" | "lg" | "xl"} // Optional padding
margin={true | "xs" | "sm" | "md" | "lg" | "xl"} // Optional margin
rounded={true | "sm" | "md" | "lg" | "full"} // Optional border radius
centered={true | false} // Center children (both axes)
row={true | false} // Use row direction
style={StyleProp} // Optional additional styles
{...ViewProps} // All standard View props
/>A themed replacement for the standard Text component.
<ThemeText
variant="h1"|"h2"|"h3"|"h4"|"h5"|"h6"|"body1"|"body2"|"body1Bold"|"body2Bold"|"subtitle1"|"subtitle2"|"caption"|"overline"|"button"
color="string" // Optional custom text color
align="auto"|"left"|"right"|"center"|"justify" // Text alignment
bold={true|false} // Make text bold
italic={true|false} // Make text italic
underline={true|false} // Add underline
uppercase={true|false} // Transform to uppercase
lowercase={true|false} // Transform to lowercase
capitalize={true|false} // Capitalize first letter of each word
style={StyleProp} // Optional additional styles
{...TextProps} // All standard Text props
/>A configurable button component with various styles.
<ThemeButton
title="string" // Button text
onPress={function} // Press handler
variant="filled"|"outlined"|"text" // Button style variant
size="sm"|"md"|"lg" // Button size
color="primary"|"secondary"|"success"|"error"|"warning"|"info" // Button color
disabled={true|false} // Disable button
loading={true|false} // Show loading indicator
fullWidth={true|false} // Take full width
leftIcon={ReactNode} // Optional icon on the left
rightIcon={ReactNode} // Optional icon on the right
style={StyleProp} // Optional container styles
textStyle={StyleProp} // Optional text styles
uppercase={true|false} // Transform text to uppercase
/><Card elevation={2} padded="md" rounded="md" contentStyle={{ gap: 16 }}>
<ThemeText variant="h6">Card Title</ThemeText>
<ThemeText>Card content goes here.</ThemeText>
</Card><ArticleCard
item={{
id: 1,
title: "Article Title",
source: "Source Name",
readTime: 5,
thumbnail: "https://example.com/image.jpg",
favorite: true,
tags: ["Technology", "Science"],
}}
onPress={() => console.log("Article pressed")}
onMenuPress={() => console.log("Menu pressed")}
/><FilterTabs
currentFilter="all"
onFilterChange={(filter) => console.log("Filter changed:", filter)}
options={[
{ id: "all", label: "All", icon: "list-outline" },
{ id: "favorites", label: "Favorites", icon: "star-outline" },
{ id: "tagged", label: "Tagged", icon: "pricetag-outline" },
]}
/>The app uses Redux with RTK Query for state management and API interactions.
The store is configured with:
- Redux Persist: For persisting state across sessions
- RTK Query: For data fetching and caching
- Custom Middleware: For side effects like token refresh
Feature-specific state modules:
- Auth Slice: Authentication state
- Theme Slice: Theme preference state
- Network Slice: Network connectivity state
RTK Query services for data fetching:
- Items API: CRUD operations for items
- Auth API: Authentication operations
- User API: User profile operations
- Props Interface: Define clear prop interfaces for each component
- Default Props: Provide sensible defaults
- Composition: Build complex components from simpler ones
- Memoization: Use React.memo() for expensive renders
- Hooks: Extract complex logic into custom hooks
- Theme-First: Use the theme system for all styling
- Responsive Design: Support different screen sizes
- Consistent Spacing: Use the spacing scale
- Typography Scale: Use the typography variants
- Color System: Use the color tokens
- Normalized State: Store entities in normalized form
- Selectors: Use selectors to access state
- Action Creators: Use typed action creators
- Immutability: Never mutate state directly
- Side Effects: Handle side effects in middleware or thunks
- Virtualization: Use FlatList for long lists
- Lazy Loading: Load resources on demand
- Memoization: Memoize expensive calculations
- API Caching: Use RTK Query's caching
- Image Optimization: Use appropriate image sizes and formats
- Create a new file in the appropriate directory
- Define the component's props interface
- Implement the component using existing core components
- Document the component's API
- Export the component from the index file
- Extend the appropriate token file (colors.ts, typography.ts, etc.)
- Update the Theme interface if necessary
- Add the new tokens to both light and dark themes
- Create a new slice file
- Define the state interface and initial state
- Implement reducers for state changes
- Export action creators and reducer
- Add the reducer to the root reducer