Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.revrag.ai/llms.txt

Use this file to discover all available pages before exploring further.

EmbedProvider advanced (FAB visibility)

Use this guide after you have a working EmbedProvider + NavigationContainer setup from the React Native integration guide. Here you tune where the FAB appears, when it shows, and how it is positioned using includeScreens, embedButtonDelayMs, and embedButtonVisibilityConfig.

Introduction

EmbedProvider wraps your app and:
  • Listens to React Navigation state and shows or hides EmbedButton by screen.
  • Supports visibility groups: per-group delay, continuity, and inset.
  • Enriches analytics with screen context (current screen, path, depth).
What this guide covers
  • includeScreens - allowlist route names where the FAB may appear.
  • embedButtonDelayMs - default delay before the FAB appears on an eligible screen.
  • embedButtonVisibilityConfig - groups, continuity, delay policies, and insets for production-grade UX.
Requirements
  • React Navigation (for example @react-navigation/native).
  • EmbedProvider must wrap NavigationContainer and use the same ref you pass to NavigationContainer.

Prerequisites

Before you use advanced visibility rules, confirm the following:
RequirementNotes
React Native0.70 or higher (same as main integration guide)
React NavigationRoot NavigationContainer with a shared navigationRef
Base embed setupuseInitialize, GestureHandlerRootView, and EmbedProvider wired as in the main guide
You will also need:
  • Route name values that match your navigators exactly (case-sensitive).
  • A clear idea of which flows should show the FAB (tabs, stacks, auth exclusions, etc.).
If navigationRef is missing or not the same ref as on NavigationContainer, the provider cannot detect screen changes and FAB visibility will not match your rules.

Before you continue: base integration

Complete installation, native LiveKit setup, and the Basic setup steps in the React Native guide first. Advanced props build on that tree.

React Native integration (install, native setup, basic EmbedProvider)

Start here if you have not finished useInitialize, peer dependencies, GestureHandlerRootView, and a minimal EmbedProvider around NavigationContainer.

Basic setup (step-by-step)

Follow these in order. You can stop after Step 2 for a simple allowlist-only integration.

Step 1 - Minimal provider and ref

import { useRef } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { EmbedProvider } from '@revrag-ai/embed-react-native';
import { RootNavigator } from './navigation/RootNavigator';

export default function App() {
  const navigationRef = useRef(null);

  return (
    <EmbedProvider navigationRef={navigationRef} appVersion="1.0.0">
      <NavigationContainer ref={navigationRef}>
        <RootNavigator />
      </NavigationContainer>
    </EmbedProvider>
  );
}
  • appVersion (required): Your app version string (for example from package.json). Used in analytics.
  • navigationRef: Must be the ref attached to NavigationContainer. Without it, the provider cannot reliably drive screen-based visibility.

Step 2 - Restrict screens with includeScreens (optional)

<EmbedProvider
  navigationRef={navigationRef}
  appVersion="1.0.0"
  includeScreens={['ScreenA', 'ScreenB', 'ScreenC']}
>
  <NavigationContainer ref={navigationRef}>
    <RootNavigator />
  </NavigationContainer>
</EmbedProvider>
  • includeScreens: Route names where the button may appear. If omitted or empty, eligibility depends on backend and groups (see visibility groups). Names must match Stack.Screen name="..." exactly.

Step 3 - Global delay (optional)

Delay the first appearance of the FAB after entering an included screen:
<EmbedProvider
  navigationRef={navigationRef}
  appVersion="1.0.0"
  includeScreens={['ScreenA', 'ScreenB']}
  embedButtonDelayMs={1500}
>
  <NavigationContainer ref={navigationRef}>
    <RootNavigator />
  </NavigationContainer>
</EmbedProvider>
  • embedButtonDelayMs: Delay in milliseconds before showing the FAB on an included screen. Default 0. Groups can override per group.

Step 4 - Visibility groups (optional, advanced)

For different delays, continuity, or insets per flow, configure embedButtonVisibilityConfig (see Visibility groups and Configuration options).

How screen-based visibility works

  1. You pass a ref from your root to both EmbedProvider and NavigationContainer.
  2. The provider subscribes to navigation state and reads the current route (deepest active screen).
  3. If the current screen is in includeScreens or in any visibility group when using groups, the FAB is shown; otherwise it is hidden.
