spotlight_tutorial 2.0.4 copy "spotlight_tutorial: ^2.0.4" to clipboard
spotlight_tutorial: ^2.0.4 copied to clipboard

A lightweight Flutter package for interactive feature tutorials with spotlight overlays, coach marks, and sequential guided steps.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:spotlight_tutorial/spotlight_tutorial.dart';

void main() {
  runApp(const TutorialDemoApp());
}

class TutorialDemoApp extends StatelessWidget {
  const TutorialDemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Spotlight Tutorial Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
        extensions: const [
          SpotlightTutorialTheme(
            tooltipBackgroundColor: Color(0xFFFFFFFF),
            scrimColor: Color(0xCC121212),
          ),
        ],
      ),
      home: const TutorialDemoPage(),
    );
  }
}

/// GlobalKeys for each UI element highlighted by the tutorial.
class DemoTargets {
  final searchKey = GlobalKey();
  final walletCardKey = GlobalKey();
  final settingsKey = GlobalKey();
  final fabKey = GlobalKey();
}

class TutorialDemoPage extends StatefulWidget {
  const TutorialDemoPage({super.key});

  @override
  State<TutorialDemoPage> createState() => _TutorialDemoPageState();
}

class _TutorialDemoPageState extends State<TutorialDemoPage> {
  final _targets = DemoTargets();
  int _guideSession = 0;
  bool _guideDismissed = false;
  int _selectedTab = 0;
  double _balance = 1240.50;

  void _restartTutorial() {
    setState(() {
      _guideDismissed = false;
      _guideSession++;
    });
  }

  List<TutorialStep> _buildSteps(BuildContext context, DemoTargets? targets) {
    final t = targets ?? _targets;
    return [
      TutorialStep(
        targetKey: t.searchKey,
        title: 'Quick search',
        body: [
          'Find accounts, transactions, or help articles from here.',
        ],
        arrowEdge: TutorialArrowEdge.bottom,
        arrowAlign: 0.15,
      ),
      TutorialStep(
        targetKey: t.walletCardKey,
        title: 'Wallet overview',
        body: [
          'Your balance and recent activity appear on this card.',
          'Swipe actions will be available in a future update.',
        ],
        arrowEdge: TutorialArrowEdge.top,
      ),
      TutorialStep(
        targetKey: t.settingsKey,
        title: 'Settings',
        body: ['Open settings and notification controls.'],
        arrowEdge: TutorialArrowEdge.bottom,
        arrowAlign: 0.92,
      ),
      TutorialStep(
        targetKey: t.fabKey,
        title: 'New transfer',
        body: ['Tap here to send money or add funds.'],
        arrowEdge: TutorialArrowEdge.bottom,
        arrowAlign: 0.85,
      ),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return TutorialScope<DemoTargets>(
      key: ValueKey(_guideSession),
      shouldStart: () => !_guideDismissed,
      onDismiss: () => setState(() => _guideDismissed = true),
      targets: _targets,
      stepsBuilder: _buildSteps,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Tutorial demo'),
          actions: [
            IconButton(
              key: _targets.settingsKey,
              icon: const Icon(Icons.settings_outlined),
              onPressed: () {},
            ),
            IconButton(
              icon: const Icon(Icons.help_outline),
              onPressed: _restartTutorial,
              tooltip: 'Show tutorial again',
            ),
          ],
        ),
        body: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            FilledButton.tonalIcon(
              onPressed: _restartTutorial,
              icon: const Icon(Icons.play_circle_outline),
              label: const Text('Show tutorial'),
            ),
            const SizedBox(height: 16),
            TextField(
              key: _targets.searchKey,
              decoration: InputDecoration(
                hintText: 'Search…',
                prefixIcon: const Icon(Icons.search),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12),
                ),
              ),
            ),
            const SizedBox(height: 20),
            Card(
              key: _targets.walletCardKey,
              elevation: 2,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(16),
              ),
              child: Padding(
                padding: const EdgeInsets.all(20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Available balance',
                      style: Theme.of(context).textTheme.labelLarge,
                    ),
                    const SizedBox(height: 8),
                    Text(
                      '\$${_balance.toStringAsFixed(2)}',
                      style: Theme.of(context).textTheme.headlineMedium
                          ?.copyWith(fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 16),
                    Row(
                      children: [
                        Expanded(
                          child: OutlinedButton.icon(
                            onPressed: () {},
                            icon: const Icon(Icons.arrow_upward),
                            label: const Text('Send'),
                          ),
                        ),
                        const SizedBox(width: 12),
                        Expanded(
                          child: OutlinedButton.icon(
                            onPressed: () {
                              setState(() => _balance += 10);
                            },
                            icon: const Icon(Icons.add),
                            label: const Text('Add'),
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            const ListTile(
              leading: Icon(Icons.receipt_long),
              title: Text('Recent transactions'),
              subtitle: Text('3 pending · 12 completed'),
              trailing: Icon(Icons.chevron_right),
            ),
            const ListTile(
              leading: Icon(Icons.insights_outlined),
              title: Text('Spending insights'),
              subtitle: Text('Updated today'),
              trailing: Icon(Icons.chevron_right),
            ),
          ],
        ),
        bottomNavigationBar: NavigationBar(
          selectedIndex: _selectedTab,
          onDestinationSelected: (i) => setState(() => _selectedTab = i),
          destinations: const [
            NavigationDestination(
              icon: Icon(Icons.home_outlined),
              selectedIcon: Icon(Icons.home),
              label: 'Home',
            ),
            NavigationDestination(
              icon: Icon(Icons.pie_chart_outline),
              selectedIcon: Icon(Icons.pie_chart),
              label: 'Stats',
            ),
            NavigationDestination(
              icon: Icon(Icons.person_outline),
              selectedIcon: Icon(Icons.person),
              label: 'Profile',
            ),
          ],
        ),
        floatingActionButton: FloatingActionButton.extended(
          key: _targets.fabKey,
          onPressed: () {},
          icon: const Icon(Icons.swap_horiz),
          label: const Text('Transfer'),
        ),
      ),
    );
  }
}
3
likes
160
points
23
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A lightweight Flutter package for interactive feature tutorials with spotlight overlays, coach marks, and sequential guided steps.

Repository (GitHub)
View/report issues

Topics

#tutorial #onboarding #coach-mark #spotlight #flutter

License

MIT (license)

Dependencies

flutter

More

Packages that depend on spotlight_tutorial