mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-18 06:49:40 +02:00
Projects included: - maerchenzauber (NestJS backend + Expo mobile + SvelteKit web + Astro landing) - manacore (Expo mobile + SvelteKit web + Astro landing) - manadeck (NestJS backend + Expo mobile + SvelteKit web) - memoro (Expo mobile + SvelteKit web + Astro landing) This commit preserves the current state before monorepo restructuring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
5.3 KiB
5.3 KiB
Glass/Blur Header Implementation Guide - Expo Router
Overview
Glass headers (blur effect headers) provide a modern iOS-style frosted glass appearance that blurs content behind the header when scrolling. This guide covers implementation in Expo Router.
Requirements
- Expo Router (latest version)
- iOS device/simulator (blur effect is iOS-only)
@react-navigation/elementspackage (foruseHeaderHeighthook)
Basic Implementation
1. Enable Blur Effect in Layout
// app/(tabs)/_layout.tsx or app/_layout.tsx
import { Tabs } from 'expo-router';
import { Platform } from 'react-native';
export default function Layout() {
return (
<Tabs
screenOptions={{
headerShown: true,
headerTransparent: Platform.OS === 'ios',
headerBlurEffect: Platform.OS === 'ios' ? 'regular' : undefined,
}}>
<Tabs.Screen name="index" options={{ title: 'Home' }} />
</Tabs>
);
}
2. Handle Content Padding
Since the header is transparent, content will render behind it. Use useHeaderHeight to add proper padding:
// app/(tabs)/index.tsx
import { useHeaderHeight } from '@react-navigation/elements';
import { Platform, FlatList } from 'react-native';
export default function Screen() {
const headerHeight = useHeaderHeight();
return (
<FlatList
data={items}
contentContainerStyle={{
paddingTop: Platform.OS === 'ios' ? headerHeight : 0
}}
renderItem={({ item }) => <Item data={item} />}
/>
);
}
Blur Effect Options (iOS Only)
Available headerBlurEffect values:
'regular'- Standard blur (recommended)'prominent'- More pronounced blur'systemMaterial'- Adapts to system theme'systemThinMaterial'- Thinner material'systemUltraThinMaterial'- Ultra-thin material'systemThickMaterial'- Thicker material'systemChromeMaterial'- Chrome-style material'systemThinMaterialLight'- Light thin material'systemThinMaterialDark'- Dark thin material
Platform-Specific Considerations
iOS
- Blur effect works natively
- Requires both
headerTransparent: trueandheaderBlurEffect - Header automatically adapts to light/dark mode with system materials
Android
- Native blur not supported
- Header remains solid
- Use
Platform.OS === 'ios'checks to prevent errors
Web
- Blur not supported
- Falls back to solid header
Best Practices
✅ Do
- Always use Platform checks for iOS-specific features
- Add proper content padding with
useHeaderHeight - Test on both iOS and Android
- Use
'regular'or'systemMaterial'for best compatibility - Consider dark mode with appropriate blur materials
❌ Don't
- Don't apply blur without
headerTransparent: true - Don't forget to handle content padding
- Don't use iOS-specific values on Android
- Don't rely on blur for critical UI elements visibility
Common Issues & Solutions
Issue: Content appears behind header
Solution: Use useHeaderHeight hook to add paddingTop
const headerHeight = useHeaderHeight();
contentContainerStyle={{ paddingTop: Platform.OS === 'ios' ? headerHeight : 0 }}
Issue: Blur not visible
Solution: Ensure both headerTransparent and headerBlurEffect are set
headerTransparent: true,
headerBlurEffect: 'regular',
Issue: Android crashes or looks wrong
Solution: Use platform checks
headerTransparent: Platform.OS === 'ios',
headerBlurEffect: Platform.OS === 'ios' ? 'regular' : undefined,
Issue: Header text not readable
Solution: Use appropriate blur material or adjust header tint color
headerBlurEffect: 'systemMaterial', // Adapts to theme
headerTintColor: colors.foreground,
Complete Example
// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
import { Platform } from 'react-native';
import { useThemeColors } from '~/utils/themeUtils';
export default function TabLayout() {
const colors = useThemeColors();
return (
<Tabs
screenOptions={{
headerShown: true,
headerTransparent: Platform.OS === 'ios',
headerBlurEffect: Platform.OS === 'ios' ? 'systemMaterial' : undefined,
headerTintColor: colors.foreground,
tabBarStyle: {
backgroundColor: colors.background,
},
}}>
<Tabs.Screen
name="index"
options={{
title: 'Home',
}}
/>
</Tabs>
);
}
// app/(tabs)/index.tsx
import { View, FlatList, Platform } from 'react-native';
import { useHeaderHeight } from '@react-navigation/elements';
export default function HomeScreen() {
const headerHeight = useHeaderHeight();
return (
<View style={{ flex: 1 }}>
<FlatList
data={items}
contentContainerStyle={{
paddingTop: Platform.OS === 'ios' ? headerHeight : 0,
paddingHorizontal: 16,
}}
renderItem={({ item }) => <Card item={item} />}
/>
</View>
);
}
References
Version Info
- Last updated: 2025-01
- Expo SDK: 52+
- Expo Router: v5+