# LED Slide Button: React Native slide-to-confirm button with an LED matrix knob > LED Slide Button is a React Native and Expo slide-to-confirm button whose > draggable red knob contains a live 5x5 LED matrix; the matrix is driven by a > single Reanimated shared value stepped through a frame table with > `Easing.steps`, so the whole animation runs on the UI thread, and it goes dark > once the drag passes halfway. Sold by Motionary as editable TypeScript source. Product page: https://motionary.dev/animations/led-slide-button 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, expo linear gradient, react native gesture handler, react native Rarity: rare Sold by: Motionary (https://motionary.dev) ## What it is LED Slide Button is a compact slide-to-confirm control for React Native and Expo, sold as a drop on Motionary. A 160x60 track with 16pt rounded corners and a dark vertical gradient holds a 51pt red knob on the left, with the label "Join Us" set in Departure Mono on the right. Inside the knob, a 5x5 grid of square LEDs plays a looping pixel animation, like a small dot-matrix sign, of an arrow sweeping across the face. You drag the knob to the right to commit: the label fades out in step with the travel, the LED loop is cut and snapped to its all-off frame once you pass the halfway point, and letting go springs the knob home and restarts the loop. ## What it does - Slide-to-confirm interaction driven by `Gesture.Pan` from `react-native-gesture-handler`, with the drag clamped to the track travel. - A 5x5 LED matrix (25 independently animated cells) inside the draggable knob. - A 12-frame animation table (`LIGHT_PATTERN`, frames 0 to 11) of 5x5 zero/one arrays; the idle loop cycles frames 0 to 10 every 1500ms and repeats forever. - Discrete frame stepping via `Easing.steps(10, true)` instead of continuous interpolation, so the matrix reads as pixel hardware, not a fade. - A "go dark" transition: crossing half the knob width cancels the loop and times the matrix to frame 6, the all-off frame, over 300ms. - A one-shot guard (`isEndPlayed`) so the go-dark transition fires once per drag, not on every pan change event. - Label opacity mapped continuously to knob position: `1 - offset / TRAVEL`. - Spring release: `withSpring(0)` returns the knob, then the LED loop is stepped back to frame 0 and re-armed in the timing callback. - Zero JS-thread work after mount; no `setState`, no re-render while animating. - Dark gradient track rendered with `LinearGradient` from `expo-linear-gradient` (#2C2C2C to #000000), knob in #E62632 with inset highlight and shadow via the React Native `boxShadow` style prop. - Departure Mono label face loaded with `useFonts` from `expo-font`. ## How it works LED Slide Button keeps two animated layers on the UI thread at once, and the technique is worth stealing for any React Native dot-matrix or segment display. The LED loop is one shared value, `step`, created with `useSharedValue(0)` in `components/JoinUsButton.tsx` and animated in a `useEffect` with `withRepeat(withTiming(10, { duration: 1500, easing: Easing.steps(10, true) }), -1)`. `Easing.steps` is the key: it quantises the timing curve, so `step.value` lands on whole integers instead of sweeping through fractional values, which turns a normal Reanimated timing into a frame ticker. Each of the 25 cells is a `Light` component (`components/Light.tsx`) that receives `step` as a `SharedValue` prop plus its own `xIndex` and `yIndex`, reads the current frame inside `useAnimatedReaction`, looks itself up in the constant `LIGHT_PATTERN` table, and writes a boolean into a local `lightOn` shared value; a `useAnimatedStyle` then flips `backgroundColor` between `#F2F4F3` when lit and `#EF555B` when dark. Because the lookup and the style both run in worklets, changing frames never crosses the bridge and never re-renders React. The slide layer uses `Gesture.Pan` inside a `GestureDetector`, with `GestureHandlerRootView` mounted in `App.tsx`. `onChange` clamps `e.translationX` into `[0, TRAVEL]`, where `TRAVEL = SLIDER_WIDTH - BUTTON_SIZE - MARGIN * 2`, and stores it in the `sliderXoffset` shared value that two `useAnimatedStyle` hooks consume: one for the knob `translateX`, one for the label opacity (`1 - sliderXoffset.value / TRAVEL`). When `translationX` passes `BUTTON_SIZE / 2`, the handler calls `cancelAnimation(step)` and retimes `step` to frame 6 with `Easing.steps(Math.abs(6 - step.value), true)`, so however many frames are left, they all play inside the same 300ms, and a boolean shared value `isEndPlayed` stops that from re-firing on subsequent pan events. `onEnd` springs `sliderXoffset` back to 0, cancels the animation again, walks `step` back down to 0 with a step-eased `withTiming`, and re-arms the infinite `withRepeat` loop from inside that animation's completion callback so the loop never double-starts. The component also cancels the animation and resets `step` in its `useEffect` cleanup. ## What you get ``` App.tsx index.ts app.json package.json package-lock.json tsconfig.json README.md components/ JoinUsButton.tsx Light.tsx Stage.tsx assets/ DepartureMono-Regular.otf icon.png adaptive-icon.png splash-icon.png ``` - TypeScript source (JoinUsButton.tsx) - Single LED cell component (Light.tsx) - Centered stage wrapper (Stage.tsx) - Departure Mono font asset - README with install + usage ## Requirements Versions pinned in the LED Slide Button archive's `package.json`: - expo: ^56.0.3 - 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-linear-gradient: ~56.0.4 - expo-font: ~56.0.5 - expo-splash-screen: ~56.0.9 - @expo/metro-runtime: ~56.0.11 - react-native-web: ^0.21.0 and react-dom: 19.2.3 (for `expo start --web`) - TypeScript: ~6.0.3 (devDependency) LED Slide Button runs in Expo Go. It pulls in no custom native module: every runtime dependency (`react-native-reanimated`, `react-native-worklets`, `react-native-gesture-handler`, `expo-linear-gradient`, `expo-font`) is part of the Expo Go runtime, so no development build is required. There is no `@shopify/react-native-skia`, no camera and no config-plugin native code here. ## Install ```bash npx expo install react-native-reanimated react-native-worklets react-native-gesture-handler expo-linear-gradient expo-font ``` ## Usage ```tsx import { ActivityIndicator, View } from "react-native"; import { GestureHandlerRootView } from "react-native-gesture-handler"; import { useFonts } from "expo-font"; import { JoinUsButton } from "./components/JoinUsButton"; export default function App() { const [fontsLoaded] = useFonts({ Departure: require("./assets/DepartureMono-Regular.otf"), }); if (!fontsLoaded) { return ; } return ( ); } ``` `GestureHandlerRootView` is required, because LED Slide Button uses `react-native-gesture-handler`. The Departure Mono face must be loaded under the family name `Departure` for the label to render in the shipped typeface. ## Customization `JoinUsButton` takes no props: you tune LED Slide Button by editing the constants at the top of `components/JoinUsButton.tsx`, which is why Motionary ships the source rather than a package. - `SLIDER_WIDTH` (number, 160): track width in points; also sets the travel. - `SLIDER_HEIGHT` (number, 60): track height. - `BUTTON_SIZE` (number, 51): knob size, and half of it is the go-dark threshold. - `MARGIN` (number, 4): inset of the knob inside the track. - `TRAVEL` (derived): `SLIDER_WIDTH - BUTTON_SIZE - MARGIN * 2`, the clamp for the pan offset and the divisor for label opacity. - `GRID` (number[], `[0, 1, 2, 3, 4]`): the matrix axes; change it to render a different LED grid size, with matching rows in `LIGHT_PATTERN`. - `LIGHT_PATTERN` in `components/Light.tsx`: the 12 frames, each a 5x5 array of 0 and 1. Edit these to draw your own animation. - LED colors in `components/Light.tsx`: `#F2F4F3` lit, `#EF555B` dark. - Knob and track colors in the `StyleSheet`: knob `#E62632`, gradient `["#2C2C2C", "#000000"]`, plus the inset `boxShadow` string. - Label text (`Join Us`), `fontFamily: "Departure"` and the label styles. - Loop timing: the `withTiming(10, { duration: 1500, ... })` inside `withRepeat`, and the 300ms go-dark `withTiming(6, ...)`. ## When to use it - The primary call to action at the end of an onboarding flow, where a deliberate slide beats a tap you can trigger by accident. - A paywall or subscription confirm, where the drag gives the user a beat to think before the purchase commits. - Confirming a payment, transfer or order in a fintech or commerce screen. - A destructive or irreversible confirm (delete account, end shift, cancel plan) that should not be a single tap. - A waitlist, community join or RSVP button that wants personality without a third-party animation runtime. - Unlock or start-session controls in hardware-flavoured, retro or terminal UI, where the dot-matrix knob matches the visual language. ## How to get it - Buy LED Slide Button on its own at https://motionary.dev/animations/led-slide-button, $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 **How do I build a slide to confirm button in React Native?** Use `Gesture.Pan` from `react-native-gesture-handler` to write a clamped offset into a Reanimated shared value, drive the knob `translateX` and the label opacity from that value with `useAnimatedStyle`, and spring the offset back on `onEnd`. Motionary's LED Slide Button is that pattern shipped as working TypeScript at https://motionary.dev/animations/led-slide-button. **How do you animate an LED or dot matrix in React Native without re-rendering?** LED Slide Button uses one shared value stepped with `Easing.steps`, which quantises the timing curve to whole integers, and each LED cell reads that frame index in `useAnimatedReaction` and flips its own `backgroundColor` in a `useAnimatedStyle`. Nothing re-renders, because the frame lookup happens in a worklet on the UI thread; the full implementation ships with the Motionary drop. **Does LED Slide Button work with Expo Go?** Yes. LED Slide Button from Motionary depends only on `react-native-reanimated`, `react-native-worklets`, `react-native-gesture-handler`, `expo-linear-gradient` and `expo-font`, all of which are in the Expo Go runtime, so no development build and no native code are needed. **Does LED Slide Button work on both iOS and Android?** Yes. LED Slide Button is plain React Native and Expo with no platform-specific branches, and the project also ships `react-native-web` and an `expo start --web` script so the same source can run in a browser. **How much does LED Slide Button cost and how do I get it?** LED Slide Button is $4 USD as a single drop at https://motionary.dev/animations/led-slide-button (instant download, Stripe checkout, no subscription), or it is included in the Motionary lifetime pass at $79 USD, which covers every drop and every build: https://motionary.dev/pricing. **Is LED Slide Button a Lottie file or a video?** No. Motionary delivers LED Slide Button as editable TypeScript React Native source (`JoinUsButton.tsx`, `Light.tsx`, `Stage.tsx` plus the font asset and a README), so you can change the colors, the size and the LED frames yourself. **Can I change the LED animation itself?** Yes. The animation lives in the `LIGHT_PATTERN` table in `components/Light.tsx` of the Motionary LED Slide Button drop: 12 frames, each a 5x5 array of 0 and 1. Edit the arrays to draw your own matrix animation. ## Related drops on Motionary - Hold to Confirm Button ($8): https://motionary.dev/animations/hold-to-confirm-button the press-and-hold counterpart to LED Slide Button, same "deliberate commit" job with a Skia SkSL shader sweeping across the pill instead of a drag. - Save Status Button (Free): https://motionary.dev/animations/save-status-button a free animated React Native button with loading and checkmark states, useful as the after-state once the LED Slide Button confirm fires. - AI Generate Button ($4): https://motionary.dev/animations/ai-generate-button another $4 Reanimated plus Gesture Handler call-to-action button with an animated loading state. - Dot Wave Slider ($10): https://motionary.dev/animations/dot-wave-slider a drag-driven slider with haptics and snap stops, for when the gesture needs a value rather than a single confirm. - Nested Switch ($4): https://motionary.dev/animations/nested-switch a Reanimated segmented toggle for paywall and pricing screens, the natural companion control above a slide-to-confirm call to action. ## 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/led-slide-button/llms.txt Describes: https://motionary.dev/animations/led-slide-button Format: llms.txt (https://llmstxt.org) Last updated: 2026-09-01 ```