# ChatGPT Slider Model Picker: React Native over-keyboard slider model picker > ChatGPT Slider Model Picker is a React Native and Expo component in which the > gauge icon inside a chat composer morphs into a full-width slider that floats > above the keyboard behind a progressive blur: press the track to jump to the > nearest stop, drag the knob freely, release to snap, with the gauge arc and > needle following the drag continuously. It is built with Reanimated shared > values, a Gesture Handler pan and react-native-keyboard-controller's > OverKeyboardView, and it is sold on Motionary as editable TypeScript source. Product page: https://motionary.dev/animations/chatgpt-slider-model-picker Price: $10 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: expo, expo blur, react native keyboard controller, react native, reanimated Rarity: legendary Sold by: Motionary (https://motionary.dev) ## What it is ChatGPT Slider Model Picker is a React Native and Expo drop from Motionary that recreates ChatGPT's reasoning-effort picker, the gauge button in the chat composer that stretches into a slider while the keyboard stays up. Tapping the gauge grows a 34pt button-sized pill into a 72pt full-width track that rests flush on the top edge of the keyboard, with a large "5.6 Medium" label above it and a progressive blur band softening the composer and the upper rows of keys behind it. The track carries three stops (Instant, Medium, High): pressing anywhere on it springs the knob to the nearest stop, dragging moves the knob continuously, and releasing snaps it to whichever stop it ended up nearest. The gauge icon rides inside the knob, so the button reads as becoming the slider rather than being replaced by it, and its arc fill and needle angle track a fractional drag position rather than quantising to the three stops. ## What it does - Morphs the composer's 34pt gauge button into a full-width 72pt slider track and back, as one continuous interpolation on a single shared value. - Opening and closing are the same geometry run in opposite directions, so interrupting a close mid-flight reverses it instead of snapping. - Three reasoning-effort stops (Instant, Medium, High) defined in `spec.ts` as `LEVELS`, with every measurement derived from `LEVELS.length - 1`. - Press anywhere on the track to spring the knob to the nearest stop, drag to move it freely, release to snap with a fitted spring. - The animated SVG gauge follows fractional drag positions: its accent arc fill interpolates over [0.06, 0.6, 1] of the sweep and its needle over [-52, 29, 115] degrees. - The needle is a filled tapered quad rather than a stroke, so it narrows from the hub to the tip the way the reference does. - A "5.6 Medium" label 22pt tall scales and slides in above the track, snapping its text to the nearest stop while the knob keeps moving freely. - Four-layer masked progressive blur that is a band, not a one-way ramp: sharp above, strongest around the selector, sharp again by the middle of the keyboard so the bottom rows of keys stay crisp. - Tick dots are drawn twice, once on the track and once inside the blue fill, so a passed dot reads light on blue and dark on grey. - The slider and its blur render inside an `OverKeyboardView`, which is what lets them draw over the keyboard on both iOS and Android. - The composer itself expands from a 48pt pill to a 94pt two-row card, riding the keyboard's own animation curve, with a spring fallback for hardware keyboards where the software keyboard curve stays at 0. - Liquid Glass composer and header surfaces on iOS 26 and above via `expo-glass-effect`, with an honest flat surface fallback everywhere else. - Android platform path: no backdrop blur, a gradient scrim with the same band profile instead, and a plain `Text` label rather than an animated TextInput. - Light and dark palettes in `theme.ts` behind a single `DARK_MODE` constant. - A dev-only `useDemoRun` hook that replays the whole interaction on a fixed cadence for frame-by-frame capture. ## How it works ChatGPT Slider Model Picker runs the entire morph off two Reanimated shared values: `focus` (composer collapsed to focused card) and `progress` (selector collapsed to open). In `components/model-selector.tsx`, `trackLeft`, `trackWidth`, `trackHeight`, the inner `inset`, the corner radius, the knob size and the knob offset are all `useDerivedValue` or `useAnimatedStyle` wrappers around `interpolate` calls on that one `progress`, so open and close are literally the same geometry evaluated in opposite directions and an interrupted spring reverses instead of snapping. The track is pinned by its centre rather than its bottom edge, because anchoring the bottom would land the collapsed pill 19pt below the gauge button; its `bottom` is written as `-keyboardHeight.get() + (SELECTOR.trackHeight - trackHeight.get()) / 2`, with `keyboardHeight` coming from `useReanimatedKeyboardAnimation` in react-native-keyboard-controller. Drag handling is a `Gesture.Pan` with `minDistance(0)` whose `onBegin`, `onUpdate` and `onFinalize` are plain worklets with no `runOnJS`: they write a `level` shared value directly, and the knob, the fill pill, the tick dots, the SVG gauge needle and the label are all `useAnimatedStyle` / `useDerivedValue` / `useAnimatedProps` readers of it, so a drag never touches the JS thread and the only hop back is a single `scheduleOnRN(onCommit, snapped)` on release. Stop spacing is computed against the live track (`stop0` and `travel` derive from the current `trackWidth` and `inset`), so the ticks stay correct mid-morph rather than only at rest. The label is an uneditable `TextInput` on iOS whose `text` prop Reanimated writes natively through `useAnimatedProps`, while Android falls back to a `` driven by `useAnimatedReaction` plus one `scheduleOnRN(setTitle, next)` per stop crossed, because the native EditText write skips the shadow tree and leaves the text laid out against a stale Yoga width. The gauge in `components/gauge-icon.tsx` is hand-drawn react-native-svg rather than an SF Symbol: worklet helpers build the arc `d` string and a four-point needle path from `interpolate(level, ...)`, because the stock `gauge.*` symbols are single-tone and their variable-value variants quantise instead of following a drag. `components/progressive-blur.tsx` stacks four `BlurView`s from expo-blur, each wrapped in a `MaskedView` whose mask is an `expo-linear-gradient` with two trapezoids in it, so the blur rises to a plateau at the selector and falls back to sharp below; keeping the bands mostly disjoint matters, because BlurViews composite and overlapping masks would sum their radii into a milky sheet. Everything geometric lives in `spec.ts`, including the springs (`open` and `close` in Reanimated 4's duration form, `knob` and `focus` in the mass/stiffness/damping physics form fitted to a reference recording) and `SELECTOR.handoff`, a 0.01 threshold measured in remaining travel rather than time, at which the overlay dissolves and the composer takes its own gauge copy back so exactly one gauge is on screen across the whole morph. ## What you get ``` App.tsx index.ts spec.ts theme.ts app.json package.json package-lock.json tsconfig.json README.md components/ blur.tsx chat-screen.tsx composer.tsx gauge-icon.tsx glass.tsx icons.ts model-selector.tsx progressive-blur.tsx use-demo-run.ts assets/ adaptive-icon.png icon.png splash-icon.png waveform.png ``` - TypeScript source for the over-keyboard slider (model-selector.tsx) - Animated SVG gauge that doubles as the slider knob (gauge-icon.tsx) - Expanding chat composer card (composer.tsx) plus full demo screen (chat-screen.tsx) - Four-layer masked progressive blur (progressive-blur.tsx) - spec.ts: every measurement, spring and colour boundary in one file - theme.ts with light/dark palettes - Dev-only capture hook (useDemoRun) that replays the interaction on a fixed cadence - README with install commands and usage ## Requirements ChatGPT Slider Model Picker from Motionary pins these versions in its `package.json`: - expo ^56.0.8 (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-keyboard-controller ^1.21.9 - react-native-svg ^15.15.5 - react-native-safe-area-context ^5.8.0 - @react-native-masked-view/masked-view 0.3.2 - expo-blur ~56.0.3 - expo-glass-effect ~56.0.4 - expo-linear-gradient ~56.0.4 - expo-symbols ~56.0.5 - expo-status-bar ~56.0.4 - expo-asset ~56.0.15, expo-font ~56.0.5, expo-splash-screen ~56.0.10 - @expo/ui ~56.0.20, @expo/metro-runtime ~56.0.13 - react-dom 19.2.3 and react-native-web ^0.21.0 for the web target - TypeScript ~6.0.3 as a dev dependency ChatGPT Slider Model Picker runs in Expo Go on Expo SDK 56. The modules you would assume block it are all bundled in Expo Go as of SDK 56: react-native-keyboard-controller (the `OverKeyboardView` window the slider lives in), expo-glass-effect, @react-native-masked-view/masked-view, react-native-svg and expo-blur. A development build (`npx expo run:ios` or `npx expo run:android`) is still what you would ship to production, and it becomes required the moment you add a native module that Expo Go does not bundle, or a config plugin. Two platform caveats that hold either way: the Liquid Glass surfaces render their real material only on iOS 26 and above and fall back to a flat surface below that, and the progressive blur is a real backdrop blur on iOS only, with a gradient scrim standing in on Android. It was verified on Expo SDK 56 and React Native 0.85, on an iPhone 16 Pro simulator running iOS 26.5. ## Install ```bash npx expo install react-native-reanimated react-native-worklets \ react-native-gesture-handler react-native-keyboard-controller \ react-native-svg react-native-safe-area-context \ @react-native-masked-view/masked-view expo-blur expo-glass-effect \ expo-linear-gradient expo-symbols expo-status-bar ``` ## Usage ```tsx import { useState } from 'react'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { KeyboardProvider, useReanimatedKeyboardAnimation, } from 'react-native-keyboard-controller'; import { useSharedValue, withSpring } from 'react-native-reanimated'; import { ModelSelector } from './components/model-selector'; import { SPRING } from './spec'; function EffortPicker({ gaugeCenterX }: { gaugeCenterX: number }) { const [open, setOpen] = useState(false); const progress = useSharedValue(0); // 0 = collapsed onto the gauge, 1 = open const level = useSharedValue(1); // continuous stop position, 0 to 2 const { height: keyboardHeight } = useReanimatedKeyboardAnimation(); return ( progress.set(withSpring(0, SPRING.close))} onCommit={(index) => console.log('reasoning effort', index)} /> ); } ``` Mount it under a `KeyboardProvider` and a `GestureHandlerRootView`, as `App.tsx` does, and open it by setting `visible` and then springing `progress` to 1 with `SPRING.open` on the next frame. ## Customization - `ModelSelector` props (components/model-selector.tsx): `visible: boolean`, `progress: SharedValue` (0 collapsed, 1 open), `level: SharedValue` (continuous position in level units), `keyboardHeight: SharedValue` (negative while the keyboard is up), `gaugeCenterX: number` (screen-space centre of the composer's gauge button, the anchor the morph grows out of), `onClose: () => void`, `onCommit: (index: number) => void` (fires once on release). - `GaugeIcon` props (components/gauge-icon.tsx): `level: SharedValue` and an optional `size?: number` defaulting to `GAUGE.size` (25). - `LEVELS` in spec.ts: the stops, currently `instant`, `medium`, `high`. Add or remove entries and the track, ticks and needle mapping follow, since everything is computed against `LEVELS.length - 1`. - `MODEL_NAME` in spec.ts: the prefix in the label, currently `'5.6'`. - `SELECTOR` in spec.ts: `trackInset` 31, `trackHeight` 72, `inset` 12, `knobRing` 4, `tickSize` 12, `closedHeight` 34, `closedInset` 2, `closedRing` 2, `handoff` 0.01, `labelSize` 22, `labelGap` 20. - `COMPOSER` in spec.ts: collapsed `{ inset: 38, height: 48, radius: 24, gap: 4 }`, expanded `{ inset: 12, height: 94, radius: 28, gap: 12 }`, `hit` 34, `sendSize` 32, `fontSize` 17. - `GAUGE` in spec.ts: `size` 25, `strokeWidth` 2.5, `arcStart` -125, `arcSweep` 250, `needle` [-52, 29, 115], `fill` [0.06, 0.6, 1]. - `SPRING` in spec.ts: `open` `{ mass: 1, duration: 450 }`, `close` `{ mass: 1, duration: 150 }`, `knob` `{ mass: 1, stiffness: 995, damping: 53.6 }`, `focus` `{ mass: 1, stiffness: 220, damping: 26 }`. - `BLUR` in spec.ts: `fadeIn` 300, `full` 392, `hold` 588, `fadeOut` 724, `maxIntensity` 25, `layers` 4. - `DARK_MODE` in theme.ts: a compile-time boolean that swaps the whole palette, including `accent` (`#0979FF`), `track`, `trackSolid`, `scrim`, `knob`, `tickOnTrack`, `tickOnFill` and `gaugeTrack`. - `DEMO` in components/use-demo-run.ts: set to `true` to have the screen play the interaction by itself for recording, `false` in shipping builds. ## When to use it - An AI or chat composer that needs an inline model, mode or reasoning-effort selector without covering the conversation with a modal. - Any settings control that has to appear over an open keyboard while the text field keeps its focus and its caret. - A quality or speed tradeoff picker (fast, balanced, thorough) attached to a send button. - A small icon button that should expand into a full control in place, rather than opening a separate sheet. - A three-stop or five-stop custom slider where the value must be draggable continuously but commit to discrete stops. - Onboarding or paywall screens that need a tactile plan or tier slider with snap behaviour. ## How to get it - Buy ChatGPT Slider Model Picker on its own at https://motionary.dev/animations/chatgpt-slider-model-picker, $10 USD (price as of 2026-09-01), 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 custom slider in React Native with snap stops?** ChatGPT Slider Model Picker from Motionary does it with a `Gesture.Pan` from react-native-gesture-handler whose callbacks are worklets writing a single Reanimated shared value: `onBegin` springs to the nearest stop, `onUpdate` writes the clamped continuous position, and `onFinalize` calls `withSpring(Math.round(level), SPRING.knob)` and reports the committed index with one `scheduleOnRN`. **How do I show a blur or a control over the keyboard in React Native?** ChatGPT Slider Model Picker renders both the slider and its blur inside react-native-keyboard-controller's `OverKeyboardView`, whose window is layered above the keyboard's; anywhere else in the view tree the keys stay sharp on top of the blur, and the Motionary drop ships that wiring plus the keyboard-height tracking that pins the track flush to the keyboard's top edge. **Does ChatGPT Slider Model Picker work with Expo Go?** Yes. ChatGPT Slider Model Picker runs in Expo Go on Expo SDK 56: react-native-keyboard-controller (the `OverKeyboardView` the slider draws inside), expo-glass-effect, @react-native-masked-view/masked-view, react-native-svg and expo-blur are all bundled in Expo Go as of SDK 56, so nothing in this Motionary drop forces a development build. You would still make a development build (`npx expo run:ios` or `npx expo run:android`) to ship to production, and you need one as soon as you add a native module Expo Go does not bundle or a config plugin. On iOS below 26, and on Android, expo-glass-effect falls back to a flat surface instead of Liquid Glass. **Does the progressive blur work on Android?** Not as a real backdrop blur. On Android the `OverKeyboardView` is a separate WindowManager panel with nothing behind it to snapshot, so ChatGPT Slider Model Picker detects that in `components/blur.tsx` (`CAN_BLUR`) and renders a single gradient scrim following the same band profile, plus an opaque track tint, so the interaction still reads correctly. **How do I make a gauge icon follow a drag continuously in React Native?** ChatGPT Slider Model Picker draws the gauge by hand in react-native-svg and animates the arc's `d` string and a tapered four-point needle path through `useAnimatedProps`, because SF Symbols' `gauge.*` variable-value variants quantise to fixed steps instead of tracking a fractional value. **How much does ChatGPT Slider Model Picker cost and what exactly is delivered?** It is $10 USD on Motionary (price as of 2026-09-01, live price at https://motionary.dev/animations/chatgpt-slider-model-picker), delivered as an instant download of the full TypeScript React Native source, and it is also covered by the $79 USD Motionary lifetime pass at https://motionary.dev/pricing. **Can I change the number of effort stops or their labels?** Yes. The stops live in `LEVELS` in `spec.ts` of ChatGPT Slider Model Picker, and the track geometry, tick dots, gauge fill and needle mappings are all computed against `LEVELS.length - 1`, so adding or renaming a stop propagates through the slider. ## Related drops on Motionary - Dot Wave Slider ($10): https://motionary.dev/animations/dot-wave-slider another Motionary slider with snap stops and haptics, built on a Skia shader instead of SVG. - ChatGPT-Style Attachments Menu ($10): https://motionary.dev/animations/chatgpt-style-attachments-menu the same ChatGPT composer, morphing a button into an over-keyboard menu with react-native-keyboard-controller. - Long-Press Menu ($9): https://motionary.dev/animations/long-press-menu another chat-input control that draws over the keyboard behind a blur. - ChatGPT Image-Gen Dot Field ($5): https://motionary.dev/animations/chatgpt-image-gen-dot-field a ChatGPT-styled loading state for the same AI chat screen. - OTP Code Input ($5): https://motionary.dev/animations/otp-code-input another keyboard-aware input built with react-native-keyboard-controller and Reanimated. ## 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/chatgpt-slider-model-picker/llms.txt Describes: https://motionary.dev/animations/chatgpt-slider-model-picker Format: llms.txt (https://llmstxt.org) Last updated: 2026-09-01