Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added dark theme to example #2242

Merged
merged 7 commits into from
Jul 11, 2024
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
161 changes: 95 additions & 66 deletions apps/Example.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import React from 'react';
import React, { createContext, useContext, useEffect, useState } from 'react';
import {
ScrollView,
StyleSheet,
Text,
I18nManager,
Platform,
StatusBar,
useColorScheme,
} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import {
DarkTheme,
DefaultTheme,
NavigationContainer,
useTheme,
} from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import RNRestart from 'react-native-restart';

import { ListItem, SettingsSwitch } from './src/shared';
import { ListItem, SettingsSwitch, ThemedText } from './src/shared';

import SimpleNativeStack from './src/screens/SimpleNativeStack';
import SwipeBackAnimation from './src/screens/SwipeBackAnimation';
Expand Down Expand Up @@ -136,74 +141,98 @@ interface MainScreenProps {
navigation: StackNavigationProp<RootStackParamList, 'Main'>;
}

const MainScreen = ({ navigation }: MainScreenProps): React.JSX.Element => (
<ScrollView testID="root-screen-examples-scrollview">
<SettingsSwitch
style={styles.switch}
label="Right to left"
value={I18nManager.isRTL}
onValueChange={() => {
I18nManager.forceRTL(!I18nManager.isRTL);
RNRestart.Restart();
}}
/>
<Text style={styles.label} testID="root-screen-examples-header">
Examples
</Text>
{examples.map(name => (
<ListItem
key={name}
testID={`root-screen-example-${name}`}
title={SCREENS[name].title}
onPress={() => navigation.navigate(name)}
disabled={!isPlatformReady(name)}
const MainScreen = ({ navigation }: MainScreenProps): React.JSX.Element => {
const { toggleTheme } = useContext(ThemeToggle);
const isDark = useTheme().dark;

return (
<ScrollView testID="root-screen-examples-scrollview">
<SettingsSwitch
style={styles.switch}
label="Right to left"
value={I18nManager.isRTL}
onValueChange={() => {
I18nManager.forceRTL(!I18nManager.isRTL);
RNRestart.Restart();
}}
/>
))}
<Text style={styles.label}>Playgrounds</Text>
{playgrounds.map(name => (
<ListItem
key={name}
testID={`root-screen-playground-${name}`}
title={SCREENS[name].title}
onPress={() => navigation.navigate(name)}
disabled={!isPlatformReady(name)}
<SettingsSwitch
style={styles.switch}
label="Dark mode"
value={isDark}
onValueChange={toggleTheme}
/>
))}
</ScrollView>
);

const ExampleApp = (): React.JSX.Element => (
<GestureHandlerRootView style={{ flex: 1 }}>
<GestureDetectorProvider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Main"
options={{
title: `${
Platform.isTV ? '📺' : '📱'
} React Native Screens Examples`,
}}
component={MainScreen}
/>
{Object.keys(SCREENS).map(name => (
<Stack.Screen
key={name}
name={name}
getComponent={() => SCREENS[name].component}
options={{ headerShown: false }}
/>
))}
</Stack.Navigator>
</NavigationContainer>
</GestureDetectorProvider>
</GestureHandlerRootView>
);
<ThemedText style={styles.label} testID="root-screen-examples-header">
Examples
</ThemedText>
{examples.map(name => (
<ListItem
key={name}
testID={`root-screen-example-${name}`}
title={SCREENS[name].title}
onPress={() => navigation.navigate(name)}
disabled={!isPlatformReady(name)}
/>
))}
<ThemedText style={styles.label}>Playgrounds</ThemedText>
{playgrounds.map(name => (
<ListItem
key={name}
testID={`root-screen-playground-${name}`}
title={SCREENS[name].title}
onPress={() => navigation.navigate(name)}
disabled={!isPlatformReady(name)}
/>
))}
</ScrollView>
);
};

const ThemeToggle = createContext<{ toggleTheme: () => void }>(null!);

