News App Tab
A modern tab based on Expo Router, and Material Top Tabs. Features a beautiful dark theme, smooth animations, and responsive design similar to popular news apps.
✨ Features
- Material Top Tabs Navigation - Smooth horizontal scrolling between categories
- Auto-scroll Active Tab - Active tab automatically scrolls into view when swiping
- Swipe Navigation - Natural swipe gestures between tabs
📦 Required Dependencies
Install the following packages in your Expo/React Native project:
bash
# Core navigation dependencies
npm install @react-navigation/material-top-tabs react-native-tab-view
# Required peer dependencies (if not already installed)
npm install @react-navigation/native @react-navigation/bottom-tabs
npm install react-native-screens react-native-safe-area-context
npm install react-native-gesture-handler react-native-reanimatedAdditional Dependencies
These should already be included in most Expo projects:
bash
npm install @expo/vector-icons expo-router🚀 Installation
- Copy the news-app folder to your
app/directory:
app/
├── news-app/
│ ├── _layout.tsx
│ ├── top.tsx
│ ├── pga.tsx
│ ├── atp.tsx
│ ├── wnba.tsx
│ ├── ucl.tsx
│ ├── uel.tsx
│ ├── nfl.tsx
│ └── nhl.tsx
- Add the route to your main navigation (e.g., in your index page):
📁 Project Structure
app/news-app/
├── _layout.tsx # Material Top Tabs layout with custom header
├── top.tsx
├── pga.tsx
├── atp.tsx
├── wnba.tsx
├── ucl.tsx
├── uel.tsx
├── nfl.tsx
└── nhl.tsx
🔧 How to Add New Tabs
1. Create a New Tab Component
Create a new file in app/news-app/ (e.g., mls.tsx):
typescript
import React from 'react';
import {
Image,
Text,
TouchableOpacity,
View,
ScrollView
} from 'react-native';
const mlsNews = [
{
title: "MLS Cup Final Preview",
timeAgo: "1h ago",
readTime: "5m read",
image: "https://picsum.photos/300/200?random=80"
},
// Add more news items...
];
const NewsCard = ({ item }) => {
return (
<TouchableOpacity
style={{
backgroundColor: '#1a1a1a',
borderRadius: 16,
marginBottom: 16,
overflow: 'hidden',
marginHorizontal: 16
}}
>
<Image
source={{ uri: item.image }}
style={{
width: '100%',
height: 120,
backgroundColor: '#2a2a2a'
}}
resizeMode="cover"
/>
<View style={{ padding: 16 }}>
<Text style={{
color: '#ffffff',
fontSize: 16,
fontWeight: '600',
lineHeight: 22,
marginBottom: 8
}}>
{item.title}
</Text>
<View style={{
flexDirection: 'row',
alignItems: 'center',
gap: 16
}}>
<Text style={{ color: '#888', fontSize: 14 }}>
{item.timeAgo}
</Text>
<Text style={{ color: '#888', fontSize: 14 }}>
{item.readTime}
</Text>
</View>
</View>
</TouchableOpacity>
);
};
export default function MLSTab() {
return (
<ScrollView style={{ flex: 1, backgroundColor: '#000' }}>
<View style={{ paddingTop: 16 }}>
<Text style={{
color: '#ffffff',
fontSize: 24,
fontWeight: '600',
marginBottom: 16,
paddingHorizontal: 16
}}>
MLS News
</Text>
{mlsNews.map((item, index) => (
<NewsCard key={index} item={item} />
))}
</View>
</ScrollView>
);
}2. Add to Layout
Update _layout.tsx to include your new tab:
typescript
<MaterialTopTabs.Screen
name="mls"
options={{ title: "MLS" }}
/>Add it in the screens section alongside the other tabs.
🎨 Customization Options
Changing Colors
Update the color scheme in _layout.tsx:
typescript
// Change active tab color
borderBottomColor: isFocused ? '#YOUR_COLOR' : 'transparent'
// Change text colors
color: isFocused ? '#YOUR_ACTIVE_COLOR' : '#YOUR_INACTIVE_COLOR'Modifying Header
Customize the header in the CustomTabBar component:
typescript
{/* Custom header title */}
<Text style={{
color: '#fff',
fontSize: 20,
fontWeight: '600'
}}>
Your App Name
</Text>🔄 Auto-scroll Feature
The active tab automatically scrolls into view when navigating. This is handled by:
typescript
useEffect(() => {
if (scrollViewRef.current) {
const activeIndex = state.index;
const tabWidth = 90;
const scrollX = Math.max(0, activeIndex * tabWidth - 50);
scrollViewRef.current.scrollTo({
x: scrollX,
animated: true
});
}
}, [state.index]);📱 Platform Support
- ✅ iOS
- ✅ Android
🛠️ Development
File Structure Best Practices
- Keep each tab as a separate component
- Use consistent naming conventions
- Maintain similar data structures across tabs
- Keep styles inline for better performance
Performance Tips
- Use
lazy: falsefor better user experience - Implement proper image loading with placeholders
- Consider virtualized lists for large datasets
- Use
React.memofor news cards if needed
🐛 Troubleshooting
📄 License
This component is all your after you bought the landing components.
Happy coding! 🚀