Add 'apps/mobile/' from commit '5fa30f365f21531094cd4d2045042bb4f1370ac3'
git-subtree-dir: apps/mobile git-subtree-mainline:86f8987dffgit-subtree-split:5fa30f365f
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { Platform, useWindowDimensions } from "react-native";
|
||||
import { useSafeAreaFrame, useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
||||
import { spacing } from "@/constants/theme";
|
||||
|
||||
/** Standard UITabBar content height (home indicator is separate). */
|
||||
const IOS_TAB_BAR_HEIGHT = 49;
|
||||
|
||||
/** Trim extra inset so scroll content sits closer to the tab bar. */
|
||||
const TAB_BAR_PADDING_TRIM = spacing.lg;
|
||||
|
||||
/**
|
||||
* Pixels between the bottom of the safe-area layout frame and the window bottom.
|
||||
*/
|
||||
function useBelowLayoutFrame(): number {
|
||||
const { height: windowHeight } = useWindowDimensions();
|
||||
const frame = useSafeAreaFrame();
|
||||
|
||||
return Math.max(0, windowHeight - frame.y - frame.height);
|
||||
}
|
||||
|
||||
/** Native tab bar height excluding the home-indicator inset. */
|
||||
export function useNativeTabBarHeight(): number {
|
||||
const belowLayoutFrame = useBelowLayoutFrame();
|
||||
const { bottom: homeIndicator } = useSafeAreaInsets();
|
||||
const measured = Math.max(0, belowLayoutFrame - homeIndicator);
|
||||
|
||||
if (measured > 0) return measured;
|
||||
return Platform.OS === "ios" ? IOS_TAB_BAR_HEIGHT : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bottom padding so scroll content can clear the floating native tab bar.
|
||||
* Uses tab bar + home indicator as the target — layout-frame measurement can
|
||||
* over-report and leave a large empty scroll gap above the tab bar.
|
||||
*/
|
||||
export function useTabBarScrollPadding(): number {
|
||||
const { bottom: homeIndicator } = useSafeAreaInsets();
|
||||
const tabBar = useNativeTabBarHeight();
|
||||
const clearance = tabBar + homeIndicator;
|
||||
|
||||
return Math.max(spacing.xs, clearance - TAB_BAR_PADDING_TRIM);
|
||||
}
|
||||
|
||||
/** Bottom offset for floating action buttons above the tab bar. */
|
||||
export function useFloatingActionBottom(): number {
|
||||
const { bottom: homeIndicator } = useSafeAreaInsets();
|
||||
const tabBar = useNativeTabBarHeight();
|
||||
|
||||
return tabBar + homeIndicator + spacing.xs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bottom padding for tab-root ScrollViews (Dashboard, Invoices, etc.).
|
||||
* Uses full tab-bar clearance — do not trim; undershooting hides content under the bar.
|
||||
*/
|
||||
export function useTabScreenScrollPadding(): number {
|
||||
const { bottom: homeIndicator } = useSafeAreaInsets();
|
||||
const tabBar = useNativeTabBarHeight();
|
||||
|
||||
return tabBar + homeIndicator + spacing.sm;
|
||||
}
|
||||
|
||||
/** @deprecated Use useTabBarScrollPadding */
|
||||
export function useTabBarInset() {
|
||||
return useTabBarScrollPadding();
|
||||
}
|
||||
Reference in New Issue
Block a user