Skip to content

Commit

Permalink
feat: add a button element to elements package
Browse files Browse the repository at this point in the history
This adds a simple `Button` component to make it easier for quick demos, examples and learning material etc.

It implements part of the material design guidelines: https://m3.material.io/components/buttons/overview

There are 3 variants implemented:

- `'plain'`
- `'tinted'`
- '`filled'`

These variants also exist in iOS design guidelines, so it makes the buttons somewhat platform agnostic. Though exact measurements will slightly differ.

Since the `Button` is part of React Navigation, it has built-in support for navigating to screens, and renders an anchor tag on the Web when used for navigation:

```js
<Button screen="Profile" params={{ userId: 'jane' }}>
  View Jane's Profile
<Button>
```

It can also be used as a regular button:

```js
<Button onPress={() => { /* do something */ }}>
  Do something
</Button>
```
  • Loading branch information
satya164 committed Oct 28, 2023
1 parent 2f58b5d commit 3435565
Show file tree
Hide file tree
Showing 32 changed files with 388 additions and 466 deletions.
5 changes: 3 additions & 2 deletions example/src/Screens/AuthFlow.tsx
@@ -1,11 +1,12 @@
import { Button } from '@react-navigation/elements';
import { type ParamListBase, useTheme } from '@react-navigation/native';
import {
createStackNavigator,
type StackScreenProps,
} from '@react-navigation/stack';
import * as React from 'react';
import { ActivityIndicator, StyleSheet, TextInput, View } from 'react-native';
import { Button, Title } from 'react-native-paper';
import { Title } from 'react-native-paper';

type AuthStackParams = {
Home: undefined;
Expand Down Expand Up @@ -63,7 +64,7 @@ const SignInScreen = ({
{ backgroundColor: colors.card, color: colors.text },
]}
/>
<Button mode="contained" onPress={signIn} style={styles.button}>
<Button variant="filled" onPress={signIn} style={styles.button}>
Sign in
</Button>
<Button onPress={() => navigation.navigate('Chat')} style={styles.button}>
Expand Down
38 changes: 9 additions & 29 deletions example/src/Screens/CustomLayout.tsx
@@ -1,4 +1,5 @@
import {
Button,
getDefaultHeaderHeight,
getHeaderTitle,
} from '@react-navigation/elements';
Expand All @@ -21,7 +22,6 @@ import {
Text,
View,
} from 'react-native';
import { Button } from 'react-native-paper';
import {
useSafeAreaFrame,
useSafeAreaInsets,
Expand All @@ -47,17 +47,12 @@ const ArticleScreen = ({
<ScrollView>
<View style={styles.buttons}>
<Button
mode="contained"
variant="filled"
onPress={() => navigation.navigate('NewsFeed', { date: Date.now() })}
style={styles.button}
>
Navigate to feed
</Button>
<Button
mode="outlined"
onPress={() => navigation.goBack()}
style={styles.button}
>
<Button variant="tinted" onPress={() => navigation.goBack()}>
Go back
</Button>
</View>
Expand All @@ -76,18 +71,10 @@ const NewsFeedScreen = ({
return (
<ScrollView>
<View style={styles.buttons}>
<Button
mode="contained"
onPress={() => navigation.navigate('Albums')}
style={styles.button}
>
<Button variant="filled" onPress={() => navigation.navigate('Albums')}>
Navigate to album
</Button>
<Button
mode="outlined"
onPress={() => navigation.goBack()}
style={styles.button}
>
<Button variant="tinted" onPress={() => navigation.goBack()}>
Go back
</Button>
</View>
Expand All @@ -103,19 +90,14 @@ const AlbumsScreen = ({
<ScrollView>
<View style={styles.buttons}>
<Button
mode="contained"
variant="filled"
onPress={() =>
navigation.navigate('Article', { author: 'Babel fish' })
}
style={styles.button}
>
Navigate to article
</Button>
<Button
mode="outlined"
onPress={() => navigation.goBack()}
style={styles.button}
>
<Button variant="tinted" onPress={() => navigation.goBack()}>
Go back
</Button>
</View>
Expand Down Expand Up @@ -229,10 +211,8 @@ const styles = StyleSheet.create({
buttons: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 8,
},
button: {
margin: 8,
gap: 12,
padding: 12,
},
breadcrumbs: {
alignItems: 'center',
Expand Down
2 changes: 1 addition & 1 deletion example/src/Screens/DrawerView.tsx
@@ -1,7 +1,7 @@
import { Button } from '@react-navigation/elements';
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import { Drawer, useDrawerProgress } from 'react-native-drawer-layout';
import { Button } from 'react-native-paper';
import Animated, {
interpolate,
type SharedValue,
Expand Down
4 changes: 3 additions & 1 deletion example/src/Screens/DynamicTabs.tsx
@@ -1,8 +1,9 @@
import Feather from '@expo/vector-icons/Feather';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Button } from '@react-navigation/elements';
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import { Button, Title } from 'react-native-paper';
import { Title } from 'react-native-paper';

type BottomTabParams = {
[key: string]: undefined;
Expand Down Expand Up @@ -54,5 +55,6 @@ const styles = StyleSheet.create({
flex: 1,
alignItems: 'center',
justifyContent: 'center',
gap: 8,
},
});
60 changes: 14 additions & 46 deletions example/src/Screens/LinkComponent.tsx
@@ -1,67 +1,43 @@
import { Button } from '@react-navigation/elements';
import {
CommonActions,
Link,
type ParamListBase,
StackActions,
useLinkProps,
} from '@react-navigation/native';
import {
createStackNavigator,
type StackScreenProps,
} from '@react-navigation/stack';
import * as React from 'react';
import { Platform, ScrollView, StyleSheet, View } from 'react-native';
import { Button } from 'react-native-paper';

import type { LinkComponentDemoParamList } from '../screens';
import { Albums } from '../Shared/Albums';
import { Article } from '../Shared/Article';

const scrollEnabled = Platform.select({ web: true, default: false });

const LinkButton = ({
screen,
params,
action,
href,
...rest
}: React.ComponentProps<typeof Button> &
Parameters<typeof useLinkProps>[0]) => {
// @ts-expect-error: This is already type-checked by the prop types
const props = useLinkProps({ screen, params, action, href });

return <Button {...props} {...rest} />;
};

const ArticleScreen = ({
navigation,
route,
}: StackScreenProps<LinkComponentDemoParamList, 'Article'>) => {
return (
<ScrollView>
<View style={styles.buttons}>
<Link
screen="LinkComponent"
params={{ screen: 'Albums' }}
style={[styles.button, { padding: 8 }]}
>
<Link screen="LinkComponent" params={{ screen: 'Albums' }}>
Go to LinkComponent &gt; Albums
</Link>
<Link
screen="LinkComponent"
params={{ screen: 'Albums' }}
action={StackActions.replace('Albums')}
style={[styles.button, { padding: 8 }]}
>
Replace with LinkComponent &gt; Albums
</Link>
<LinkButton screen="Home" mode="contained" style={styles.button}>
<Button screen="Home" variant="filled">
Go to Home
</LinkButton>
<Button
mode="outlined"
onPress={() => navigation.goBack()}
style={styles.button}
>
</Button>
<Button variant="tinted" action={CommonActions.goBack()}>
Go back
</Button>
</View>
Expand All @@ -82,23 +58,17 @@ const AlbumsScreen = ({
<Link
screen="LinkComponent"
params={{ screen: 'Article', params: { author: 'Babel' } }}
style={[styles.button, { padding: 8 }]}
>
Go to /link-component/article
Go to Article
</Link>
<LinkButton
<Button
screen="LinkComponent"
params={{ screen: 'Article', params: { author: 'Babel' } }}
mode="contained"
style={styles.button}
>
Go to /link-component/article
</LinkButton>
<Button
mode="outlined"
onPress={() => navigation.goBack()}
style={styles.button}
variant="filled"
>
Go to Article
</Button>
<Button variant="tinted" onPress={() => navigation.goBack()}>
Go back
</Button>
</View>
Expand Down Expand Up @@ -140,9 +110,7 @@ export function LinkComponent({ navigation, ...rest }: Props) {

const styles = StyleSheet.create({
buttons: {
padding: 8,
},
button: {
margin: 8,
gap: 12,
padding: 12,
},
});
22 changes: 9 additions & 13 deletions example/src/Screens/LinkingScreen.tsx
@@ -1,10 +1,11 @@
import { Button } from '@react-navigation/elements';
import { useUnhandledLinking } from '@react-navigation/native';
import {
createStackNavigator,
type StackScreenProps,
} from '@react-navigation/stack';
import React, { useContext } from 'react';
import { Button, Platform, StyleSheet, Text, View } from 'react-native';
import { Platform, StyleSheet, Text, View } from 'react-native';

const info = `
\u2022 xcrun simctl openurl booted exp://127.0.0.1:19000/--/linking/profile
Expand Down Expand Up @@ -32,11 +33,8 @@ const ProfileScreen = ({
<Text style={{ ...styles.text, ...{ color: 'teal' } }}>
Profile Screen
</Text>
<Button
onPress={() => navigation.popTo('Home')}
title="Go back to home"
/>
<Button onPress={signOut} title="Sign out" />
<Button onPress={() => navigation.popTo('Home')}>Go back to home</Button>
<Button onPress={signOut}>Sign out</Button>
</View>
);
};
Expand All @@ -50,11 +48,8 @@ const HomeScreen = ({
<Text style={{ ...styles.text, ...{ color: 'indianred' } }}>
Home Screen
</Text>
<Button
onPress={() => navigation.popTo('Profile')}
title="Go to profile"
/>
<Button onPress={signOut} title="Sign out" />
<Button onPress={() => navigation.popTo('Profile')}>Go to profile</Button>
<Button onPress={signOut}>Sign out</Button>
</View>
);
};
Expand All @@ -73,8 +68,9 @@ const SignInScreen = () => {
scheduleNext();
signIn();
}}
title="Sign In"
/>
>
Sign in
</Button>
</View>
);
};
Expand Down
38 changes: 9 additions & 29 deletions example/src/Screens/MixedHeaderMode.tsx
@@ -1,3 +1,4 @@
import { Button } from '@react-navigation/elements';
import type { ParamListBase } from '@react-navigation/native';
import {
createStackNavigator,
Expand All @@ -7,7 +8,6 @@ import {
} from '@react-navigation/stack';
import * as React from 'react';
import { Platform, ScrollView, StyleSheet, View } from 'react-native';
import { Button } from 'react-native-paper';

import { Albums } from '../Shared/Albums';
import { Article } from '../Shared/Article';
Expand All @@ -29,17 +29,12 @@ const ArticleScreen = ({
<ScrollView>
<View style={styles.buttons}>
<Button
mode="contained"
variant="filled"
onPress={() => navigation.push('NewsFeed', { date: Date.now() })}
style={styles.button}
>
Push feed
</Button>
<Button
mode="outlined"
onPress={() => navigation.pop()}
style={styles.button}
>
<Button variant="tinted" onPress={() => navigation.pop()}>
Pop screen
</Button>
</View>
Expand All @@ -58,18 +53,10 @@ const NewsFeedScreen = ({
return (
<ScrollView>
<View style={styles.buttons}>
<Button
mode="contained"
onPress={() => navigation.push('Albums')}
style={styles.button}
>
<Button variant="filled" onPress={() => navigation.push('Albums')}>
Navigate to album
</Button>
<Button
mode="outlined"
onPress={() => navigation.pop()}
style={styles.button}
>
<Button variant="tinted" onPress={() => navigation.pop()}>
Pop screen
</Button>
</View>
Expand All @@ -85,17 +72,12 @@ const AlbumsScreen = ({
<ScrollView>
<View style={styles.buttons}>
<Button
mode="contained"
variant="filled"
onPress={() => navigation.push('Article', { author: 'Babel fish' })}
style={styles.button}
>
Push article
</Button>
<Button
mode="outlined"
onPress={() => navigation.pop()}
style={styles.button}
>
<Button variant="tinted" onPress={() => navigation.pop()}>
Pop screen
</Button>
</View>
Expand Down Expand Up @@ -158,9 +140,7 @@ const styles = StyleSheet.create({
buttons: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 8,
},
button: {
margin: 8,
gap: 12,
padding: 12,
},
});

0 comments on commit 3435565

Please sign in to comment.