Important
  • EmbedProvider must wrap NavigationContainer so the listener uses the same ref.
  • Route names are case-sensitive and must match exactly (for example Screen1, not screen1).

Global delay

See Step 3 above. embedButtonDelayMs is the global default; embedButtonVisibilityConfig.defaultDelayMs and per-group delayMs override or refine behavior when you use groups.

Visibility groups

For finer control (different delays, staying visible across screens, per-group position), use visibility groups.

Concepts

ConceptMeaning
GroupA set of screens that share delay, continuity, and inset rules.
ContinuityWhether the FAB stays visible when moving between screens in the same group.
Delay policyWhen the delay runs: every screen, once per group entry, or once per app session.
InsetDistance from screen edges (right, bottom, and so on) for the FAB.

Types (import from the package)

import type {
  EmbedButtonVisibilityConfig,
  EmbedButtonGroupConfig,
  EmbedButtonContinuity,
  EmbedButtonDelayPolicy,
  EmbedButtonInset,
} from '@revrag-ai/embed-react-native';

EmbedButtonVisibilityConfig

interface EmbedButtonVisibilityConfig {
  defaultDelayMs?: number;   // Optional fallback when a group does not set delayMs
  defaultInset?: EmbedButtonInset;
  groups?: EmbedButtonGroupConfig[];
}
When do you need defaultDelayMs? You do not need it if every group sets its own delayMs. It is a fallback when:
  • A group omits delayMs - that group falls back to defaultDelayMs, then top-level embedButtonDelayMs.
  • A screen is included (for example via includeScreens) but does not belong to any group - the provider uses defaultDelayMs (or embedButtonDelayMs) for that screen.
You can omit defaultDelayMs and defaultInset when every group defines its own delayMs and inset.

EmbedButtonGroupConfig

interface EmbedButtonGroupConfig {
  id: string;                    // Unique ID for this group
  screens: string[];             // Route names in this group
  continuity: EmbedButtonContinuity;
  inset?: EmbedButtonInset;
  delayMs?: number;
  delayPolicy?: EmbedButtonDelayPolicy;
}

EmbedButtonContinuity

  • continuous - Moving between screens in the same group keeps the FAB visible; delay is not re-applied in the way perScreen would.
  • perScreen - Each screen in the group is treated independently (delay can re-run per screen if the policy allows).

EmbedButtonDelayPolicy

  • perScreen - Delay runs on every included screen in the group when you land on it.
  • oncePerGroupEntry - Delay runs when entering the group (first screen of that visit). Moving within the group does not re-trigger the delay (pairs well with continuous).
  • oncePerAppSession - Delay runs once per app session for that group; later visits to the group show the FAB immediately per policy.

Including screens via groups

Screens listed in any group screens array count as included even if you omit them from includeScreens. You can:
  • Use only groups (for example omit the allowlist and define all included screens inside groups), or
  • Use both - the final included set is the union of includeScreens and all group screens.

Insets (button position)

EmbedButtonInset controls distance from screen edges:
type EmbedButtonInset = {
  top?: number | string;
  right?: number | string;
  bottom?: number | string;
  left?: number | string;
};
  • Values are usually numbers (for example 16, 54).
  • Set per group in EmbedButtonGroupConfig.inset, or a default in EmbedButtonVisibilityConfig.defaultInset.
  • If unset, the SDK uses internal defaults (for example right: 16, bottom: 20).
const flowGroup: EmbedButtonGroupConfig = {
  id: 'mainFlow',
  screens: ['Screen1', 'Screen2', 'Screen3'],
  continuity: 'continuous',
  inset: { right: 16, bottom: 54 },
  delayMs: 1500,
  delayPolicy: 'oncePerGroupEntry',
};

Configuration options

EmbedProvider props

PropTypeRequiredDescription
childrenReactNodeYesYour app, usually NavigationContainer and below.
navigationRefrefRecommendedSame ref as NavigationContainer so route changes are observed.
appVersionstringYesApp version for analytics.
includeScreensstring[]NoRoute names where the FAB may appear; union with group screens if both are set.
embedButtonDelayMsnumberNoDefault delay (ms) before showing the FAB when no group overrides apply.
embedButtonVisibilityConfigEmbedButtonVisibilityConfigNoGroups, continuity, per-group delays, insets.

