app_onboarding_guide 0.0.1 copy "app_onboarding_guide: ^0.0.1" to clipboard
app_onboarding_guide: ^0.0.1 copied to clipboard

A guided tour and onboarding helper that helps you to present your app and its features in a beautiful, simple and customizable way.

example/lib/main.dart

// ignore_for_file: avoid_print, deprecated_member_use

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

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Onboarding Guide Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6366F1), // Indigo
          primary: const Color(0xFF4F46E5), // Premium Indigo
          secondary: const Color(0xFFF59E0B), // Warm Amber
          surface: const Color(0xFFF8FAFC), // Slate 50
        ),
      ),
      home: const MyHomePage(),
    );
  }
}

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

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  late AppOnboardingGuide appOnboardingGuide;

  // Onboarding target keys
  final GlobalKey keyProfileHeader = GlobalKey();
  final GlobalKey keyBalanceOverview = GlobalKey();
  final GlobalKey keyQuickActions = GlobalKey();
  final GlobalKey keySettingsCard = GlobalKey();
  final GlobalKey keyTransactionsSection = GlobalKey();
  final GlobalKey keyStartTourButton = GlobalKey();

  // Customizer state options
  bool _isArabic = false;
  bool _showIndicator = true;
  StepIndicatorStyle _stepIndicatorStyle = StepIndicatorStyle.dots;
  bool _autoScroll = true;
  double _opacityShadow = 0.8;
  bool _pulseEnable = true;
  bool _rippleEnable = false;
  bool _enableSwipeNavigation = true;
  bool _enableKeyboardNavigation = true;
  bool _glowEnable = true;
  double _glowRadius = 16.0;

  // Translation dictionary
  final Map<String, Map<String, String>> _translations = {
    'en': {
      'app_title': 'Onboarding Guide',
      'dashboard': 'Customizer Dashboard',
      'start_tour': 'Start Onboarding Tour',
      'profile_title': 'User Profile',
      'user_name': 'John Doe',
      'user_role': 'Senior Developer',
      'balance_title': 'Available Balance',
      'balance_amount': r'$12,540.50',
      'balance_subtitle': 'Active checking account',
      'quick_actions': 'Quick Actions',
      'action_add': 'Add Money',
      'action_send': 'Send',
      'action_request': 'Request',
      'recent_transactions': 'Recent Transactions',
      'tx_grocery': 'Grocery Store',
      'tx_electric': 'Electric Bill',
      'tx_salary': 'Salary Deposit',
      'tx_grocery_desc': 'Weekly shopping',
      'tx_electric_desc': 'Utility payment',
      'tx_salary_desc': 'Direct deposit credit',
      'settings_title': 'Customize Tour Settings',
      'lang_rtl': 'Arabic Language (RTL)',
      'show_indicator': 'Show Step Indicator',
      'indicator_style': 'Indicator Style',
      'dots': 'Dots',
      'bar': 'Progress Bar',
      'numbered': 'Numbered Text',
      'auto_scroll': 'Auto-Scroll to Offscreen',
      'opacity': 'Overlay Opacity',
      'pulse': 'Pulse Animation',
      'ripple': 'Sonar Ripple Waves',
      'swipe': 'Swipe Navigation',
      'keyboard': 'Keyboard Shortcuts',
      'spotlight_glow': 'Spotlight Glow',
      'glow_radius': 'Glow Radius',
      'tour_p1_title': 'User Profile Header',
      'tour_p1_desc': 'This card displays your profile avatar, name, and role in the organization.',
      'tour_p2_title': 'Account Balance',
      'tour_p2_desc': 'This widget tracks your current available funds and updates in real-time.',
      'tour_p3_title': 'Operations Shortcuts',
      'tour_p3_desc': 'Quickly transfer funds, request payments, or deposit cash with these buttons.',
      'tour_p4_title': 'Off-screen Transactions',
      'tour_p4_desc': 'Your recent expenditures log. Notice how the page automatically scrolled down to reveal this!',
      'tour_p5_title': 'Customizer Configuration',
      'tour_p5_desc': 'You can configure settings like overlay opacity, indicator styles, and pulse effects here.',
      'tour_skip': 'SKIP',
      'tour_back_to_start': 'Go to start',
      'tour_prev': 'Prev',
      'tour_next': 'Next',
      'tour_finish': 'Finish',
    },
    'ar': {
      'app_title': 'دليل البدء والتوجيه',
      'dashboard': 'لوحة التحكم بالمخصص',
      'start_tour': 'بدء الجولة التعريفية',
      'profile_title': 'ملف تعريف المستخدم',
      'user_name': 'جون دو',
      'user_role': 'مطور برمجيات أول',
      'balance_title': 'الرصيد المتاح',
      'balance_amount': '١٢،٥٤٠.٥٠ \$',
      'balance_subtitle': 'الحساب الجاري النشط',
      'quick_actions': 'إجراءات سريعة',
      'action_add': 'إضافة أموال',
      'action_send': 'إرسال ثانٍ',
      'action_request': 'طلب مال',
      'recent_transactions': 'المعاملات الأخيرة',
      'tx_grocery': 'متجر البقالة',
      'tx_electric': 'فاتورة الكهرباء',
      'tx_salary': 'إيداع الراتب',
      'tx_grocery_desc': 'التسوق الأسبوعي',
      'tx_electric_desc': 'سداد فاتورة الخدمات',
      'tx_salary_desc': 'رصيد إيداع مباشر',
      'settings_title': 'تخصيص إعدادات الجولة',
      'lang_rtl': 'اللغة العربية (يمين إلى يسار)',
      'show_indicator': 'عرض مؤشر الخطوات',
      'indicator_style': 'نمط مؤشر التقدم',
      'dots': 'نقاط',
      'bar': 'شريط تقدم',
      'numbered': 'أرقام الخطوات',
      'auto_scroll': 'التمرير التلقائي للعناصر البعيدة',
      'opacity': 'شفافية غطاء التظليل',
      'pulse': 'تأثير النبض البصري',
      'ripple': 'تموجات السونار الدائرية',
      'swipe': 'التنقل بالسحب الجانبي',
      'keyboard': 'مفاتيح لوحة المفاتيح',
      'spotlight_glow': 'وهج تسليط الضوء',
      'glow_radius': 'نصف قطر التوهج',
      'tour_p1_title': 'ترويسة ملف المستخدم',
      'tour_p1_desc': 'تعرض هذه البطاقة صورتك الرمزية واسمك ودورك في المؤسسة.',
      'tour_p2_title': 'رصيد الحساب المالي',
      'tour_p2_desc': 'يتتبع هذا العنصر أموالك الحالية المتاحة ويقوم بالتحديث في الوقت الفعلي.',
      'tour_p3_title': 'اختصارات العمليات السريعة',
      'tour_p3_desc': 'قم بنقل الأموال أو طلب المدفوعات أو إيداع النقد بسرعة باستخدام هذه الأزرار.',
      'tour_p4_title': 'المعاملات خارج الشاشة',
      'tour_p4_desc': 'سجل نفقاتك الأخيرة. لاحظ كيف قامت الصفحة بالتمرير لأسفل تلقائيًا للكشف عن هذا العنصر!',
      'tour_p5_title': 'تكوين مخصص الجولة',
      'tour_p5_desc': 'يمكنك تكوين إعدادات مثل شفافية الغطاء ونمط المؤشر وتأثيرات النبض من هنا.',
      'tour_skip': 'تخطي',
      'tour_back_to_start': 'الذهاب للبداية',
      'tour_prev': 'السابق',
      'tour_next': 'التالي',
      'tour_finish': 'إنهاء',
    }
  };

  String t(String key) {
    final lang = _isArabic ? 'ar' : 'en';
    return _translations[lang]?[key] ?? key;
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      showTutorial();
    });
  }

  void showTutorial() {
    createTutorial();
    appOnboardingGuide.show(context: context);
  }

  void createTutorial() {
    appOnboardingGuide = AppOnboardingGuide(
      targets: _createTargets(),
      colorShadow: const Color(0xFF0F172A), // Slate 900
      opacityShadow: _opacityShadow,
      textSkip: t('tour_skip'),
      alignSkip: AlignmentDirectional.bottomEnd,
      hideSkip: false,
      pulseEnable: _pulseEnable,
      rippleEnable: _rippleEnable,
      rippleColor: const Color(0xFF818CF8), // Indigo light ripple
      showStepIndicator: _showIndicator,
      stepIndicatorStyle: _stepIndicatorStyle,
      stepIndicatorAlignment: Alignment.bottomCenter,
      stepIndicatorActiveColor: const Color(0xFFF59E0B), // Amber active indicator
      stepIndicatorInactiveColor: Colors.white.withOpacity(0.3),
      enableSwipeNavigation: _enableSwipeNavigation,
      enableKeyboardNavigation: _enableKeyboardNavigation,
      autoScroll: _autoScroll,
      scrollDuration: const Duration(milliseconds: 400),
      scrollCurve: Curves.easeInOut,
      textDirection: _isArabic ? TextDirection.rtl : TextDirection.ltr,
      onFinish: () => print("Tour finished"),
      onSkip: () {
        print("Tour skipped");
        return true;
      },
    );
  }

  List<TargetFocus> _createTargets() {
    List<TargetFocus> targets = [];

    // 1. Profile Header Target
    targets.add(
      TargetFocus(
        identify: "profileHeaderTarget",
        keyTarget: keyProfileHeader,
        contents: [
          TargetContent(
            align: ContentAlign.bottom,
            builder: (context, controller) {
              return _buildTourCard(
                controller: controller,
                title: t('tour_p1_title'),
                desc: t('tour_p1_desc'),
                stepIndex: 0,
                totalSteps: 4,
              );
            },
          ),
        ],
        shape: ShapeLightFocus.RRect,
        radius: 12,
        glowEnable: _glowEnable,
        glowRadius: _glowRadius,
        glowColor: const Color(0xFF818CF8),
      ),
    );

    // 2. Balance Overview Target
    targets.add(
      TargetFocus(
        identify: "balanceOverviewTarget",
        keyTarget: keyBalanceOverview,
        contents: [
          TargetContent(
            align: ContentAlign.bottom,
            builder: (context, controller) {
              return _buildTourCard(
                controller: controller,
                title: t('tour_p2_title'),
                desc: t('tour_p2_desc'),
                stepIndex: 1,
                totalSteps: 4,
              );
            },
          ),
        ],
        shape: ShapeLightFocus.RRect,
        radius: 12,
        glowEnable: _glowEnable,
        glowRadius: _glowRadius,
        glowColor: const Color(0xFFF59E0B),
      ),
    );

    // 3. Quick Actions Row Target
    targets.add(
      TargetFocus(
        identify: "quickActionsTarget",
        keyTarget: keyQuickActions,
        contents: [
          TargetContent(
            align: ContentAlign.top,
            builder: (context, controller) {
              return _buildTourCard(
                controller: controller,
                title: t('tour_p3_title'),
                desc: t('tour_p3_desc'),
                stepIndex: 2,
                totalSteps: 4,
              );
            },
          ),
        ],
        shape: ShapeLightFocus.RRect,
        radius: 16,
        glowEnable: _glowEnable,
        glowRadius: _glowRadius,
        glowColor: const Color(0xFF10B981),
      ),
    );

    // 4. Off-screen Recent Transactions (tests auto-scroll)
    targets.add(
      TargetFocus(
        identify: "transactionsSectionTarget",
        keyTarget: keyTransactionsSection,
        contents: [
          TargetContent(
            align: ContentAlign.top,
            builder: (context, controller) {
              return _buildTourCard(
                controller: controller,
                title: t('tour_p4_title'),
                desc: t('tour_p4_desc'),
                stepIndex: 3,
                totalSteps: 4,
              );
            },
          ),
        ],
        shape: ShapeLightFocus.RRect,
        radius: 12,
        glowEnable: _glowEnable,
        glowRadius: _glowRadius,
        glowColor: const Color(0xFFEF4444),
      ),
    );

    return targets;
  }

  Widget _buildTourCard({
    required AppOnboardingGuideController controller,
    required String title,
    required String desc,
    required int stepIndex,
    required int totalSteps,
  }) {
    final isFirst = stepIndex == 0;
    final isLast = stepIndex == totalSteps - 1;

    return Container(
      width: MediaQuery.of(context).size.width - 40,
      margin: const EdgeInsets.symmetric(horizontal: 20),
      decoration: BoxDecoration(
        color: const Color(0xFF1E293B), // Slate 800
        borderRadius: BorderRadius.circular(16),
        border: Border.all(color: Colors.white.withOpacity(0.15)),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withOpacity(0.3),
            blurRadius: 10,
            offset: const Offset(0, 5),
          ),
        ],
      ),
      padding: const EdgeInsets.all(20),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                title,
                style: const TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                  color: Colors.white,
                ),
              ),
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
                decoration: BoxDecoration(
                  color: const Color(0xFF4F46E5), // Indigo 600
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Text(
                  '${stepIndex + 1}/$totalSteps',
                  style: const TextStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                ),
              ),
            ],
          ),
          const SizedBox(height: 12),
          Text(
            desc,
            style: TextStyle(
              fontSize: 14,
              color: Colors.white.withOpacity(0.85),
              height: 1.4,
            ),
          ),
          const SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              if (!isFirst)
                TextButton(
                  onPressed: () => controller.previous(),
                  child: Text(
                    t('tour_prev'),
                    style: const TextStyle(color: Colors.white70),
                  ),
                ),
              if (isFirst)
                TextButton(
                  onPressed: () => appOnboardingGuide.goTo(3),
                  child: Text(
                    '${t('tour_next')} ${t('recent_transactions')}',
                    style: const TextStyle(color: Colors.amber),
                  ),
                ),
              const SizedBox(width: 8),
              ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: const Color(0xFF4F46E5),
                  foregroundColor: Colors.white,
                ),
                onPressed: () {
                  if (isLast) {
                    controller.skip();
                  } else {
                    controller.next();
                  }
                },
                child: Text(isLast ? t('tour_finish') : t('tour_next')),
              ),
            ],
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: _isArabic ? TextDirection.rtl : TextDirection.ltr,
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            t('app_title'),
            style: const TextStyle(fontWeight: FontWeight.w800, color: Colors.white),
          ),
          backgroundColor: const Color(0xFF4F46E5),
          centerTitle: true,
          elevation: 2,
          actions: [
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              child: DropdownButton<String>(
                value: _isArabic ? 'ar' : 'en',
                dropdownColor: const Color(0xFF4F46E5),
                icon: const Icon(Icons.language, color: Colors.white),
                underline: const SizedBox(),
                items: const [
                  DropdownMenuItem(
                    value: 'en',
                    child: Text('EN', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
                  ),
                  DropdownMenuItem(
                    value: 'ar',
                    child: Text('عربي', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
                  ),
                ],
                onChanged: (langCode) {
                  if (langCode != null) {
                    setState(() {
                      _isArabic = (langCode == 'ar');
                    });
                  }
                },
              ),
            ),
          ],
        ),
        body: SafeArea(
          child: SingleChildScrollView(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  // 1. Profile Header Card
                  Card(
                    key: keyProfileHeader,
                    elevation: 4,
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
                    color: Colors.white,
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Row(
                        children: [
                          const CircleAvatar(
                            radius: 30,
                            backgroundColor: Color(0xFF818CF8),
                            child: Icon(Icons.person, size: 36, color: Colors.white),
                          ),
                          const SizedBox(width: 16),
                          Expanded(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(
                                  t('user_name'),
                                  style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF1E293B)),
                                ),
                                const SizedBox(height: 4),
                                Text(
                                  t('user_role'),
                                  style: const TextStyle(fontSize: 14, color: Color(0xFF64748B)),
                                ),
                              ],
                            ),
                          ),
                          IconButton(
                            icon: const Icon(Icons.edit, color: Color(0xFF4F46E5)),
                            onPressed: () {},
                          )
                        ],
                      ),
                    ),
                  ),
                  const SizedBox(height: 16),

                  // 2. Balance Overview Card
                  Card(
                    key: keyBalanceOverview,
                    elevation: 4,
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
                    color: const Color(0xFF4F46E5), // Premium Indigo Background
                    child: Padding(
                      padding: const EdgeInsets.all(20.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            t('balance_title'),
                            style: TextStyle(fontSize: 14, color: Colors.white.withOpacity(0.8)),
                          ),
                          const SizedBox(height: 8),
                          Text(
                            t('balance_amount'),
                            style: const TextStyle(fontSize: 32, fontWeight: FontWeight.w800, color: Colors.white, letterSpacing: -0.5),
                          ),
                          const SizedBox(height: 12),
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              Text(
                                t('balance_subtitle'),
                                style: TextStyle(fontSize: 12, color: Colors.white.withOpacity(0.7)),
                              ),
                              Container(
                                padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                                decoration: BoxDecoration(
                                  color: Colors.white.withOpacity(0.2),
                                  borderRadius: BorderRadius.circular(8),
                                ),
                                child: Row(
                                  children: const [
                                    Icon(Icons.shield, color: Colors.white, size: 12),
                                    SizedBox(width: 4),
                                    Text('Secure', style: TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold)),
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
                  const SizedBox(height: 16),

                  // 3. Quick Actions Card
                  Card(
                    key: keyQuickActions,
                    elevation: 4,
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
                    color: Colors.white,
                    child: Padding(
                      padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 12.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
                            child: Text(
                              t('quick_actions'),
                              style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Color(0xFF475569)),
                            ),
                          ),
                          const SizedBox(height: 8),
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceAround,
                            children: [
                              _buildActionButton(Icons.add_circle, t('action_add'), const Color(0xFF10B981)),
                              _buildActionButton(Icons.send, t('action_send'), const Color(0xFF3B82F6)),
                              _buildActionButton(Icons.request_page, t('action_request'), const Color(0xFFF59E0B)),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
                  const SizedBox(height: 16),

                  // 4. Customizer Settings Dashboard
                  Card(
                    key: keySettingsCard,
                    elevation: 6,
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
                    color: Colors.white,
                    child: Padding(
                      padding: const EdgeInsets.all(20.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            t('settings_title'),
                            style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Color(0xFF1E293B)),
                          ),
                          const Divider(height: 24, thickness: 1),

                          // Language switch
                          SwitchListTile(
                            contentPadding: EdgeInsets.zero,
                            title: Text(t('lang_rtl')),
                            value: _isArabic,
                            onChanged: (val) {
                              setState(() {
                                _isArabic = val;
                              });
                            },
                          ),

                          // Indicator Toggle
                          SwitchListTile(
                            contentPadding: EdgeInsets.zero,
                            title: Text(t('show_indicator')),
                            value: _showIndicator,
                            onChanged: (val) {
                              setState(() {
                                _showIndicator = val;
                              });
                            },
                          ),

                          if (_showIndicator) ...[
                            // Indicator Style selection dropdown
                            Padding(
                              padding: const EdgeInsets.symmetric(vertical: 8.0),
                              child: Row(
                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                children: [
                                  Text(t('indicator_style')),
                                  DropdownButton<StepIndicatorStyle>(
                                    value: _stepIndicatorStyle,
                                    onChanged: (val) {
                                      if (val != null) {
                                        setState(() {
                                          _stepIndicatorStyle = val;
                                        });
                                      }
                                    },
                                    items: [
                                      DropdownMenuItem(
                                        value: StepIndicatorStyle.dots,
                                        child: Text(t('dots')),
                                      ),
                                      DropdownMenuItem(
                                        value: StepIndicatorStyle.bar,
                                        child: Text(t('bar')),
                                      ),
                                      DropdownMenuItem(
                                        value: StepIndicatorStyle.numbered,
                                        child: Text(t('numbered')),
                                      ),
                                    ],
                                  ),
                                ],
                              ),
                            ),
                          ],

                          // Auto Scroll Toggle
                          SwitchListTile(
                            contentPadding: EdgeInsets.zero,
                            title: Text(t('auto_scroll')),
                            value: _autoScroll,
                            onChanged: (val) {
                              setState(() {
                                _autoScroll = val;
                              });
                            },
                          ),

                          // Pulse Toggle
                          SwitchListTile(
                            contentPadding: EdgeInsets.zero,
                            title: Text(t('pulse')),
                            value: _pulseEnable,
                            onChanged: (val) {
                              setState(() {
                                _pulseEnable = val;
                              });
                            },
                          ),

                          // Sonar Ripple Toggle
                          SwitchListTile(
                            contentPadding: EdgeInsets.zero,
                            title: Text(t('ripple')),
                            value: _rippleEnable,
                            onChanged: (val) {
                              setState(() {
                                _rippleEnable = val;
                              });
                            },
                          ),

                          // Swipe Navigation Toggle
                          SwitchListTile(
                            contentPadding: EdgeInsets.zero,
                            title: Text(t('swipe')),
                            value: _enableSwipeNavigation,
                            onChanged: (val) {
                              setState(() {
                                _enableSwipeNavigation = val;
                              });
                            },
                          ),

                          // Keyboard Navigation Toggle
                          SwitchListTile(
                            contentPadding: EdgeInsets.zero,
                            title: Text(t('keyboard')),
                            value: _enableKeyboardNavigation,
                            onChanged: (val) {
                              setState(() {
                                _enableKeyboardNavigation = val;
                              });
                            },
                          ),

                          // Spotlight Glow Toggle
                          SwitchListTile(
                            contentPadding: EdgeInsets.zero,
                            title: Text(t('spotlight_glow')),
                            value: _glowEnable,
                            onChanged: (val) {
                              setState(() {
                                _glowEnable = val;
                              });
                            },
                          ),

                          if (_glowEnable) ...[
                            // Glow Radius Slider
                            Padding(
                              padding: const EdgeInsets.symmetric(vertical: 8.0),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text('${t('glow_radius')}: ${_glowRadius.toStringAsFixed(1)}'),
                                  Slider(
                                    value: _glowRadius,
                                    min: 5.0,
                                    max: 40.0,
                                    onChanged: (val) {
                                      setState(() {
                                        _glowRadius = val;
                                      });
                                    },
                                  ),
                                ],
                              ),
                            ),
                          ],

                          // Shadow Opacity Slider
                          Padding(
                            padding: const EdgeInsets.symmetric(vertical: 8.0),
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text('${t('opacity')}: ${_opacityShadow.toStringAsFixed(2)}'),
                                Slider(
                                  value: _opacityShadow,
                                  min: 0.1,
                                  max: 0.95,
                                  onChanged: (val) {
                                    setState(() {
                                      _opacityShadow = val;
                                    });
                                  },
                                ),
                              ],
                            ),
                          ),

                          const SizedBox(height: 16),

                          // Start Guide Button
                          SizedBox(
                            width: double.infinity,
                            child: ElevatedButton.icon(
                              key: keyStartTourButton,
                              style: ElevatedButton.styleFrom(
                                backgroundColor: const Color(0xFF4F46E5),
                                foregroundColor: Colors.white,
                                padding: const EdgeInsets.symmetric(vertical: 14.0),
                                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
                              ),
                              onPressed: showTutorial,
                              icon: const Icon(Icons.play_circle_fill),
                              label: Text(
                                t('start_tour'),
                                style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                  const SizedBox(height: 60),

                  // Scroll Spacing section: Creates height between sections to verify scroll visibility
                  Container(
                    height: 250,
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        colors: [Colors.indigo.shade50, Colors.amber.shade50],
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                      ),
                      borderRadius: BorderRadius.circular(16),
                    ),
                    child: Center(
                      child: Opacity(
                        opacity: 0.3,
                        child: Icon(Icons.arrow_downward_rounded, size: 80, color: Colors.indigo.shade300),
                      ),
                    ),
                  ),
                  const SizedBox(height: 60),

                  // 5. Recent Transactions (Target at bottom of ScrollView)
                  Card(
                    key: keyTransactionsSection,
                    elevation: 4,
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
                    color: Colors.white,
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            t('recent_transactions'),
                            style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF1E293B)),
                          ),
                          const Divider(height: 20),
                          _buildTransactionItem(
                            icon: Icons.shopping_basket,
                            color: Colors.pink,
                            title: t('tx_grocery'),
                            desc: t('tx_grocery_desc'),
                            amount: '-\$45.20',
                          ),
                          _buildTransactionItem(
                            icon: Icons.electric_bolt,
                            color: Colors.amber.shade700,
                            title: t('tx_electric'),
                            desc: t('tx_electric_desc'),
                            amount: '-\$120.00',
                          ),
                          _buildTransactionItem(
                            icon: Icons.account_balance_wallet,
                            color: Colors.green,
                            title: t('tx_salary'),
                            desc: t('tx_salary_desc'),
                            amount: '+\$4,200.00',
                            isIncome: true,
                          ),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildActionButton(IconData icon, String label, Color color) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        CircleAvatar(
          radius: 24,
          backgroundColor: color.withOpacity(0.12),
          child: Icon(icon, color: color, size: 24),
        ),
        const SizedBox(height: 8),
        Text(
          label,
          style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF475569)),
        ),
      ],
    );
  }

  Widget _buildTransactionItem({
    required IconData icon,
    required Color color,
    required String title,
    required String desc,
    required String amount,
    bool isIncome = false,
  }) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8.0),
      child: Row(
        children: [
          CircleAvatar(
            backgroundColor: color.withOpacity(0.1),
            child: Icon(icon, color: color, size: 20),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  title,
                  style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1E293B)),
                ),
                Text(
                  desc,
                  style: const TextStyle(fontSize: 12, color: Color(0xFF64748B)),
                ),
              ],
            ),
          ),
          Text(
            amount,
            style: TextStyle(
              fontSize: 14,
              fontWeight: FontWeight.bold,
              color: isIncome ? const Color(0xFF10B981) : const Color(0xFFEF4444),
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
160
points
128
downloads

Documentation

API reference

Publisher

verified publisheritsxhadi.fun

Weekly Downloads

A guided tour and onboarding helper that helps you to present your app and its features in a beautiful, simple and customizable way.

Repository (GitHub)

License

MIT (license)

Dependencies

flutter

More

Packages that depend on app_onboarding_guide