react-tourlight

Troubleshooting & FAQ

Common issues, browser compatibility, and frequently asked questions.

Common issues

Spotlight doesn't appear

  1. Missing CSS import — Make sure you import the stylesheet:

    import 'react-tourlight/styles.css'
  2. Tour not started<SpotlightTour> only registers steps. You need to call start():

    const { start } = useSpotlight()
    start('your-tour-id')
  3. Target element not found — Verify the CSS selector or ref points to a mounted element. Open DevTools and run document.querySelector('#your-selector') to confirm.

  4. Missing Provider — Ensure <SpotlightProvider> wraps both your <SpotlightTour> and the component calling useSpotlight().

Tooltip is mispositioned

  1. Install Floating UI@floating-ui/react-dom is a required peer dependency; react-tourlight imports it directly and has no positioning fallback without it. If it's missing (or your package manager didn't install peer deps automatically), install it explicitly:

    npm install @floating-ui/react-dom
  2. Target inside a scroll container — Floating UI handles this automatically via autoUpdate. If positioning still looks wrong, ensure the target element is actually visible in the viewport.

  3. CSS transforms on ancestors — CSS transform on a parent element creates a new containing block, which can offset fixed positioning. This is a browser behavior, not a bug. Floating UI handles this correctly.

Tour doesn't advance

  1. Async elements — If the next step's target isn't in the DOM yet, react-tourlight waits for it using MutationObserver. Ensure the element eventually mounts. Check the when callback if you're using conditional steps.

  2. Focus trap interference — If another focus trap (e.g., a modal) is active, it may conflict with the spotlight's focus trap. Dismiss the modal before starting the tour.

SSR / hydration issues

react-tourlight is client-only. The overlay and tooltip render via portals and depend on document. In Next.js or other SSR frameworks:

// Dynamically import if needed
import dynamic from 'next/dynamic'

const SpotlightProvider = dynamic(
  () => import('react-tourlight').then(m => m.SpotlightProvider),
  { ssr: false }
)

Or simply ensure start() is only called after hydration (e.g., in a useEffect), which is the normal pattern.

Browser compatibility

BrowserMinimum versionNotes
Chrome88+Full support
Firefox97+Full support
Safari15.4+Full support
Edge88+Full support (Chromium-based)
iOS Safari15.4+Full support
Chrome Android88+Full support

react-tourlight uses:

  • CSS clip-path: path() (widely supported)
  • MutationObserver (supported everywhere)
  • inert attribute (Chrome 102+, Firefox 112+, Safari 15.5+)

For older browsers without inert support, the accessibility features degrade gracefully — keyboard navigation and ARIA attributes still work, but background content won't be fully inert.

FAQ

Does it work with React Native?

No. react-tourlight is for React DOM (web) only. It relies on DOM APIs like getBoundingClientRect, CSS clip-path, and portal rendering.

Can I use it without Floating UI?

No. @floating-ui/react-dom is a required peer dependency — the tooltip is positioned entirely through Floating UI's useFloating hook (flip, shift, and overflow handling included), and there is no built-in fallback positioning algorithm. Installing it alongside react-tourlight is a required step, not an optional enhancement.

Does it support multiple simultaneous tours?

Only one tour can be active at a time. You can register multiple tours with different IDs and start them independently, but starting a new tour will stop the current one.

Can I persist tour completion state?

react-tourlight doesn't handle persistence — that's your app's concern. Use the onComplete callback to save state:

<SpotlightTour
  id="onboarding"
  steps={steps}
  onComplete={() => localStorage.setItem('onboarding-done', 'true')}
/>

Does it work with CSS-in-JS libraries?

Yes. The default styles are in a regular CSS file (react-tourlight/styles.css). You can override styles via CSS custom properties, the theme prop, or the renderTooltip render prop for full control.

What's the bundle size?

The core library is ~5KB gzipped with no bundled runtime dependencies of its own — @floating-ui/react-dom is required, but as a peer dependency, so it's installed once and shared instead of duplicated. Floating UI itself adds roughly ~4KB gzipped.