EmbedButtonVisibilityConfig

FieldDescription
defaultDelayMsUsed when a matched group does not specify delayMs.
defaultInsetDefault inset when a group does not specify inset.
groupsArray of EmbedButtonGroupConfig.

EmbedButtonGroupConfig

FieldDescription
idUnique string for the group.
screensScreen names in this group.
continuitycontinuous or perScreen.
delayMsDelay in ms for this group.
delayPolicyperScreen, oncePerGroupEntry, or oncePerAppSession.
insetOffsets from edges { top, right, bottom, left }.

Usage examples

Example 1: Multi-screen flow and confirmation screen

  • Main flow: Screen1 to Screen3. FAB after 1.5s when entering the flow, stays visible within the flow. Inset right: 16, bottom: 54.
  • Screen4: Single screen. Delay 1.5s once per app session. Inset right: 24, bottom: 32.
  • Other screens: No FAB.
import {
  EmbedProvider,
  type EmbedButtonContinuity,
  type EmbedButtonDelayPolicy,
  type EmbedButtonGroupConfig,
  type EmbedButtonVisibilityConfig,
} from '@revrag-ai/embed-react-native';
import { NavigationContainer } from '@react-navigation/native';
import { useRef } from 'react';

const flowGroup: EmbedButtonGroupConfig = {
  id: 'mainFlow',
  screens: ['Screen1', 'Screen2', 'Screen3'],
  continuity: 'continuous' as EmbedButtonContinuity,
  inset: { right: 16, bottom: 54 },
  delayMs: 1500,
  delayPolicy: 'oncePerGroupEntry' as EmbedButtonDelayPolicy,
};

const confirmationGroup: EmbedButtonGroupConfig = {
  id: 'confirmationScreen',
  screens: ['Screen4'],
  continuity: 'perScreen' as EmbedButtonContinuity,
  inset: { right: 24, bottom: 32 },
  delayMs: 1500,
  delayPolicy: 'oncePerAppSession' as EmbedButtonDelayPolicy,
};

const embedButtonVisibilityConfig: EmbedButtonVisibilityConfig = {
  defaultDelayMs: 1200,
  defaultInset: { right: 16, bottom: 20 },
  groups: [flowGroup, confirmationGroup],
};

export default function App() {
  const navigationRef = useRef(null);

  return (
    <EmbedProvider
      navigationRef={navigationRef}
      includeScreens={['Screen1', 'Screen2', 'Screen3', 'Screen4']}
      appVersion="1.0.0"
      embedButtonDelayMs={1200}
      embedButtonVisibilityConfig={embedButtonVisibilityConfig}
    >
      <NavigationContainer ref={navigationRef}>
        <RootNavigator />
      </NavigationContainer>
    </EmbedProvider>
  );
}

Example 2: Two screens with different delays

  • ScreenA: Delay 1.5s every visit, inset right: 16, bottom: 24.
  • ScreenB: Delay 3s every visit, same inset.
const screenAGroup: EmbedButtonGroupConfig = {
  id: 'groupA',
  screens: ['ScreenA'],
  continuity: 'perScreen',
  inset: { right: 16, bottom: 24 },
  delayMs: 1500,
  delayPolicy: 'perScreen',
};

const screenBGroup: EmbedButtonGroupConfig = {
  id: 'groupB',
  screens: ['ScreenB'],
  continuity: 'perScreen',
  inset: { right: 16, bottom: 24 },
  delayMs: 3000,
  delayPolicy: 'perScreen',
};

const embedButtonVisibilityConfig: EmbedButtonVisibilityConfig = {
  defaultDelayMs: 1200,
  defaultInset: { right: 16, bottom: 20 },
  groups: [screenAGroup, screenBGroup],
};

<EmbedProvider
  navigationRef={navigationRef}
  includeScreens={['ScreenA', 'ScreenB']}
  appVersion="1.0.0"
  embedButtonVisibilityConfig={embedButtonVisibilityConfig}
>
  <NavigationContainer ref={navigationRef}>
    <RootNavigator />
  </NavigationContainer>
