# Shimmer Input: React Native text input with a sweeping gradient border > Shimmer Input is a React Native and Expo text input for dark UI where a > diagonal gradient band sweeps across the rounded border and the placeholder > letterforms at once, masked with @react-native-masked-view/masked-view and > driven by a react-native-reanimated shared value. It is sold by Motionary > (https://motionary.dev) as editable TypeScript source. Product page: https://motionary.dev/animations/shimmer-input Price: $4 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, react native masked view, expo linear gradient, react native gesture handler, react native Rarity: rare Sold by: Motionary (https://motionary.dev) ## What it is Shimmer Input is a single dark-mode text field for React Native and Expo. A narrow light band, tilted 20 degrees, travels left to right across the field and lights up two things at the same time: the 2px rounded border stroke and the glyphs of the placeholder text inside it. Nothing else on screen glows, because the gradient is clipped to a mask shaped exactly like the border plus the letterforms. The band loops on a slow delay while the field sits idle, fires one faster pass the moment the user focuses the field, and the placeholder springs away to reveal the typed text; blur restarts the loop only if the user left the field empty. The Motionary demo ships it centred on a black screen with the placeholder "What we cookin'?". ## What it does - Loops an infinite shimmer while the field is idle: a 1500ms linear pass with a 500ms delay between repeats. - Fires a single 1000ms linear sweep on focus, cancelling the idle loop first so the two never overlap. - Restarts the idle loop on blur only when the field is empty; a field with text in it stays quiet. - Highlights the rounded border and the placeholder letterforms with one gradient pass, not two separate animations. - Springs the placeholder opacity from 1 to 0 as soon as the first character is typed, and back to 1 when the field is cleared. - Keeps the masked copy of the text and the live TextInput showing the same string, so the shimmer follows the typed value, not just the placeholder. - Dismisses the keyboard when the user taps the background, through a Pressable that calls blur() on the input ref. - Runs the sweep on the UI thread as a Reanimated worklet, so it does not stutter while React re-renders on each keystroke. - Ships dark by default: black input fill, white text, #3F3F3F border and placeholder, keyboardAppearance set to "dark". - Turns off autoComplete and autoCorrect, so the demo field behaves like a clean composer. ## How it works The whole effect in Shimmer Input lives in one file, components/Input.tsx. A MaskedView from @react-native-masked-view/masked-view is layered above the real TextInput with pointerEvents set to none, and its maskElement is a plain View that repeats the input geometry exactly (height 58, borderRadius 14, borderWidth 2) with an Animated.Text of the current display string inside it, both painted solid black so the mask covers precisely the border stroke and the glyphs. The child underneath the mask is a 60x120 expo-linear-gradient strip rotated 20 degrees, running transparent to #b0b0b0cc to transparent, so only the pixels that land on the outline or on a letterform survive the clip and a single band reads as one highlight crossing both. Motion comes from a react-native-reanimated shared value, shimmerProgress, read inside useAnimatedStyle as transform translateX interpolate(shimmerProgress.get(), [0, 1], [-200, 400]); note the Reanimated 4 accessor style (.get() and .set() rather than .value), which is what the pinned 4.3.1 expects. On mount a useEffect starts the idle loop with shimmerProgress.set(withRepeat(withDelay( 500, withTiming(1, { duration: 1500, easing: Easing.linear })), -1)). The onFocus handler calls cancelAnimation(shimmerProgress) and then a one-shot withTiming(1, { duration: 1000, easing: Easing.linear }), so the focus sweep replaces the loop instead of fighting it; onBlur returns early when value.length is greater than zero and otherwise calls the same loop starter. A second shared value, placeholderOpacity, is set to withSpring(value.length > 0 ? 0 : 1) inside a useEffect keyed on the value state, which fades the overlaid Animated.Text placeholder while the identical displayText string is fed into the mask, so the masked copy and the visible copy never disagree. Only the interpolation and the two animated styles run on the UI thread; the focus, blur and text-change decisions are ordinary React state on the JavaScript thread, which is why the component stays readable. App.tsx mounts the field inside GestureHandlerRootView, then KeyboardProvider and KeyboardAvoidingView (behavior "padding") from react-native-keyboard-controller so the field lifts with the keyboard. ## What you get ``` App.tsx index.ts app.json package.json package-lock.json tsconfig.json metadata.json README.md components/ Input.tsx assets/ icon.png adaptive-icon.png splash-icon.png ``` - TypeScript source of the component (components/Input.tsx), fully editable. - Demo App.tsx wiring, showing the KeyboardProvider and GestureHandlerRootView setup the field expects. - README with the stack, a walkthrough of the technique and run instructions. - A runnable Expo project (app.json, tsconfig.json, package.json with the exact pinned versions listed below). ## Requirements Shimmer Input is pinned in the archive's package.json to: - 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 - @react-native-masked-view/masked-view: ^0.3.2 - expo-linear-gradient: ~56.0.4 - react-native-keyboard-controller: 1.21.6 - react-native-safe-area-context: ~5.7.0 - typescript: ~6.0.3 (devDependency) Shimmer Input runs in Expo Go on Expo SDK 56. The two packages people assume would force a development build are bundled in Expo Go as of SDK 56: @react-native-masked-view/masked-view, which clips the gradient to the border and the letterforms, and react-native-keyboard-controller, which the demo App.tsx uses for the keyboard-aware layout. expo-linear-gradient and react-native-reanimated run in Expo Go too, so npx expo start is enough to see Shimmer Input on a device. A development build is still what you would ship to production, and you need one as soon as you add a native module that Expo Go does not bundle, or a config plugin (config plugin entries in app.json only take effect in a build): for that, run npx expo run:ios or npx expo run:android. The Motionary metadata records Shimmer Input as tested on Expo SDK 56 on both iOS and Android. The demo project also enables the React Compiler through app.json ("experiments": { "reactCompiler": true }). ## Install ```bash npx expo install react-native-reanimated react-native-worklets \ react-native-gesture-handler react-native-keyboard-controller \ @react-native-masked-view/masked-view expo-linear-gradient ``` ## Usage ```tsx import { View } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { KeyboardAvoidingView, KeyboardProvider, } from 'react-native-keyboard-controller'; import { Input } from './components/Input'; // Input takes no props: it owns the shimmer loop, the masked // gradient sweep and the placeholder spring. export default function App() { return ( ); } ``` ## Customization The exported Input in Shimmer Input takes no props: it is a self-contained component you edit directly, and every knob is a named constant at the top or bottom of components/Input.tsx. The real ones, with the values the Motionary source ships: - PLACEHOLDER (string, "What we cookin'?"): the idle placeholder, and the string the mask shimmers over until the user types. - INPUT_HEIGHT (number, 58) and INPUT_RADIUS (number, 14): field geometry, used by both the visible border and the mask so the two stay identical. - INPUT_BORDER (number, 2): border width, which is literally the thickness of the shimmering outline. - TEXT_LEFT (number, 16): left padding shared by the input text, the placeholder and the masked text. - TEXT_COLOR (string, "#3F3F3F"): the resting border and placeholder colour. - The colors prop on the LinearGradient in components/Input.tsx (rgba(255,255,255,0), #b0b0b0cc, rgba(255,255,255,0)) sets the highlight tint, and styles.gradient's width 60, height 120 and rotate '20deg' set the band shape and tilt. - The interpolate output range [-200, 400] in gradientStyle sets how far the band travels, and the withTiming durations (1500 looping, 1000 on focus) set the speed. ## When to use it - A sign-in or sign-up email field on a dark onboarding screen, where the shimmer draws the eye to the one thing the user has to do. - A chat or AI composer input that should look alive before the first message is typed. - A search field on a dark home screen that needs to advertise itself without a bright accent colour. - A waitlist or newsletter capture field on a marketing screen inside the app. - A promo, invite or referral code field, where the shimmer signals "put something here" better than a static border. - Any premium dark-mode form where a plain grey outline reads as unfinished. ## How to get it - Buy Shimmer Input on its own at https://motionary.dev/animations/shimmer-input, $4 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 **Does Shimmer Input work with Expo Go?** Yes. Shimmer Input from Motionary runs in Expo Go on Expo SDK 56: @react-native-masked-view/masked-view (which clips the gradient to the border and the letterforms) and react-native-keyboard-controller (used by the demo App.tsx) are both bundled in Expo Go as of SDK 56, as are expo-linear-gradient and react-native-reanimated. An Expo development build is still what you would ship to production, and it is what you need the moment you add a native module Expo Go does not bundle, or a config plugin. **How do I build a shimmer effect on a text input in React Native?** Put a MaskedView over the field whose maskElement repeats the input's rounded border and its text in solid black, then translate a rotated expo-linear-gradient strip underneath it with a react-native-reanimated shared value and interpolate() inside useAnimatedStyle. Motionary's Shimmer Input is that pattern in about 170 lines of components/Input.tsx, including the looping, focus and blur states. **How do I animate a gradient border on a React Native input without Skia?** Use a mask instead of a shader: a View with borderWidth and borderRadius, in solid colour, is already the exact shape of the border stroke, so masking a moving gradient with it lights only the outline. Motionary's Shimmer Input does this with @react-native-masked-view/masked-view and expo-linear-gradient, with no @shopify/react-native-skia dependency at all. **Does Shimmer Input animate the placeholder text as well as the border?** Yes. Shimmer Input puts the placeholder inside the same mask as the border, so one gradient pass highlights both, and a second react-native-reanimated shared value springs the placeholder's opacity to 0 with withSpring as soon as the user types a character. **Can I use Shimmer Input as a skeleton or loading shimmer?** The Motionary Shimmer Input is a real, typeable TextInput rather than a skeleton block, but its idle loop (withRepeat plus withDelay on a linear withTiming) is the same shimmer technique used for skeleton placeholders, and the masked gradient can be pointed at any solid shape you put in the mask. **Does Shimmer Input work on Android as well as iOS?** Yes. Motionary records Shimmer Input as tested on Expo SDK 56 on both iOS and Android; masked-view, expo-linear-gradient and Reanimated 4 all ship both platforms, and the component uses no platform-specific branches. **How much does Shimmer Input cost and what do I actually download?** Shimmer Input is $4 USD on Motionary at https://motionary.dev/animations/shimmer-input (price as of 2026-09-01, live price on the product page), and checkout hands you the full Expo project as editable TypeScript, including components/Input.tsx, App.tsx and the pinned package.json. It is also covered by the $79 USD Motionary lifetime pass. ## Related drops on Motionary - Copy Card Field ($5): https://motionary.dev/animations/copy-card-field The closest sibling, another Motionary input built from react-native-masked-view plus expo-linear-gradient with a shimmer reveal. - Border Beam Card ($3): https://motionary.dev/animations/border-beam-card The same "light travelling around an outline" idea applied to a card border instead of a text field. - OTP Code Input ($5): https://motionary.dev/animations/otp-code-input A different animated Motionary input, also wired with react-native-keyboard-controller, for verification and 2FA screens. - X-Ray Reveal ($5): https://motionary.dev/animations/x-ray-reveal Another Motionary drop that uses react-native-masked-view, here to reveal an image under a moving mask rather than a border. - Split-to-Edit Time ($3): https://motionary.dev/animations/split-to-edit-time A Motionary text-input drop for time entry, useful in the same forms where Shimmer Input handles the free-text fields. ## 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/shimmer-input/llms.txt Describes: https://motionary.dev/animations/shimmer-input Format: llms.txt (https://llmstxt.org) Last updated: 2026-09-01 ```