Onboarding spotlight walkthrough — dimmed overlay with a rounded cutout, anchored tooltip card, Back/Next/Skip navigation and progress dots
$ npx lumioui add coach-marks
import { CoachMarks } from "@/components/ui/coach-marks/coach-marks";
Files installed into your repo
components/ui/coach-marks/coach-marks.tsx
Registry dependencies (installed automatically)
Native packages required
@lumioui/core@latest@lumioui/ui@latestreact-native-reanimated@^4.0.0react-native-safe-area-context@^4.0.0expo-haptics@*
Props11
| open | boolean | |
| steps | CoachMarkStep[] | |
| step? | number | Controlled step index. Omit (with defaultStep) for uncontrolled. |
| defaultStep? | number | Uncontrolled initial step. Default 0. |
| onStepChange? | (step: number) => void | |
| onFinish? | () => void | Called when the flow completes (Done on the last step). |
| onSkip? | () => void | Called when the user skips. Defaults to onFinish. |
| advanceOnBackdropPress? | boolean | Tap the dimmed area to advance. Default true. |
| showDots? | boolean | Progress dots row. Default true. |
| glass? | boolean | Frost the tooltip card (liquid-glass material over the dimmed world). |
| className? | string | |
Coach Marksdots.tsx
Live preview offline the relay is unreachable — check back shortly
coach-marks/variants/dots.tsx open Onboarding spotlight walkthrough — dimmed overlay with a rounded cutout, anchored tooltip card, Back/Next/Skip navigation and progress dots
import { CoachMarksDots } from "@/components/ui/coach-marks/variants/dots";
export function Example() {
return (
<CoachMarksDots />
);
}
import * as React from "react";
import { View } from "react-native";
import { CoachMarks, type CoachMarkStep } from "../coach-marks";
import { Ambient, Button, Glass, Icon, Text } from "@lumioui/ui";
/** CoachMarksDots — three-step walkthrough with progress dots on a wallet home. */
export function CoachMarksDots() {
const [open, setOpen] = React.useState(true);
const [step, setStep] = React.useState(0);
const balanceRef = React.useRef<View | null>(null);
const actionsRef = React.useRef<View | null>(null);
const activityRef = React.useRef<View | null>(null);
const steps: CoachMarkStep[] = [
{
key: "balance",
title: "Your balance, always live",
body: "Lumo Wallet syncs across devices — pull to refresh anytime.",
targetRef: balanceRef,
},
{
key: "actions",
title: "Send in one tap",
body: "Quick actions for transfers, top-ups and splitting a ramen bill.",
targetRef: actionsRef,
},
{
key: "activity",
title: "Every order tracked",
body: "Order #8421 from Sakura Ramen lands here the moment Diego picks it up.",
targetRef: activityRef,
},
];
return (
<View className="relative w-full overflow-hidden rounded-3xl">
<Ambient seed="coach-marks-dots" />
<View className="w-full gap-3 p-4">
{/* Live targets the walkthrough spotlights. */}
<Glass interactive ref={balanceRef} curvature="edge" className="rounded-2xl p-4">
<Text variant="muted" className="text-xs">Lumo Wallet balance</Text>
<Text variant="large">$4,280.50</Text>
</Glass>
<View ref={actionsRef} className="flex-row gap-2">
<Glass interactive curvature="edge" className="flex-1 flex-row items-center justify-center gap-1.5 rounded-xl py-2.5">
<Icon name="send" size="sm" color="foreground" />
<Text variant="small">Send</Text>
</Glass>
<Glass interactive curvature="edge" className="flex-1 flex-row items-center justify-center gap-1.5 rounded-xl py-2.5">
<Icon name="plus" size="sm" color="foreground" />
<Text variant="small">Top up</Text>
</Glass>
</View>
<Glass interactive ref={activityRef} curvature="edge" className="rounded-2xl p-4">
<Text variant="small">Order #8421 · Sakura Ramen</Text>
<Text variant="muted">Tonkotsu ×2 — out for delivery</Text>
</Glass>
{!open ? (
<Button variant="glass" size="sm" onPress={() => { setStep(0); setOpen(true); }}>
Replay tour
</Button>
) : null}
<CoachMarks
glass
open={open}
steps={steps}
step={step}
onStepChange={setStep}
onFinish={() => setOpen(false)}
onSkip={() => setOpen(false)}
/>
</View>
</View>
);
}