Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,33 @@ yarn add react-native-bottom-tabs


```tsx
import { TabView } from "react-native-bottom-tabs";

const items: TabViewItems = [
{ key: 'article', title: 'Article', icon: 'document.fill' },
{ key: 'albums', title: 'Albums', icon: 'square.grid.2x2.fill', badge: '3' },
{ key: 'contacts', title: 'Contacts', icon: 'person.fill' },
];

export default function App() {
const [selectedPage, setSelectedTab] = useState<string>('contacts');
import TabView, { SceneMap } from 'react-native-bottom-tabs';

export default function ThreeTabs() {
const [index, setIndex] = useState(0);
const [routes] = useState([
{ key: 'article', title: 'Article', icon: 'document.fill', badge: '!' },
{
key: 'albums',
title: 'Albums',
icon: 'square.grid.2x2.fill',
badge: '5',
},
{ key: 'contacts', title: 'Contacts', icon: 'person.fill' },
]);

const renderScene = SceneMap({
article: Article,
albums: Albums,
contacts: Contacts,
});

return (
<TabView
style={styles.fullWidth}
items={items}
selectedPage={selectedPage}
onPageSelected={handlePageSelected}
>
<View/>
<View/>
<View/>
</TabView>
navigationState={{ index, routes }}
onIndexChange={setIndex}
renderScene={renderScene}
/>
);
}
```
Expand Down
67 changes: 25 additions & 42 deletions example/src/Examples/FourTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,36 @@
import { StyleSheet } from 'react-native';
import TabView, {
type OnPageSelectedEventData,
type TabViewItems,
} from 'react-native-bottom-tabs';
import TabView, { SceneMap } from 'react-native-bottom-tabs';
import { useState } from 'react';
import { Article } from '../Screens/Article';
import { Albums } from '../Screens/Albums';
import { Chat } from '../Screens/Chat';
import { Contacts } from '../Screens/Contacts';
import { Chat } from '../Screens/Chat';

const items: TabViewItems = [
{ key: 'article', title: 'Article', icon: 'document.fill', badge: '!' },
{ key: 'albums', title: 'Albums', icon: 'square.grid.2x2.fill', badge: '5' },
{ key: 'contacts', title: 'Contacts', icon: 'person.fill' },
{ key: 'chat', title: 'Chat', icon: 'keyboard' },
];

export default function FourTabs() {
const [selectedPage, setSelectedTab] = useState<string>('contacts');

const handlePageSelected = ({
nativeEvent: { key },
}: {
nativeEvent: OnPageSelectedEventData;
}) => setSelectedTab(key);
export default function ThreeTabs() {
const [index, setIndex] = useState(0);
const [routes] = useState([
{ key: 'article', title: 'Article', icon: 'document.fill', badge: '!' },
{
key: 'albums',
title: 'Albums',
icon: 'square.grid.2x2.fill',
badge: '5',
},
{ key: 'contacts', title: 'Contacts', icon: 'person.fill' },
{ key: 'chat', title: 'Chat', icon: 'keyboard' },
]);

const goToAlbums = () => {
setSelectedTab('albums');
};
const renderScene = SceneMap({
article: Article,
albums: Albums,
contacts: Contacts,
chat: Chat,
});

return (
<TabView
style={styles.fullWidth}
items={items}
tabViewStyle="sidebarAdaptable"
selectedPage={selectedPage}
onPageSelected={handlePageSelected}
>
<Article onClick={goToAlbums} />
<Albums />
<Contacts />
<Chat />
</TabView>
navigationState={{ index, routes }}
onIndexChange={setIndex}
renderScene={renderScene}
/>
);
}

const styles = StyleSheet.create({
fullWidth: {
width: '100%',
height: '100%',
},
});
59 changes: 21 additions & 38 deletions example/src/Examples/ThreeTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,33 @@
import { StyleSheet } from 'react-native';
import TabView, {
type OnPageSelectedEventData,
type TabViewItems,
} from 'react-native-bottom-tabs';
import TabView, { SceneMap } from 'react-native-bottom-tabs';
import { useState } from 'react';
import { Article } from '../Screens/Article';
import { Albums } from '../Screens/Albums';
import { Contacts } from '../Screens/Contacts';

const items: TabViewItems = [
{ key: 'article', title: 'Article', icon: 'document.fill', badge: '!' },
{ key: 'albums', title: 'Albums', icon: 'square.grid.2x2.fill', badge: '5' },
{ key: 'contacts', title: 'Contacts', icon: 'person.fill' },
];

export default function ThreeTabs() {
const [selectedPage, setSelectedTab] = useState<string>('contacts');

const handlePageSelected = ({
nativeEvent: { key },
}: {
nativeEvent: OnPageSelectedEventData;
}) => setSelectedTab(key);
const [index, setIndex] = useState(0);
const [routes] = useState([
{ key: 'article', title: 'Article', icon: 'document.fill', badge: '!' },
{
key: 'albums',
title: 'Albums',
icon: 'square.grid.2x2.fill',
badge: '5',
},
{ key: 'contacts', title: 'Contacts', icon: 'person.fill' },
]);

const goToAlbums = () => {
setSelectedTab('albums');
};
const renderScene = SceneMap({
article: Article,
albums: Albums,
contacts: Contacts,
});

return (
<TabView
style={styles.fullWidth}
items={items}
tabViewStyle="sidebarAdaptable"
selectedPage={selectedPage}
onPageSelected={handlePageSelected}
>
<Article onClick={goToAlbums} />
<Albums />
<Contacts />
</TabView>
navigationState={{ index, routes }}
onIndexChange={setIndex}
renderScene={renderScene}
/>
);
}

const styles = StyleSheet.create({
fullWidth: {
width: '100%',
height: '100%',
},
});
11 changes: 8 additions & 3 deletions example/src/Screens/Article.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

type Props = Partial<ScrollViewProps> & {
date?: string;
onClick?: () => void;
jumpTo?: (key: string) => void;
author?: {
name: string;
};
Expand All @@ -23,7 +23,7 @@
style,
...rest
}: TextProps & { children: React.ReactNode }) => {
return <Text style={[styles.heading, { color: '#000' }, style]} {...rest} />;

Check warning on line 26 in example/src/Screens/Article.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { color: '#000' }
};