const ExampleApp = (): React.JSX.Element => {
const scheme = useColorScheme();
const [isDark, setIsDark] = useState(scheme === 'dark');

useEffect(() => setIsDark(scheme === 'dark'), [scheme]);

const toggleTheme = () => setIsDark(prev => !prev);

return (
<GestureHandlerRootView style={{ flex: 1 }}>
<GestureDetectorProvider>
<ThemeToggle.Provider value={{ toggleTheme }}>
<NavigationContainer theme={isDark ? DarkTheme : DefaultTheme}>
<Stack.Navigator
screenOptions={{ statusBarStyle: isDark ? 'light' : 'dark' }}>
<Stack.Screen
name="Main"
options={{
title: `${
Platform.isTV ? '📺' : '📱'
} React Native Screens Examples`,
}}
component={MainScreen}
/>
{Object.keys(SCREENS).map(name => (
<Stack.Screen
key={name}
name={name}
getComponent={() => SCREENS[name].component}
options={{ headerShown: false }}
/>
))}
</Stack.Navigator>
</NavigationContainer>
</ThemeToggle.Provider>
</GestureDetectorProvider>
</GestureHandlerRootView>
);
};

const styles = StyleSheet.create({
label: {
fontSize: 15,
color: 'black',
margin: 10,
marginTop: 15,
},
Expand Down
8 changes: 6 additions & 2 deletions apps/src/screens/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ interface PrivacyScreenProps {
navigation: NativeStackNavigationProp<StackParamList, 'Main'>;
}

const PrivacyScreen = ({ navigation }: PrivacyScreenProps): React.JSX.Element => {
const PrivacyScreen = ({
navigation,
}: PrivacyScreenProps): React.JSX.Element => {
const toast = useToast();

useEffect(() => {
Expand Down Expand Up @@ -228,7 +230,9 @@ interface OptionsScreenProps {
navigation: NativeStackNavigationProp<StackParamList, 'Main'>;
}

const OptionsScreen = ({ navigation }: OptionsScreenProps): React.JSX.Element => {
const OptionsScreen = ({
navigation,
}: OptionsScreenProps): React.JSX.Element => {
const toast = useToast();

useEffect(() => {
Expand Down
1 change: 0 additions & 1 deletion apps/src/screens/HeaderOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 10,
backgroundColor: 'white',
},
heading: {
marginLeft: 10,
Expand Down
11 changes: 6 additions & 5 deletions apps/src/screens/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useLayoutEffect, useRef, useState } from 'react';
import { ScrollView, Text, StyleSheet } from 'react-native';
import { ScrollView, StyleSheet } from 'react-native';
import { SearchBarCommands, SearchBarProps } from 'react-native-screens';
import {
createNativeStackNavigator,
Expand All @@ -11,6 +11,7 @@ import {
SettingsInput,
SettingsPicker,
SettingsSwitch,
ThemedText,
ToastProvider,
useToast,
} from '../shared';
Expand Down Expand Up @@ -132,7 +133,7 @@ const MainScreen = ({ navigation }: MainScreenProps): React.JSX.Element => {
onValueChange={setAutoCapitalize}
items={['none', 'words', 'sentences', 'characters']}
/>
<Text style={styles.heading}>iOS only</Text>
<ThemedText style={styles.heading}>iOS only</ThemedText>
<SettingsSwitch
label="Hide navigation bar"
value={hideNavigationBar}
Expand All @@ -148,7 +149,7 @@ const MainScreen = ({ navigation }: MainScreenProps): React.JSX.Element => {
value={hideWhenScrolling}
onValueChange={setHideWhenScrolling}
/>
<Text style={styles.heading}>Android only</Text>
<ThemedText style={styles.heading}>Android only</ThemedText>
<SettingsPicker<InputType>
label="Input type"
value={inputType}
Expand All @@ -172,7 +173,7 @@ const MainScreen = ({ navigation }: MainScreenProps): React.JSX.Element => {
value={shouldShowHintSearchIcon}
onValueChange={setShouldShowHintSearchIcon}
/>
<Text style={styles.heading}>Imperative actions</Text>
<ThemedText style={styles.heading}>Imperative actions</ThemedText>
<Button onPress={() => searchBarRef.current?.blur()} title="Blur" />
<Button onPress={() => searchBarRef.current?.focus()} title="Focus" />
<Button
Expand All @@ -192,7 +193,7 @@ const MainScreen = ({ navigation }: MainScreenProps): React.JSX.Element => {
onPress={() => searchBarRef.current?.cancelSearch()}
title="Cancel search"
/>
<Text style={styles.heading}>Other</Text>
<ThemedText style={styles.heading}>Other</ThemedText>
<Button
onPress={() => navigation.navigate('Search')}
title="Other Searchbar example"
Expand Down
2 changes: 1 addition & 1 deletion apps/src/screens/StackPresentation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ interface FormScreenProps {
}

const FormScreen = ({ navigation }: FormScreenProps): React.JSX.Element => (
<View style={{ ...styles.container, backgroundColor: 'white' }}>
<View style={styles.container}>
<Form />
<Button
testID="stack-presentation-form-screen-go-back-button"
Expand Down
50 changes: 26 additions & 24 deletions apps/src/shared/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
import React from 'react';
import { View, StyleSheet, Text, TextInput } from 'react-native';
import React, { Fragment } from 'react';
import { View, StyleSheet } from 'react-native';
import { ThemedText, ThemedTextInput } from '.';

export const Form = (): React.JSX.Element => (
<View testID="form" style={styles.wrapper}>
<Text testID="form-header" style={styles.heading}>
Example form
</Text>
<Text testID="form-first-name-label" style={styles.label}>
First Name *
</Text>
<TextInput testID="form-first-name-input" style={styles.input} />
<Text testID="form-last-name-label" style={styles.label}>
Last Name *
</Text>
<TextInput testID="form-last-name-input" style={styles.input} />
<Text testID="form-email-label" style={styles.label}>
Email *
</Text>
<TextInput testID="form-email-input" style={styles.input} />
</View>
);
const fields = [
{ name: 'form-first-name', placeholder: 'First Name *' },
{ name: 'form-last-name', placeholder: 'Last Name *' },
{ name: 'form-email', placeholder: 'Email *' },
];

export const Form = (): React.JSX.Element => {
return (
<View testID="form" style={styles.wrapper}>
<ThemedText testID="form-header" style={styles.heading}>
Example form
</ThemedText>
{fields.map(({ name, placeholder }) => (
<Fragment key={name}>
<ThemedText testID={`${name}-label`} style={styles.label}>
{placeholder}
</ThemedText>
<ThemedTextInput testID={`${name}-input`} style={styles.input} />
</Fragment>
))}
</View>
);
};

const styles = StyleSheet.create({
wrapper: {
Expand All @@ -28,19 +33,16 @@ const styles = StyleSheet.create({
heading: {
fontSize: 16,
fontWeight: 'bold',
color: 'black',
marginBottom: 16,
},
label: {
color: 'darkslategray',
textTransform: 'capitalize',
fontSize: 12,
marginBottom: 8,
},
input: {
borderWidth: 1,
borderRadius: 5,
borderColor: 'black',
marginBottom: 12,
height: 40,
},
Expand Down
23 changes: 10 additions & 13 deletions apps/src/shared/ListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useTheme } from '@react-navigation/native';
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { TouchableOpacity, StyleSheet } from 'react-native';
import { ThemedText, ThemedView } from '.';

interface Props {
title: string;
Expand All @@ -14,11 +16,15 @@ export const ListItem = ({
testID,
disabled,
}: Props): React.JSX.Element => {
const { colors } = useTheme();
return (
<TouchableOpacity onPress={onPress} testID={testID} disabled={disabled}>
<View style={styles.container}>
<Text style={[styles.title, disabled && styles.disabled]}>{disabled && '(N/A) '}{title}</Text>
</View>
<ThemedView style={[styles.container, { borderColor: colors.border }]}>
<ThemedText style={disabled ? styles.disabled : undefined}>
{disabled && '(N/A) '}
{title}
</ThemedText>
</ThemedView>
</TouchableOpacity>
);
};
Expand All @@ -29,18 +35,9 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
padding: 10,
backgroundColor: 'white',
borderColor: '#ccc',
borderWidth: 1,
},
disabled: {
color: 'gray',
},
title: {
color: 'black',
},
chevron: {
fontWeight: 'bold',
color: 'black',
},
});
Loading
Loading