Skip to content

Commit 0ce9bff

Browse files
committed
feat(example): add inline toaster config and improve demo UX
Replace flat button list with sectioned Form layout. Toaster config (position, theme, swipe direction, stacking, etc.) is now inline at the top of the home screen. Switch from NativeTabs to root Stack for reliable header control with title and modal button in header right.
1 parent 3d8fb5e commit 0ce9bff

9 files changed

Lines changed: 1489 additions & 894 deletions

File tree

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,8 @@
11
import * as React from 'react';
2-
import { useColorScheme } from 'react-native';
32
import { Stack } from 'expo-router';
4-
import { isLiquidGlassAvailable } from 'expo-glass-effect';
53

64
const HomeLayout: React.FC = () => {
7-
const rawTheme = useColorScheme();
8-
const theme = rawTheme === 'dark' ? 'dark' : 'light';
9-
const isGlassAvailable = isLiquidGlassAvailable();
10-
const blurEffect =
11-
theme === 'dark' ? 'systemMaterialDark' : 'systemMaterialLight';
12-
13-
return (
14-
<Stack
15-
screenOptions={{
16-
headerShown: true,
17-
headerLargeTitle: true,
18-
headerTransparent: true,
19-
headerTintColor: theme === 'dark' ? 'white' : 'black',
20-
headerLargeStyle: { backgroundColor: 'transparent' },
21-
headerBlurEffect: isGlassAvailable ? undefined : blurEffect,
22-
}}
23-
>
24-
<Stack.Screen
25-
name="index"
26-
options={{
27-
title: 'Home',
28-
}}
29-
/>
30-
</Stack>
31-
);
5+
return <Stack screenOptions={{ headerShown: false }} />;
326
};
337

348
export default HomeLayout;

example/app/(tabs)/(settings)/index.tsx

Lines changed: 9 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,20 @@
11
import * as React from 'react';
2-
import { useRouter, useGlobalSearchParams } from 'expo-router';
3-
import { Host, Form, Section, Switch, Picker, Button } from '@expo/ui/swift-ui';
4-
import type { ToastPosition } from 'sonner-native';
5-
6-
const POSITION_OPTIONS: ToastPosition[] = [
7-
'top-center',
8-
'center',
9-
'bottom-center',
10-
];
11-
12-
const POSITION_LABELS: Record<ToastPosition, string> = {
13-
'top-center': 'Top Center',
14-
'center': 'Center',
15-
'bottom-center': 'Bottom Center',
16-
};
2+
import { useRouter } from 'expo-router';
3+
import { Host, Form, Section, Button } from '@expo/ui/swift-ui';
4+
import { buttonStyle } from '@expo/ui/swift-ui/modifiers';
175

