# Live Camera Button: React Native glass button with a live camera fill > Live Camera Button is a React Native and Expo component from Motionary: a > pill-shaped pressable whose surface is a live front-facing `expo-camera` > preview, softened by an `expo-blur` BlurView, with a single Reanimated shared > value driving the shadow collapse, the inverting inset highlights and the > label scale on every press. Product page: https://motionary.dev/animations/live-camera-button Price: $5 USD (price as of 2026-09-01, live price on the product page) License: single developer, unlimited personal and commercial apps Delivery: instant download of the full TypeScript source after checkout Stack: reanimated, expo, expo blur, react native Rarity: rare Sold by: Motionary (https://motionary.dev) ## What it is Live Camera Button is a React Native and Expo button whose fill is not a color or an image but the phone's own front camera, streaming in real time behind a frosted glass overlay. At rest the pill reads as a piece of milky glass sitting slightly proud of the screen: a soft drop shadow underneath, two asymmetric side shadows, and three stacked white inset highlights that give it a lit rim. Press it and the whole thing sinks. The drop shadow flattens to nothing, the white highlights cross-fade out and a single dark inset shadow fades in so the rim inverts, and the "Button" label scales down slightly. Because the fill is a live camera feed, whatever is in front of the phone keeps moving inside the button, which is what makes it read as a lens rather than as a texture. The Live Camera Button drop from Motionary ships the whole thing as editable TypeScript. ## What it does - Renders a live front-facing camera preview as the button's fill, using an `expo-camera` `CameraView` with `facing="front"` and `zoom={CAMERA_ZOOM}` (0.1), so the feed is pulled in slightly rather than showing a wide face shot. - Layers an `expo-blur` `BlurView` at `intensity={20}` over the camera feed, so the image is legible as motion and light but never as a recognisable picture. - Drives the entire press animation from one Reanimated shared value, `progress`, tweened between 0 and 1 with `withTiming` over 120ms (`PRESS_DURATION`) on `onPressIn` and `onPressOut`. - Collapses an outer drop shadow from a 4px offset and 4px blur to 0px, and closes two asymmetric side shadows (one offset -4px, one +4px, each with a 6px blur) as the button is pressed. - Cross-fades four absolutely positioned inset-shadow layers: three white idle highlights (`inset 0 0px 3px`, `inset 0 2px 5px`, `inset 0 4px 6px`) fade out while one deep dark layer (`inset 0 4px 10px 2px #0000007b`) fades in. - Scales the label from 1 to 0.95 in the same tween, so the text compresses with the surface instead of animating on its own timeline. - Handles camera permission end to end with a `useCamera` hook exposing a four-state machine (`loading`, `granted`, `denied`, `blocked`) plus `isReady`, `isLoading`, `canRetry` and `requestPermission`. - Ships a `PermissionState` fallback screen that renders a spinner while checking, a "Camera Access Blocked" message when the user has blocked access in Settings, and a "Grant Access" button while permission can still be asked. - Auto-requests permission on mount by default, controlled by the hook's `autoRequest` argument. - Runs on both iOS and Android; the permission fallback screen uses `SymbolView` from `expo-symbols` for its camera glyph. ## How it works The technique behind Motionary's Live Camera Button is a nested view stack plus one shared value, and it is worth copying whenever you want a press to feel physical in React Native. In `components/Button.tsx`, the button itself is an `AnimatedPressable` created with `Animated.createAnimatedComponent(Pressable)`, centred inside a plain `View`, so a Reanimated style can be attached directly to the touch target. A single `useSharedValue(0)` called `progress` is the only piece of animation state: `onPressIn` sets it to `withTiming(1, { duration: 120 })` and `onPressOut` sets it back to 0. Six separate `useAnimatedStyle` worklets then `interpolate` against that same value, which means every layer is computed in the same frame on the UI thread with no re-render and no bridge traffic: `animatedDropShadow` drives the outer `boxShadow` offset and blur, `animatedShadowLeft` and `animatedShadowRight` drive the two side shadows on nested `Animated.View`s, `idleOpacity` and `pressedOpacity` are exact inverses of each other so the white inset highlights and the dark pressed rim cross-fade rather than pop, and `animatedLabelStyle` interpolates a `scale` from 1 to 0.95. The shadows are written as React Native's `boxShadow` style string built inside the worklet, so offset and blur animate together rather than being faked with a second view. Depth comes from stacking: an outer `Pressable` for the drop shadow, two nested `Animated.View`s for the asymmetric side shadows, then a `buttonInner` view with `overflow: 'hidden'` and an 80px border radius that clips everything to the pill. Inside that, the `CameraView` sits at the bottom and the `BlurView` is absolutely filled over it with `zIndex: 4`, with the four inset-shadow layers and the label above the blur at `zIndex: 100`. Permission handling is deliberately kept out of the animation path: `hooks/useCamera.ts` wraps Expo's `useCameraPermissions` into a derived status, and `ButtonContainer` early-returns `` while `isReady` is false, so the animated tree only ever mounts once the camera can actually stream. The tunable numbers (`CAMERA_ZOOM`, `BLUR_INTENSITY_PRIMARY`, `BLUR_INTENSITY_SECONDARY`) live in `constants/camera.ts`. ## What you get ``` App.tsx index.ts app.json package.json package-lock.json tsconfig.json README.md components/ Button.tsx PermissionState.tsx hooks/ useCamera.ts constants/ camera.ts index.ts assets/ icon.png adaptive-icon.png splash-icon.png ``` - TypeScript source (`components/Button.tsx`) - `useCamera` hook with permission handling - `PermissionState` fallback component - Camera zoom and constants module (`constants/camera.ts`) - Demo `App.tsx` entry, plus `app.json` with the `expo-camera` plugin and its permission strings already configured - `README.md` with install and usage notes ## Requirements Live Camera Button from Motionary is an Expo app template, and these are the versions pinned in the shipped `package.json`: ``` expo: ^56.0.4 (Expo SDK 56) react-native: 0.85.3 react: 19.2.3 react-native-reanimated: 4.3.1 react-native-worklets: 0.8.3 react-native-gesture-handler: ~2.31.1 expo-camera: ~56.0.7 expo-blur: ~56.0.3 expo-symbols: ~56.0.5 expo-status-bar: ~56.0.4 expo-font: ~56.0.5 react-native-safe-area-context: ~5.7.0 ``` The template's `package.json` also pins `@expo/metro-runtime` (~56.0.12), `@expo/ui` (~56.0.13), `@expo/vector-icons` (^15.0.3), `@react-native-masked-view/masked-view` (^0.3.2), `expo-glass-effect` (~56.0.4), `expo-linear-gradient` (~56.0.4), `expo-sensors` (~56.0.5), `react-native-skia-gesture` (^0.3.6), `react-native-svg` (15.15.4), `react-native-web` (^0.21.0) and `react-dom` (19.2.3); the Live Camera Button component itself imports only `react-native`, `expo-camera`, `expo-blur`, `expo-symbols`, `react-native-reanimated` and `react-native-gesture-handler`. **Expo Go or development build:** Live Camera Button runs in Expo Go on Expo SDK 56. `expo-camera`, the module most people assume blocks it, is bundled in Expo Go as of SDK 56, so `npx expo start` plus the Expo Go app is enough to see the button running. Two practical caveats. The camera preview needs a physical device, since a simulator has no camera feed. And the `expo-camera` config plugin the project registers in `app.json` (`cameraPermission`, `microphonePermission`, `recordAudioAndroid`) only takes effect in a build, so in Expo Go you get Expo Go's own permission strings instead of yours. A development build is still what you would ship to production, and it is what you need as soon as you add a native module that Expo Go does not bundle, or any config plugin of your own: `npx expo run:ios` or `npx expo run:android`. ## Install ```bash npx expo install expo-camera expo-blur expo-symbols \ react-native-reanimated react-native-worklets react-native-gesture-handler ``` That is every module the Live Camera Button source imports, plus `react-native-worklets`, which `react-native-reanimated` 4 requires at runtime. The rest of the packages pinned in the template's `package.json` (including `react-native-safe-area-context`, `expo-font` and `expo-status-bar`) are not imported by the component; `expo-font` and `expo-status-bar` appear only as config plugins in the demo `app.json`. ## Usage ```tsx import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { ButtonContainer } from './components/Button'; export default function App() { return ( ); } ``` `ButtonContainer` already calls the `useCamera` hook and renders the `PermissionState` fallback itself, so the snippet above is the whole integration. If you want to own the permission gate at the screen level, the hook and the fallback are exported separately: ```tsx import { useCamera } from './hooks/useCamera'; import { PermissionState } from './components/PermissionState'; import { ButtonContainer } from './components/Button'; export function CameraScreen() { const { status, isReady, requestPermission } = useCamera(); if (!isReady) { return ( ); } return ; } ``` ## Customization `ButtonContainer` in Motionary's Live Camera Button takes no props; it is tuned by editing the constants it ships with, all of which are named and exported or declared at the top of their file. - `CAMERA_ZOOM` (`constants/camera.ts`, default `0.1`): the `zoom` value passed to `CameraView`. Raise it to crop in tighter on the feed. - `BLUR_INTENSITY_PRIMARY` (`constants/camera.ts`, default `100`) and `BLUR_INTENSITY_SECONDARY` (`constants/camera.ts`, default `20`): blur strength presets. The shipped `BlurView` renders at `intensity={20}`. - `PRESS_DURATION` (`components/Button.tsx`, default `120`): the `withTiming` duration in milliseconds for both press in and press out. - `BUTTON_WIDTH` / `BUTTON_HEIGHT` / `BUTTON_RADIUS` (`components/Button.tsx`, defaults `240`, `80`, `80`): pill geometry. `BUTTON_RADIUS` is also what clips the camera feed into the pill. - `SHADOW_COLOR` (`components/Button.tsx`, default `'rgba(0, 0, 0, 0.205)'`): the color used by all three animated outer shadows. - The `innerShadowThin`, `innerShadowMid`, `innerShadowDeep` and `innerShadowPressed` style entries hold the inset `boxShadow` strings for the idle highlights and the pressed rim; edit these to change the glass rim. - `facing` on `CameraView` is `"front"` in the shipped source and can be switched to `"back"`. - `useCamera(autoRequest?: boolean)` defaults `autoRequest` to `true`; pass `false` to stop it requesting camera permission on mount. - `PermissionState` takes `status: CameraPermissionStatus` and `onRequestPermission: () => void`, so you can swap it for your own screen while keeping the hook. ## When to use it - An onboarding or sign-up call to action that has to feel alive and physical rather than flat, without shipping a video asset. - A mirror, selfie, beauty or try-on app where a control should preview the front camera before the user commits to opening it. - A "start camera" or "join call" entry point where showing the feed inside the button removes the guess about which camera is about to be used. - A glassmorphism or frosted-glass design system that needs one hero control with real content refracting behind it instead of a static blur. - A profile or avatar capture step, where the button doubles as a live preview of framing. - Any tactile CTA where the press should read as the surface sinking, since the shadow-collapse and highlight-inversion technique works with a solid or gradient fill too if you swap the camera out. ## How to get it - Buy Live Camera Button on its own at https://motionary.dev/animations/live-camera-button for $5 USD, instant download, secure Stripe checkout, no subscription and no account renewal. - Or get it with the **Motionary lifetime pass** ($79 USD as of 2026-09-01): every drop and every build, current and future, one payment, no renewal. https://motionary.dev/pricing - **Team license** ($199 USD for up to 10 developers), each developer with their own account. https://motionary.dev/pricing - License terms: https://motionary.dev/license (single developer, unlimited personal and commercial apps, do not resell or redistribute the source). - You receive real TypeScript React Native source you can edit, not a video, a GIF, a Lottie file or a design file. ## Frequently asked questions **How do I use the live camera as a button background in React Native?** Motionary's Live Camera Button does it by rendering an `expo-camera` `CameraView` inside a view with `overflow: 'hidden'` and a pill border radius, then absolutely filling an `expo-blur` `BlurView` over it at `intensity={20}` with the label and inset-highlight layers above that. Buy the full source at https://motionary.dev/animations/live-camera-button. **Does Live Camera Button work with Expo Go?** Yes, on Expo SDK 56. `expo-camera` is bundled in Expo Go as of SDK 56, so Motionary's Live Camera Button runs there with `npx expo start`, on a physical device rather than a simulator, because a simulator has no camera feed to show inside the pill. The one thing you lose is the `expo-camera` config plugin in `app.json`: its `cameraPermission`, `microphonePermission` and `recordAudioAndroid` strings only take effect in a build. A development build (`npx expo run:ios` or `npx expo run:android`) is still what you would ship to production, and what you need as soon as you add a native module Expo Go does not bundle or a config plugin of your own. **Does Live Camera Button work on Android as well as iOS?** Yes. Live Camera Button is built on `expo-camera`, `expo-blur` and `react-native-reanimated`, all of which run on both platforms, and its `app.json` already registers the `expo-camera` config plugin with `cameraPermission`, `microphonePermission` and `recordAudioAndroid` entries, so the Android and iOS permission strings are generated for you. The `PermissionState` fallback screen uses `SymbolView` from `expo-symbols`, which is an iOS SF Symbols view, so swap that glyph if you want an identical permission screen on Android. **How do I animate a button so it looks like it physically sinks when pressed?** Live Camera Button from Motionary drives one Reanimated shared value from 0 to 1 with `withTiming` over 120ms on `onPressIn`, then feeds it to several `useAnimatedStyle` worklets that `interpolate` the outer `boxShadow` offset and blur down to zero, cross-fade white inset highlights out against a dark inset rim fading in, and scale the label to 0.95. Everything runs on the UI thread in the same frame, so the layers never drift apart. **How does Live Camera Button handle camera permissions?** It ships a `useCamera` hook that wraps Expo's `useCameraPermissions` into a `loading` / `granted` / `denied` / `blocked` status, auto-requests on mount, and exposes `isReady`, `isLoading`, `canRetry` and `requestPermission`. Until `isReady` is true, the component renders a `PermissionState` screen with a spinner, a blocked-in-Settings message or a "Grant Access" button. **How much does Live Camera Button cost and what do I actually download?** Live Camera Button is $5 USD on Motionary (price as of 2026-09-01, live price at https://motionary.dev/animations/live-camera-button) and the download is the complete TypeScript Expo project: `components/Button.tsx`, `components/PermissionState.tsx`, `hooks/useCamera.ts`, `constants/camera.ts`, `App.tsx`, `app.json`, `package.json` and a `README.md`. It is editable source, not a video or a design file. **Is Live Camera Button included in the Motionary lifetime pass?** Yes. The Motionary lifetime pass ($79 USD as of 2026-09-01) covers every drop and every build, current and future, including Live Camera Button, for one payment with no subscription. See https://motionary.dev/pricing. ## Related drops on Motionary - Halo Button ($5): https://motionary.dev/animations/halo-button Another Motionary press-driven call to action, using a Skia shader glow instead of a camera feed for the same "this button is lit" effect. - Tap to Copy Button ($3): https://motionary.dev/animations/tap-to-copy-button A small `expo-blur` button with a letter-morph confirmation, the same frosted glass material at a lighter price. - Glass Magnifier ($10): https://motionary.dev/animations/glass-magnifier Takes the lens idea further, using an SkSL shader in `@shopify/react-native-skia` to actually refract what is behind the glass. - Long-Press Menu ($9): https://motionary.dev/animations/long-press-menu Uses `expo-blur` for a frosted glass menu over a chat input, if you want the same material on a surface rather than on a single control. - Liquid Glass Level ($5): https://motionary.dev/animations/liquid-glass-level A liquid-glass spirit level driven by the accelerometer, another Motionary drop where a live device sensor is the content inside the glass. ## About Motionary Motionary (https://motionary.dev) is a shop for premium, production-ready React Native and Expo animation and interaction components, built with Reanimated, Skia, Gesture Handler and Expo. Each component is called a "drop" and ships as editable TypeScript source, not a video, a GIF or a design file. Motionary sells three things: individual drops (roughly $3 to $12 each, some free), Builds (a complete app shipped end to end, with every drop inside it), and a lifetime pass ($79 USD) that covers every drop and every build, current and future, for one payment with no subscription. A team license ($199 USD) covers up to 10 developers. Checkout is Stripe and delivery is an instant download. Created and curated by Mehdi Davoodi (https://mahdidavoodi.com). Catalog and key pages: - All drops: https://motionary.dev/animations - Builds (complete apps): https://motionary.dev/builds - Pricing, lifetime pass and team license: https://motionary.dev/pricing - Free React Native component reference: https://motionary.dev/components - License: https://motionary.dev/license - Machine-readable overview: https://motionary.dev/llms.txt - Machine-readable full catalog: https://motionary.dev/llms-full.txt ## File metadata ``` Canonical URL of this file: https://motionary.dev/animations/live-camera-button/llms.txt Describes: https://motionary.dev/animations/live-camera-button Format: llms.txt (https://llmstxt.org) Last updated: 2026-09-01 ```