react-native-spotlight-tour: a guided tour overlay for React Native
A highly customizable tour feature with an awesome spotlight effect
At a glance
- What is it?
- This library puts a spotlight over the element you are describing and dims the rest of the screen, which is the standard way to walk a new user through an app one step at a time. What makes it worth a look is the positioning: it delegates that to Floating UI rather than doing it by hand, so a tooltip lands somewhere sensible on a small screen, and it re-exports the Floating UI middlewares so you can configure the behaviour per step.
- Who is it for?
- Adopt react-native-spotlight-tour if you are adding an onboarding tour to a React Native application and want the tooltip placement handled by Floating UI rather than by hand-tuned offsets, since the middleware surface it exposes is what stops a label from overlapping the control it points at.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the library is, and what it is built on
react-native-spotlight-tour is a simple and intuitive library for React Native, working on Android, iOS and the web. It uses Floating UI under the hood to handle element positioning, and it re-exports all the Floating UI middlewares so they can be configured in the tour.
That dependency is the design decision that shapes the whole library. Positioning a tooltip relative to a highlighted element, and keeping it inside the viewport, is fiddly work: you need to know the element's frame, you need to decide which side to put the label on, and you need to flip it when there is no room. Floating UI is a library that solves exactly that problem, and rather than write a smaller version of it, this library hands the job over.
The result is that a step's placement is a configuration value rather than a set of hand-tuned offsets. The middleware list is the vocabulary: offset pushes the tooltip away from the edge, shift slides it along the axis to stay in view, and flip changes the side when the preferred one does not fit. Those three are the default set, and they are the ones you would reach for.
The library also handles the animations at the native level, and the README shows four recordings of the effect, with the bounce, fade, slide and rect variants named in the file names. Native animation is the point of using a React Native component rather than a web overlay, since the transition runs on the platform's own animation system rather than through the JavaScript bridge.
The intended use is stated as two lines: guiding users on how to use your application, and showing an introduction to your users. Both are onboarding cases, and both are cases where the element being highlighted is a real control the user is about to press.
The primary language is TypeScript, the licence is MIT, and the homepage is stackbuilders.github.io/react-native-spotlight-tour. The recent releases are v4.0.0 from 2025-06-23, v3.0.1 from 2023-09-22 and v3.0.0 from the same day. The last push was on 2026-10-20 with the project not archived, and the default branch is named Chore/update-security-vulnerabilities, which is a branch name rather than the usual main.
The requirements are short and one of them is a peer dependency worth noting: React at 16.8.0 or newer, React Native at 0.50.0 or newer, and react-native-svg at 12.1.0 or newer. The SVG library is needed because a spotlight effect is a cut-out shape in a dimmed overlay, which is a drawing operation rather than a view operation.
Installing it
Installation is one command, with the two package managers given separately:
npm install react-native-spotlight-touror
yarn add react-native-spotlight-tourThat is the whole installation, and the absence of a linking step is worth a note. The library depends on react-native-svg, and in a React Native project that library normally needs to be linked to the native side. The requirements list names react-native-svg at 12.1.0 or newer as a requirement of this library, which means you install it yourself and manage its linking, rather than the library doing it for you.
This is the shape of a modern React Native package that stays in the JavaScript layer. There is no native module of its own to compile, so there is no podspec to run and no Android project to build, and the whole thing is JavaScript plus the SVG library it draws with.
That has an obvious benefit, which is that adding a tour to an application does not change your native build. On iOS that means no pod install step and no rebuild of the Xcode project, which for a library you might add late to a shipped app is often the difference between a five-minute change and a day of certificate and build problems.
The trade is that the effect is drawn with SVG rather than being a native view, so the spotlight cut-out and the dimming are composited by the platform's own SVG implementation. The README's claim that the library handles animations at the native level refers to the animation of the transition rather than to the spotlight being a native view.
The provider, the hook and the step array
The usage model has three parts, and the example shows all of them.
Everything is wrapped in a SpotlightTourProvider, which takes the steps array and global configuration. The provider also hands down access to the tour context through a hook, and the render-prop form gives you a start function:
import { Button, Text, View } from "react-native";
import {
AttachStep,
SpotlightTourProvider,
TourStep,
flip,
offset,
shift,
} from "react-native-spotlight-tour";
const mySteps: TourStep[] = [
// ...setup the steps
];
return (
<SpotlightTourProvider
steps={mySteps}
overlayColor={"gray"}
overlayOpacity={0.36}
// This configurations will apply to all steps
floatingProps={{
middleware:[offset(5), shift(), flip()],
placement: "bottom",
}}
>
{({ start }) => (
<>
<Button title="Start" onPress={start} />
<View>
<AttachStep index={0}>
<Text>Introduction</Text>
</AttachStep>
<Text>
This is an example using the spotlight-tour library.
Press the Start button to see it in action.
</Text>
</View>
<View>
<AttachStep index={1}>
<Text>Documentation</Text>
</AttachStep>
<DescriptionText>
Please, read the documentation before installing.
</DescriptionText>
</View>
</>
)};
</SpotlightTourProvider>
);Two design details in that example matter more than the rest.
First, the provider uses a render prop, so the child receives an object with the start function. That is what lets a Start button anywhere in the tree begin the tour, without the button having to reach into a context by hand or the application having to hold a ref.
Second, the elements to highlight are not listed in the steps array. Each step is attached to a piece of the tree with an AttachStep component carrying an index, and the steps array maps onto those indices. So the number of steps and the number of AttachStep wrappers have to agree, and the mapping is by position rather than by name.
That arrangement has a practical consequence. The tour highlights real elements in your component tree rather than coordinates, so it survives a layout change, and it is why the library can measure the element and position the tooltip with Floating UI. The cost is that the step definitions and the tree have to be kept in step with each other, and the attachment point must be a real view for the measurement to work.
The provider's own configuration is global for the tour: the overlay colour and opacity, and the floatingProps object that holds the middleware list and the placement. The README gives the defaults explicitly, which is helpful, because a tooltip that sits four pixels off the element rather than flush against it is a visible difference. The defaults are middlewares of flip, offset with four pixels, and shift, with a placement of bottom.
Per-step configuration, and the two hooks into the tour
Each step can override the global Floating UI configuration, and can do things before it renders and while it renders.
The step array example shows the shape:
import { Button, Text, View } from "react-native";
import {
Align,
TourStep,
useSpotlightTour
} from "react-native-spotlight-tour";
const mySteps: TourStep[] = [{
// This configurations will apply just for this step
floatingProps:{
middleware: [offset(0), shift(), flip()],
placement: "right",
},
render: ({ next }) => (
<View>
<Text>This is the first step of tour!</Text>
<Button title="Next" onPress={next} />
</View>
)
}, {
before: () => {
return DataService.fetchData()
.then(setData);
},
render: () => {
// You can also use the hook inside the step component!
const { previous, stop } = useSpotlightTour();
return (
<View>
<Text>This is the first step of tour!</Text>
<Button title="Previous" onPress={previous} />
<Button title="Stop" onPress={stop} />
</View>
);
}
}];Three fields carry most of the weight.
The floatingProps on a step is a per-step Floating UI configuration, and if a step does not specify one it inherits the provider's. So the global settings are the baseline and a step overrides them, rather than each step having to repeat the whole set. The example puts a tooltip to the right of the first element with a different middleware list, which is the sort of adjustment you need when one step sits in a corner where the default placement would not fit.
The before field is a function that runs before the step renders and may return a promise. The example fetches data and sets it, which is the pattern for a step that points at something not yet on screen. Because it can be asynchronous, a step can wait for its content to load rather than highlighting an empty view.
The render function is where the step's own interface is drawn, and it receives the tour context. The example destructures previous and stop, which is how a step offers a Back button and a way to end the tour. And the comment points out that you can also call the useSpotlightTour hook inside the step component, which is the way to reach the context from a child component rather than from the render function itself.
So there are two access routes to the same context, the render-prop argument and the hook, and the library documents both because they suit different component structures. A step whose body is a single component can use the hook, and one that wants the controls inline can destructure them from the render argument.
The render function receives the tour methods, and the whole set is described as giving information and fine control over the tour.
The v2 to v3 upgrade, which is mostly about positioning
The breaking changes section is the most useful part of the README for anyone arriving at the current version with an older one in a project, and the change is concentrated in one area.
The first change is the package name. It was @stackbuilders/react-native-spotlight-tour and is now just react-native-spotlight-tour, with the note that the library is still developed and maintained by the Stack Builders team, so the rename is not a handover. The upgrade steps are to remove the former package from your dependencies, install using the command in the install section, and rename any import from the previous name.
The second change is the tooltip positioning, and it is the substantial one. The props related to tooltip position were removed from the SpotlightTourProvider and from the TourStep object. The Align and Position enums were both removed, and the alignTo and position props were both removed. Positioning is now delegated to Floating UI, so you use the floatingProps prop to configure its global behaviour or granularly on each step. The middleware functions are re-exported from @floating-ui/react-native to this package, and you may not need to change floatingProps at all since the default behaviour is very similar to v2.
That last sentence is the reassuring part, because removing an enum and two props from a component's API sounds like a rewrite when it is mostly a change of mechanism. The positioning decision moves from the tour's own props into Floating UI's own vocabulary, which means the tour inherits the whole middleware ecosystem rather than a small subset of it.
The pattern to notice is that the migration is a rename of the configuration surface rather than a change of behaviour. If your v2 code set alignTo and position on each step, that configuration now becomes the floatingProps placement and middleware on that step, and the defaults mean you may be able to delete it.
The version history shows two more releases after the v3 work, v3.0.1 and then v4.0.0 in June 2025, so the current line is v4 and the v2 to v3 notes still describe the migration most people will need.
The repository, and the tooling behind it
The top-level listing shows a Yarn workspace with a Turbo build, which is the modern React Native library layout.
There is a package/ directory, which is the library itself, and an example/ directory, which is a full React Native application. Alongside them are docs/, a .yarn/ directory with a .yarnrc.yml, a turbo.json, an eslint.config.mjs, a tsconfig.json, a _config.yml for the documentation site, an .all-contributorsrc and a .nvmrc.
The package manifest confirms the shape and the scripts are worth reading:
"android": "yarn workspace example android",
"build": "turbo build",
"check": "NODE_OPTIONS=\"--no-experimental-detect-module\" turbo check && yarn lint",
"compile": "turbo compile",
"docs": "yarn workspace react-native-spotlight-tour docs",
"ios": "yarn workspace example ios",
"lint": "eslint .",
"release": "turbo release --concurrency=1",
"start": "turbo start",
"start:reset": "turbo start:reset",
"test": "NODE_OPTIONS=\"--no-experimental-detect-module\" turbo test",
"test:ci": "turbo test"So the android and ios scripts delegate to the example workspace, which means running the example application is the intended way to see the library working. The build, compile, start, check and release scripts all run through Turbo, so the workspace tasks are cached and the release runs with a concurrency of one, which is the setting that stops two packages publishing at once.
Two scripts are worth singling out. The check script sets NODE_OPTIONS to --no-experimental-detect-module before running the Turbo check and then the lint, and the test script does the same before running Turbo test. That environment flag exists because newer Node versions detect module syntax automatically and change how a project resolves its module type, and the project wants to keep the older behaviour so the build is deterministic across Node versions.
The engines field requires Node 18 or newer, and the packageManager field pins Yarn at 4.9.1, which with the .yarn directory and the yarn.lock means the package manager version is fixed rather than whatever happens to be installed.
The example directory is a substantial application rather than a snippet. It has android/ and ios/ platform directories, its own metro.config.cjs and metro.config.web.cjs, a babel.config.js, an index.html and index.js for the web target, a Gemfile with a .ruby-version, a .watchmanconfig and a .bundle directory. So the library is tested against a real React Native app on all three platforms, which is the most convincing evidence available about whether the spotlight effect behaves the same on a phone as it does in a browser.
The contributor count is twenty, shown by the all-contributors badge, and the project carries a known vulnerabilities badge from Snyk, which is a signal that the dependency surface is being watched.
How to evaluate it, and what to check first
There are four things to consider.
First, whether the positioning behaviour is what you want. The library gives you Floating UI's defaults with an escape hatch into its middleware configuration. That means a tooltip will land somewhere sensible by default, and where it does not you adjust with offset, shift and flip rather than by hand-computing coordinates. If you have used a tour library that places tooltips with fixed offsets, the difference is that this one will not overlap the element you are pointing at, which is the failure people usually complain about.
Second, the state of the project. v4.0.0 is from June 2025 and the last push was on 2026-10-20, with the default branch named for a security update. The library is MIT licensed and the company behind it says it is still maintained. If you are starting fresh, the current version is the one to use; if you have v2 in a project, the migration notes are specific enough to work through.
Third, the native build cost. The library is JavaScript plus react-native-svg, so adding a tour does not change your native build. The requirement is that you install react-native-svg at 12.1.0 or newer yourself, which means you own its linking step, and that is worth checking against how your project handles autolinking.
Fourth, the step-to-tree mapping. The steps array and the AttachStep wrappers must line up by index, and the highlighted element has to be a real view for the measurement to work. For a tour that walks through a form, that means the steps have to be written knowing the layout, and adding a screen means renumbering.
What you get is a focused library that does one thing, with a positioning implementation that does not have to be reinvented, a per-step configuration surface that inherits rather than repeats, and a full example application covering Android, iOS and web. The costs are the index-based coupling between steps and the tree, and the fact that the highlight requires a measurable view.
Editorial conclusion
Adopt react-native-spotlight-tour if you are adding an onboarding tour to a React Native application and want the tooltip placement handled by Floating UI rather than by hand-tuned offsets, since the middleware surface it exposes is what stops a label from overlapping the control it points at. Do not adopt it if you need steps addressed by name rather than by index, because the TourStep array and the AttachStep wrappers are matched by position and every screen you add means renumbering. Before you commit, install react-native-svg at 12.1.0 or newer and check that its native linking fits how your project handles autolinking, since the library draws the spotlight with SVG and does not bring its own native module, and if you are upgrading from v2 remove the old scoped package, rename your imports, and expect to replace the alignTo and position props with the floatingProps placement and middleware configuration.
Frequently asked questions
What does react-native-spotlight-tour do?
It is a React Native library for Android, iOS and the web that shows a spotlight over one element at a time and dims the rest of the screen, for guiding users through an application or showing an introduction. It uses Floating UI to position the tooltip and re-exports the Floating UI middlewares so they can be configured in the tour.
How do I install react-native-spotlight-tour?
Run npm install react-native-spotlight-tour, or yarn add react-native-spotlight-tour. The requirements are React at 16.8.0 or newer, React Native at 0.50.0 or newer, and react-native-svg at 12.1.0 or newer, which you install yourself because the library draws its effect with SVG.
How do I attach a tour step to an element?
Wrap the element in an AttachStep component with an index, and give the provider an array of TourStep objects of the same length. The mapping is by position, so the number of steps and the number of AttachStep wrappers have to agree. The provider takes the steps array and also exposes a start function through its render prop.
What changed between v2 and v3 of react-native-spotlight-tour?
The package was renamed from @stackbuilders/react-native-spotlight-tour to react-native-spotlight-tour, so imports and the dependency entry change. Tooltip positioning was refactored: the Align and Position enums and the alignTo and position props were removed from the provider and the step object, and positioning is now delegated to Floating UI through the floatingProps prop, with the middleware functions re-exported from this package.
Can I configure the tooltip position for a single step?
Yes. The floatingProps on a TourStep holds that step's Floating UI configuration, including a middleware list and a placement, and if a step does not specify one it inherits the provider's configuration. The library's default is flip, offset with four pixels and shift, with a placement of bottom.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/stackbuilders-react-native-spotlight-tour)Was this useful?