const Paragraph = ({
Expand All @@ -31,7 +31,7 @@
...rest
}: TextProps & { children: React.ReactNode }) => {
return (
<Text style={[styles.paragraph, { color: '#000' }, style]} {...rest} />

Check warning on line 34 in example/src/Screens/Article.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { color: '#000' }
);
};

Expand All @@ -42,7 +42,7 @@
export function Article({
date = '1st Jan 2025',
author = DEFAULT_AUTHOR,
onClick,
jumpTo,
...rest
}: Props) {
const ref = React.useRef<ScrollView>(null);
Expand All @@ -51,7 +51,7 @@
return (
<ScrollView
ref={ref}
style={{ backgroundColor: '#fff' }}

Check warning on line 54 in example/src/Screens/Article.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { backgroundColor: '#fff' }
contentContainerStyle={styles.content}
{...rest}
>
Expand All @@ -61,11 +61,16 @@
source={require('../../assets/avatar-1.png')}
/>
<View style={styles.meta}>
<Text style={[styles.name, { color: '#000' }]}>{author.name}</Text>

Check warning on line 64 in example/src/Screens/Article.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { color: '#000' }
<Text style={[styles.timestamp, { color: '#000' }]}>{date}</Text>

Check warning on line 65 in example/src/Screens/Article.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { color: '#000' }
</View>
</View>
<Button title="Go to Albums" onPress={onClick} />
<Button
title="Go to Albums"
onPress={() => {
jumpTo?.('albums');
}}
/>
<Heading>What is Lorem Ipsum?</Heading>
<Paragraph>
Lorem Ipsum is simply dummy text of the printing and typesetting
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -195,5 +195,8 @@
"create-react-native-library": {
"type": "view-mixed",
"version": "0.41.2"
},
"dependencies": {
"use-latest-callback": "^0.2.1"
}
}
34 changes: 34 additions & 0 deletions src/SceneMap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react';

type SceneProps = {
route: any;
jumpTo: (key: string) => void;
};

const SceneComponent = React.memo(
<T extends { component: React.ComponentType<any> } & SceneProps>({
component,
...rest
}: T) => {
return React.createElement(component, rest);
}
);

SceneComponent.displayName = 'SceneComponent';

export function SceneMap<T>(scenes: { [key: string]: React.ComponentType<T> }) {
return ({ route, jumpTo }: SceneProps) => {
const component = scenes[route.key];
if (!component) {
return null;
}
return (
<SceneComponent
key={route.key}
jumpTo={jumpTo}
component={component}
route={route}
/>
);
};
}
54 changes: 0 additions & 54 deletions src/TabView.android.tsx

This file was deleted.

Loading
Loading