</EmbedProvider>

Example 3: Screens included only via groups

Omit includeScreens; only group membership decides visibility:
<EmbedProvider
  navigationRef={navigationRef}
  appVersion="1.0.0"
  embedButtonVisibilityConfig={embedButtonVisibilityConfig}
>
  <NavigationContainer ref={navigationRef}>
    <RootNavigator />
  </NavigationContainer>
</EmbedProvider>
Screens that appear in at least one group screens array get the FAB; all others do not.

Practical scenarios

Multi-step form flow (single delay)

Goal: Show delay once, then keep the FAB visible across steps.
const flowGroup: EmbedButtonGroupConfig = {
  id: 'formFlow',
  screens: ['Step1', 'Step2', 'Step3', 'Step4', 'Step5'],
  continuity: 'continuous' as EmbedButtonContinuity,
  delayMs: 1500,
  delayPolicy: 'oncePerGroupEntry' as EmbedButtonDelayPolicy,
};

Same flow with extra standalone screens

Goal: Delay once for the flow, different behavior for other screens.
const flowGroup: EmbedButtonGroupConfig = {
  id: 'formFlow',
  screens: ['Step1', 'Step2', 'Step3', 'Step4', 'Step5'],
  continuity: 'continuous' as EmbedButtonContinuity,
  delayMs: 1500,
  delayPolicy: 'oncePerGroupEntry' as EmbedButtonDelayPolicy,
};

const otherGroup: EmbedButtonGroupConfig = {
  id: 'otherScreens',
  screens: ['ScreenX', 'ScreenY'],
  continuity: 'perScreen' as EmbedButtonContinuity,
  delayMs: 1200,
  delayPolicy: 'perScreen' as EmbedButtonDelayPolicy,
};

Avoid overlapping bottom UI

Goal: Push the FAB above a bottom tab bar.
const flowGroup: EmbedButtonGroupConfig = {
  id: 'formFlow',
  screens: ['Step1', 'Step2', 'Step3'],
  continuity: 'continuous' as EmbedButtonContinuity,
  inset: { right: 16, bottom: 64 },
  delayMs: 1200,
  delayPolicy: 'oncePerGroupEntry' as EmbedButtonDelayPolicy,
};

Troubleshooting

IssueWhat to check
FAB never appears1) navigationRef matches NavigationContainer. 2) EmbedProvider wraps NavigationContainer. 3) Current route is in includeScreens or a group screens list.
FAB on wrong screensRoute name values must match exactly (case-sensitive) your Stack.Screen (or equivalent) name.
Screen not interactive when FAB is visibleOverlay uses pointerEvents="box-none" so touches pass through except on the FAB. Update the SDK if behavior differs.
Wrong positionSet inset per group or defaultInset. Insets apply inside the FAB container on the full-screen overlay.
Delay feels wrongCheck delayPolicy and continuity: oncePerGroupEntry + continuous delays once on group entry; perScreen can re-apply on each screen.
Types not foundImport from @revrag-ai/embed-react-native: EmbedButtonVisibilityConfig, EmbedButtonGroupConfig, EmbedButtonContinuity, EmbedButtonDelayPolicy, EmbedButtonInset.
  1. Log the active route name and compare to includeScreens / group screens.
  2. Confirm EmbedProvider is outside NavigationContainer and ref is the same object reference.
  3. Temporarily set a broad includeScreens list to verify routing, then tighten.

Best practices

  • Match route names in config to navigator name props - typos and casing break visibility.
  • Start with includeScreens, then add groups when you need different delays or insets per flow.
  • Prefer oncePerGroupEntry + continuous for multi-step flows so users do not see the FAB pop in on every step.
  • Tune bottom inset when you have tab bars or bottom sheets so the FAB does not overlap primary UI.
  • Keep appVersion accurate for analytics when debugging screen context.
  • Re-read delay policies when QA reports “delay only happened once” - often oncePerAppSession or oncePerGroupEntry is working as designed.

Support

Main integration: React Native integration (install, native setup, useInitialize, USER_DATA, events).

Back to React Native integration

Installation, native LiveKit setup, GestureHandlerRootView, useInitialize, EmbedProvider basics, Embed.Event, and troubleshooting.