186
const SettingsScreen: React.FC = () => {
197
const router = useRouter();
20-
const params = useGlobalSearchParams<{
21-
stacking?: string;
22-
position?: string;
23-
}>();
24-
25-
const stackingEnabled = params.stacking !== 'false';
26-
const defaultPosition = (params.position as ToastPosition) || 'top-center';
27-
28-
const selectedIndex = POSITION_OPTIONS.indexOf(defaultPosition);
29-
const positionLabels = POSITION_OPTIONS.map((pos) => POSITION_LABELS[pos]);
30-
31-
const handleStackingChange = (value: boolean) => {
32-
router.setParams({ stacking: value.toString() });
33-
};
34-
35-
const handlePositionChange = (position: ToastPosition) => {
36-
router.setParams({ position });
37-
};
388

399
return (
4010
<Host style={{ flex: 1 }}>
41-
<Form scrollEnabled>
42-
<Section title="Global Toast Options">
43-
<Picker
44-
label="Toast Position"
45-
options={positionLabels}
46-
selectedIndex={selectedIndex}
47-
variant="menu"
48-
onOptionSelected={({ nativeEvent }) => {
49-
const position = POSITION_OPTIONS[nativeEvent.index];
50-
if (position) {
51-
handlePositionChange(position);
52-
}
53-
}}
54-
/>
55-
<Switch
56-
label="Stacking Enabled"
57-
value={stackingEnabled}
58-
onValueChange={handleStackingChange}
11+
<Form>
12+
<Section title="Navigation">
13+
<Button
14+
onPress={() => router.push('/modal')}
15+
label="Open Modal"
16+
modifiers={[buttonStyle('bordered')]}
5917
/>
60-
<Button onPress={() => router.push('/modal')}>Open Modal</Button>
6118
</Section>
6219
</Form>
6320
</Host>

example/app/(tabs)/_layout.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import { useColorScheme } from 'react-native';
3-
import { Icon, Label, NativeTabs } from 'expo-router/unstable-native-tabs';
3+
import { NativeTabs } from 'expo-router/unstable-native-tabs';
44

55
const TabsLayout: React.FC = () => {
66
const colorScheme = useColorScheme();
@@ -9,12 +9,12 @@ const TabsLayout: React.FC = () => {
99
return (
1010
<NativeTabs blurEffect={blurEffect}>
1111
<NativeTabs.Trigger name="(home)">
12-
<Label>Home</Label>
13-
<Icon sf="house.fill" drawable="custom_android_drawable" />
12+
<NativeTabs.Trigger.Label>Home</NativeTabs.Trigger.Label>
13+
<NativeTabs.Trigger.Icon sf="house.fill" drawable="custom_android_drawable" />
1414
</NativeTabs.Trigger>
1515
<NativeTabs.Trigger name="(settings)">
16-
<Icon sf="gear" drawable="custom_settings_drawable" />
17-
<Label>Settings</Label>
16+
<NativeTabs.Trigger.Icon sf="gear" drawable="custom_settings_drawable" />
17+
<NativeTabs.Trigger.Label>Settings</NativeTabs.Trigger.Label>
1818
</NativeTabs.Trigger>
1919
</NativeTabs>
2020
);

example/app/_layout.tsx

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,72 @@
11
import * as React from 'react';
2-
import { Stack, useGlobalSearchParams } from 'expo-router';
3-
import { Text } from 'react-native';
2+
import { Pressable, Text, useColorScheme } from 'react-native';
3+
import { Stack, useGlobalSearchParams, useRouter } from 'expo-router';
44
import { GestureHandlerRootView } from 'react-native-gesture-handler';
55
import { SafeAreaProvider } from 'react-native-safe-area-context';
6-
import { Toaster, type ToastPosition } from 'sonner-native';
6+
import {
7+
Toaster,
8+
type AutoWiggle,
9+
type ToastPosition,
10+
type ToastSwipeDirection,
11+
type ToastTheme,
12+
} from 'sonner-native';
713

814
const RootLayout: React.FC = () => {
15+
const colorScheme = useColorScheme();
16+
const router = useRouter();
917
const params = useGlobalSearchParams<{
1018
stacking?: string;
1119
position?: string;
20+
theme?: string;
21+
swipeDirection?: string;
22+
closeButton?: string;
23+
visibleToasts?: string;
24+
autoWiggle?: string;
25+
richColors?: string;
26+
invert?: string;
1227
}>();
1328

29+
const position = (params.position as ToastPosition) || 'top-center';
1430
const stackingEnabled = params.stacking !== 'false';
15-
const defaultPosition = (params.position as ToastPosition) || 'top-center';
31+
const theme = (params.theme as ToastTheme) || 'system';
32+
const swipeDirection =
33+
(params.swipeDirection as ToastSwipeDirection) || 'up';
34+
const closeButton = params.closeButton !== 'false';
35+
const visibleToasts = parseInt(params.visibleToasts || '4', 10);
36+
const autoWiggle = (params.autoWiggle as AutoWiggle) || 'toast-change';
37+
const richColors = params.richColors === 'true';
38+
const invert = params.invert === 'true';
1639

1740
return (
1841
<SafeAreaProvider>
1942
<GestureHandlerRootView style={{ flex: 1 }}>
2043
<Stack>
21-
{/* Tabs group - all tab screens are handled in (tabs)/_layout.tsx */}
2244
<Stack.Screen
23-
name="(tabs)"
45+
name="index"
2446
options={{
25-
headerShown: false,
47+
title: 'Toasts',
48+
headerRight: () => (
49+
<Pressable
50+
onPress={() => router.push('/modal')}
51+
hitSlop={8}
52+
>
53+
<Text
54+
style={{
55+
color:
56+
colorScheme === 'dark' ? '#0A84FF' : '#007AFF',
57+
fontSize: 17,
58+
}}
59+
>
60+
Modal
61+
</Text>
62+
</Pressable>
63+
),
2664
}}
2765
/>
28-
{/* Modal screens outside of tabs */}
66+
<Stack.Screen
67+
name="(tabs)"
68+
options={{ headerShown: false }}
69+
/>
2970
<Stack.Screen
3071
name="modal"
3172
options={{
@@ -36,14 +77,16 @@ const RootLayout: React.FC = () => {
3677
/>
3778
</Stack>
3879
<Toaster
39-
position={defaultPosition}
80+
position={position}
4081
duration={30000}
41-
swipeToDismissDirection="up"
42-
visibleToasts={4}
43-
closeButton
44-
autoWiggleOnUpdate="toast-change"
45-
theme="system"
82+
swipeToDismissDirection={swipeDirection}
83+
visibleToasts={visibleToasts}
84+
closeButton={closeButton}
85+
autoWiggleOnUpdate={autoWiggle}
86+
theme={theme}
4687
enableStacking={stackingEnabled}
88+
richColors={richColors}
89+
invert={invert}
4790
icons={{
4891
error: <Text>💥</Text>,
4992
loading: <Text>🔄</Text>,

example/app/index.tsx

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,5 @@
1-
import { Text } from '@react-navigation/elements';
2-
import { Link } from 'expo-router';
3-
import { ScrollView } from 'react-native';
41
import ToastDemo from '../components/toast-demo';
52

63
export default function Index() {
7-
return (
8-
<ScrollView
9-
contentInsetAdjustmentBehavior="automatic"
10-
contentContainerStyle={{
11-
paddingVertical: 20,
12-
flex: 1,
13-
}}
14-
>
15-
<Link href="/modal">
16-
<Text>Show modal</Text>
17-
</Link>
18-
<ToastDemo />
19-
</ScrollView>
20-
);
4+
return <ToastDemo />;
215
}

0 commit comments

Comments
 (0)