A performant interactive bottom sheet with fully configurable options for React Native applications.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Hooks and utilities for creating and customizing animation configurations for bottom sheet movements, providing both spring and timing-based animations with platform-specific defaults.
Utility hook for generating spring animation configurations with proper defaults and type safety.
/**
* Hook for generating spring animation configurations
* Currently a pass-through function that may be enhanced in future versions
* @param configs - Spring animation configuration (excludes velocity)
* @returns Memoized spring configuration object
*/
declare function useBottomSheetSpringConfigs(
configs: Omit<WithSpringConfig, 'velocity'>
): Omit<WithSpringConfig, 'velocity'>;
interface WithSpringConfig {
/** Damping ratio for spring animation */
damping?: number;
/** Stiffness of the spring */
stiffness?: number;
/** Mass of the object being animated */
mass?: number;
/** Initial velocity (managed internally by library) */
velocity?: number;
/** Whether to clamp overshoot */
overshootClamping?: boolean;
/** Threshold for displacement at rest */
restDisplacementThreshold?: number;
/** Threshold for speed at rest */
restSpeedThreshold?: number;
/** Reduce motion accessibility setting */
reduceMotion?: ReduceMotion;
}Usage Examples:
import React, { useMemo } from 'react';
import { View } from 'react-native';
import BottomSheet, {
useBottomSheet,
useBottomSheetSpringConfigs
} from '@gorhom/bottom-sheet';
// Basic spring configuration
const SpringExample = () => {
const springConfigs = useBottomSheetSpringConfigs({
damping: 80,
stiffness: 500,
mass: 1,
overshootClamping: true,
restDisplacementThreshold: 0.1,
restSpeedThreshold: 0.1,
});
const { snapToIndex } = useBottomSheet();
const handleSnapWithSpring = () => {
snapToIndex(1, springConfigs);
};
return (
<View>
<Button title="Snap with Spring" onPress={handleSnapWithSpring} />
</View>
);
};
// Bouncy spring animation
const BouncySpringExample = () => {
const bouncySpring = useBottomSheetSpringConfigs({
damping: 15,
stiffness: 200,
mass: 2,
overshootClamping: false, // Allow overshoot for bounce effect
});
const { expand } = useBottomSheet();
const expandWithBounce = () => {
expand(bouncySpring);
};
return (
<View>
<Button title="Bouncy Expand" onPress={expandWithBounce} />
</View>
);
};
// Stiff, fast spring
const FastSpringExample = () => {
const fastSpring = useBottomSheetSpringConfigs({
damping: 50,
stiffness: 1000,
mass: 0.5,
overshootClamping: true,
});
const { close } = useBottomSheet();
const fastClose = () => {
close(fastSpring);
};
return (
<View>
<Button title="Fast Close" onPress={fastClose} />
</View>
);
};
// Responsive to reduce motion settings
const AccessibleSpringExample = () => {
const accessibleSpring = useBottomSheetSpringConfigs({
damping: 80,
stiffness: 400,
reduceMotion: ReduceMotion.System, // Respects system settings
});
const { snapToIndex } = useBottomSheet();
const accessibleSnap = () => {
snapToIndex(2, accessibleSpring);
};
return (
<View>
<Button title="Accessible Snap" onPress={accessibleSnap} />
</View>
);
};Generates timing animation configurations with sensible defaults for duration and easing functions.
/**
* Hook for generating timing animation configurations
* Provides defaults: duration: 250ms, easing: Easing.out(Easing.exp)
* @param configs - Timing animation configuration
* @returns Memoized timing configuration object
*/
declare function useBottomSheetTimingConfigs(
configs: TimingConfig
): TimingConfig;
interface TimingConfig {
/** Animation duration in milliseconds */
duration?: number;
/** Easing function for animation curve */
easing?: EasingFunction | EasingFunctionFactory;
/** Reduce motion accessibility setting */
reduceMotion?: ReduceMotion;
}Usage Examples:
import React from 'react';
import { View, Button } from 'react-native';
import { Easing } from 'react-native-reanimated';
import BottomSheet, {
useBottomSheet,
useBottomSheetTimingConfigs
} from '@gorhom/bottom-sheet';
// Basic timing configuration
const TimingExample = () => {
const timingConfigs = useBottomSheetTimingConfigs({
duration: 300,
easing: Easing.bezier(0.25, 0.46, 0.45, 0.94),
});
const { snapToIndex } = useBottomSheet();
const handleSnapWithTiming = () => {
snapToIndex(1, timingConfigs);
};
return (
<View>
<Button title="Snap with Timing" onPress={handleSnapWithTiming} />
</View>
);
};
// Fast, snappy animation
const FastTimingExample = () => {
const fastTiming = useBottomSheetTimingConfigs({
duration: 150,
easing: Easing.out(Easing.quad),
});
const { collapse } = useBottomSheet();
const fastCollapse = () => {
collapse(fastTiming);
};
return (
<View>
<Button title="Fast Collapse" onPress={fastCollapse} />
</View>
);
};
// Slow, smooth animation
const SmoothTimingExample = () => {
const smoothTiming = useBottomSheetTimingConfigs({
duration: 600,
easing: Easing.bezier(0.4, 0.0, 0.2, 1.0), // Material Design easing
});
const { expand } = useBottomSheet();
const smoothExpand = () => {
expand(smoothTiming);
};
return (
<View>
<Button title="Smooth Expand" onPress={smoothExpand} />
</View>
);
};
// Custom easing curves
const CustomEasingExample = () => {
const customTiming = useBottomSheetTimingConfigs({
duration: 400,
easing: Easing.inOut(Easing.back(1.5)), // Back easing with custom factor
});
const { snapToPosition } = useBottomSheet();
const customSnap = () => {
snapToPosition('75%', customTiming);
};
return (
<View>
<Button title="Custom Easing Snap" onPress={customSnap} />
</View>
);
};
// Accessibility-aware timing
const AccessibleTimingExample = () => {
const accessibleTiming = useBottomSheetTimingConfigs({
duration: 250,
easing: Easing.out(Easing.exp),
reduceMotion: ReduceMotion.System,
});
const { close } = useBottomSheet();
const accessibleClose = () => {
close(accessibleTiming);
};
return (
<View>
<Button title="Accessible Close" onPress={accessibleClose} />
</View>
);
};The library provides platform-specific default configurations:
/** Platform-specific default animation configurations */
const ANIMATION_CONFIGS = Platform.select<TimingConfig | SpringConfig>({
android: {
duration: 250,
easing: Easing.out(Easing.exp),
},
default: {
damping: 500,
stiffness: 1000,
mass: 3,
overshootClamping: true,
restDisplacementThreshold: 10,
restSpeedThreshold: 10,
},
});
const ANIMATION_EASING: EasingFunction = Easing.out(Easing.exp);
const ANIMATION_DURATION = 250;All animation configurations support accessibility settings:
enum ReduceMotion {
/** Follow system accessibility settings (default) */
System = 'system',
/** Always disable animations */
Always = 'always',
/** Never disable animations */
Never = 'never',
}Usage with Reduce Motion:
// Automatically respect system settings
const respectfulAnimation = useBottomSheetSpringConfigs({
damping: 80,
stiffness: 400,
reduceMotion: ReduceMotion.System, // Default behavior
});
// Force disable animations
const noAnimation = useBottomSheetTimingConfigs({
duration: 0, // Instant
reduceMotion: ReduceMotion.Always,
});
// Force enable animations
const alwaysAnimated = useBottomSheetSpringConfigs({
damping: 50,
stiffness: 300,
reduceMotion: ReduceMotion.Never,
});For rapid interactions like buttons or toggles:
const quickAnimation = useBottomSheetTimingConfigs({
duration: 150,
easing: Easing.out(Easing.quad),
});For content changes or navigation:
const smoothAnimation = useBottomSheetSpringConfigs({
damping: 80,
stiffness: 500,
mass: 1,
});For engaging user interactions:
const playfulAnimation = useBottomSheetSpringConfigs({
damping: 20,
stiffness: 300,
mass: 1.5,
overshootClamping: false,
});For exact positioning requirements:
const preciseAnimation = useBottomSheetSpringConfigs({
damping: 100,
stiffness: 800,
mass: 0.8,
overshootClamping: true,
restDisplacementThreshold: 0.1,
restSpeedThreshold: 0.1,
});Common easing functions available from React Native Reanimated:
// Linear
Easing.linear
// Quadratic
Easing.quad
Easing.in(Easing.quad)
Easing.out(Easing.quad)
Easing.inOut(Easing.quad)
// Cubic
Easing.cubic
Easing.in(Easing.cubic)
Easing.out(Easing.cubic)
Easing.inOut(Easing.cubic)
// Exponential
Easing.exp
Easing.in(Easing.exp)
Easing.out(Easing.exp)
Easing.inOut(Easing.exp)
// Back
Easing.back(overshoot)
Easing.in(Easing.back(1.7))
Easing.out(Easing.back(1.7))
Easing.inOut(Easing.back(1.7))
// Bounce
Easing.bounce
Easing.in(Easing.bounce)
Easing.out(Easing.bounce)
Easing.inOut(Easing.bounce)
// Bezier curves
Easing.bezier(x1, y1, x2, y2)