flashx 1.0.0 copy "flashx: ^1.0.0" to clipboard
flashx: ^1.0.0 copied to clipboard

Beautiful, animated, and highly customizable snackbar, toast, and notification package for Flutter with zero boilerplate support.

example/lib/main.dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flashx/flashx.dart';

void main() {
  // Optional: configure global defaults before running the app.
  FlashX.configure(
    const FlashXConfig(
      position: FlashPosition.top,
      animation: FlashAnimation.slide,
      borderRadius: BorderRadius.all(Radius.circular(16)),
      duration: Duration(seconds: 4),
      showProgress: true,
    ),
  );

  runApp(const FlashXExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FlashX Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: Colors.deepPurple,
        useMaterial3: true,
        brightness: Brightness.light,
      ),
      darkTheme: ThemeData(
        colorSchemeSeed: Colors.deepPurple,
        useMaterial3: true,
        brightness: Brightness.dark,
      ),
      // 🔑 Key step: wrap with FlashXWidget.init() builder
      builder: FlashXWidget.init(),
      home: const ExampleHome(),
    );
  }
}

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

  @override
  State<ExampleHome> createState() => _ExampleHomeState();
}

class _ExampleHomeState extends State<ExampleHome> {
  FlashPosition _position = FlashPosition.top;
  FlashAnimation _animation = FlashAnimation.slide;
  bool _showTitle = true;
  bool _showAction = false;
  bool _blur = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('🔥 FlashX Demo'),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // ─── Settings ──────────────────────────────────────────────────
            _SectionHeader('Settings'),
            const SizedBox(height: 12),
            _SettingRow(
              label: 'Position',
              child: SegmentedButton<FlashPosition>(
                segments: const [
                  ButtonSegment(value: FlashPosition.top, label: Text('Top')),
                  ButtonSegment(
                      value: FlashPosition.bottom, label: Text('Bottom')),
                  ButtonSegment(
                      value: FlashPosition.center, label: Text('Center')),
                ],
                selected: {_position},
                onSelectionChanged: (s) => setState(() => _position = s.first),
              ),
            ),
            const SizedBox(height: 10),
            _SettingRow(
              label: 'Animation',
              child: DropdownButton<FlashAnimation>(
                value: _animation,
                isExpanded: true,
                items: FlashAnimation.values
                    .map((a) => DropdownMenuItem(
                          value: a,
                          child: Text(a.name),
                        ))
                    .toList(),
                onChanged: (v) => setState(() => _animation = v!),
              ),
            ),
            const SizedBox(height: 10),
            Row(
              children: [
                Expanded(
                  child: CheckboxListTile(
                    title: const Text('Show Title'),
                    value: _showTitle,
                    onChanged: (v) => setState(() => _showTitle = v!),
                    contentPadding: EdgeInsets.zero,
                  ),
                ),
                Expanded(
                  child: CheckboxListTile(
                    title: const Text('Action Button'),
                    value: _showAction,
                    onChanged: (v) => setState(() => _showAction = v!),
                    contentPadding: EdgeInsets.zero,
                  ),
                ),
                Expanded(
                  child: CheckboxListTile(
                    title: const Text('Blur'),
                    value: _blur,
                    onChanged: (v) => setState(() => _blur = v!),
                    contentPadding: EdgeInsets.zero,
                  ),
                ),
              ],
            ),
            const Divider(height: 32),

            // ─── Basic Types ───────────────────────────────────────────────
            _SectionHeader('Basic Types'),
            const SizedBox(height: 12),
            Row(
              children: [
                _TypeButton(
                  label: 'Success',
                  color: const Color(0xFF22C55E),
                  onTap: () => FlashX.success(
                    'Your changes have been saved.',
                    title: _showTitle ? 'Saved!' : null,
                    options: _buildOptions(FlashType.success),
                  ),
                ),
                const SizedBox(width: 8),
                _TypeButton(
                  label: 'Error',
                  color: const Color(0xFFEF4444),
                  onTap: () => FlashX.error(
                    'Unable to process your request.',
                    title: _showTitle ? 'Payment Failed' : null,
                    options: _buildOptions(FlashType.error),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 8),
            Row(
              children: [
                _TypeButton(
                  label: 'Warning',
                  color: const Color(0xFFF59E0B),
                  onTap: () => FlashX.warning(
                    'Your session expires in 5 minutes.',
                    title: _showTitle ? 'Session Expiring' : null,
                    options: _buildOptions(FlashType.warning),
                  ),
                ),
                const SizedBox(width: 8),
                _TypeButton(
                  label: 'Info',
                  color: const Color(0xFF3B82F6),
                  onTap: () => FlashX.info(
                    'Version 2.0 is available for download.',
                    title: _showTitle ? 'Update Available' : null,
                    options: _buildOptions(FlashType.info),
                  ),
                ),
              ],
            ),
            const Divider(height: 32),

            // ─── Advanced ──────────────────────────────────────────────────
            _SectionHeader('Advanced Features'),
            const SizedBox(height: 12),

            _DemoButton(
              icon: Icons.hourglass_top_rounded,
              label: 'Loading → Success',
              subtitle: 'Tracks an async operation',
              onTap: () async {
                await FlashX.future(
                  future: Future.delayed(const Duration(seconds: 2)),
                  loading: 'Processing your order...',
                  success: 'Order placed successfully! 🎉',
                  error: 'Order failed. Please try again.',
                );
              },
            ),
            const SizedBox(height: 8),

            _DemoButton(
              icon: Icons.layers_rounded,
              label: 'Queue Multiple',
              subtitle: 'Shows 4 notifications in sequence',
              onTap: () {
                FlashX.info('First notification in queue');
                FlashX.success('Second — success!');
                FlashX.warning('Third — heads up');
                FlashX.error('Fourth — uh oh');
              },
            ),
            const SizedBox(height: 8),

            _DemoButton(
              icon: Icons.priority_high_rounded,
              label: 'Priority Queue',
              subtitle: 'Critical items jump the queue',
              onTap: () {
                FlashX.show(const FlashOptions(
                  type: FlashType.info,
                  message: 'Normal priority #1',
                  priority: FlashPriority.normal,
                ));
                FlashX.show(const FlashOptions(
                  type: FlashType.info,
                  message: 'Normal priority #2',
                  priority: FlashPriority.normal,
                ));
                FlashX.show(const FlashOptions(
                  type: FlashType.error,
                  title: 'Critical Alert',
                  message: 'This jumps to the front!',
                  priority: FlashPriority.critical,
                ));
              },
            ),
            const SizedBox(height: 8),

            _DemoButton(
              icon: Icons.widgets_rounded,
              label: 'Custom Widget',
              subtitle: 'Fully custom notification content',
              onTap: () {
                FlashX.show(FlashOptions(
                  type: FlashType.custom,
                  position: _position,
                  animation: _animation,
                  themeData: const FlashThemeData(
                    backgroundColor: Color(0xFF1E1B4B),
                    textColor: Colors.white,
                    iconColor: Colors.white,
                    actionColor: Colors.amberAccent,
                    progressColor: Colors.amber,
                    borderColor: Color(0xFF312E81),
                    borderWidth: 1,
                  ),
                  customWidget: Padding(
                    padding: const EdgeInsets.all(14),
                    child: Row(
                      children: [
                        Container(
                          width: 40,
                          height: 40,
                          decoration: BoxDecoration(
                            color: Colors.amber.withValues(alpha: 0.2),
                            shape: BoxShape.circle,
                          ),
                          child: const Icon(Icons.star_rounded,
                              color: Colors.amber),
                        ),
                        const SizedBox(width: 12),
                        const Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              Text('Custom Widget!',
                                  style: TextStyle(
                                      color: Colors.white,
                                      fontWeight: FontWeight.bold)),
                              Text('You can render anything here.',
                                  style: TextStyle(
                                      color: Colors.white70, fontSize: 12)),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ));
              },
            ),
            const SizedBox(height: 8),

            _DemoButton(
              icon: Icons.gradient_rounded,
              label: 'Gradient Background',
              subtitle: 'Custom gradient theme',
              onTap: () {
                FlashX.show(FlashOptions(
                  type: FlashType.custom,
                  title: 'Premium Feature',
                  message: 'Unlock the full experience.',
                  position: _position,
                  animation: _animation,
                  actionText: 'Upgrade',
                  onAction: () {},
                  themeData: FlashThemeData(
                    backgroundColor: Colors.transparent,
                    textColor: Colors.white,
                    iconColor: Colors.white,
                    actionColor: Colors.amber,
                    progressColor: Colors.amber,
                    gradient: const LinearGradient(
                      colors: [Color(0xFF7C3AED), Color(0xFFEC4899)],
                    ),
                    elevation: 12,
                    shadowColor: const Color(0x807C3AED),
                  ),
                ));
              },
            ),
            const SizedBox(height: 8),

            _DemoButton(
              icon: Icons.deselect_rounded,
              label: 'Persistent + Dismiss All',
              subtitle: 'Manual dismissal',
              onTap: () {
                FlashX.show(const FlashOptions(
                  type: FlashType.info,
                  title: 'Persistent',
                  message: 'This stays until dismissed.',
                  duration: null,
                  showProgress: false,
                  actionText: 'Got it',
                  onAction: null,
                ));
                Future.delayed(const Duration(seconds: 3), FlashX.dismissAll);
              },
            ),
            const SizedBox(height: 8),

            _DemoButton(
              icon: Icons.deselect_outlined,
              label: 'Duplicate Prevention',
              subtitle: 'Same key = shown only once',
              onTap: () {
                for (int i = 0; i < 5; i++) {
                  FlashX.show(const FlashOptions(
                    type: FlashType.warning,
                    message: 'Only one of these shows!',
                    key: 'dedupe_demo',
                  ));
                }
              },
            ),
            const SizedBox(height: 32),
          ],
        ),
      ),
    );
  }

  FlashOptions _buildOptions(FlashType type) {
    return FlashOptions(
      type: type,
      position: _position,
      animation: _animation,
      actionText: _showAction ? 'Undo' : null,
      onAction: _showAction ? () => FlashX.info('Action tapped!') : null,
      themeData: _blur
          ? FlashThemeData.glassSuccess(
              dark: Theme.of(context).brightness == Brightness.dark)
          : null,
    );
  }
}

// ─── Helper Widgets ──────────────────────────────────────────────────────────

class _SectionHeader extends StatelessWidget {
  final String text;
  const _SectionHeader(this.text);

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: Theme.of(context).textTheme.titleMedium?.copyWith(
            fontWeight: FontWeight.w700,
          ),
    );
  }
}

class _SettingRow extends StatelessWidget {
  final String label;
  final Widget child;

  const _SettingRow({required this.label, required this.child});

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(label,
            style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600)),
        const SizedBox(height: 4),
        child,
      ],
    );
  }
}

class _TypeButton extends StatelessWidget {
  final String label;
  final Color color;
  final VoidCallback onTap;

  const _TypeButton({
    required this.label,
    required this.color,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: FilledButton(
        onPressed: onTap,
        style: FilledButton.styleFrom(
          backgroundColor: color,
          foregroundColor: Colors.white,
          padding: const EdgeInsets.symmetric(vertical: 14),
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
        ),
        child: Text(label, style: const TextStyle(fontWeight: FontWeight.w700)),
      ),
    );
  }
}

class _DemoButton extends StatelessWidget {
  final IconData icon;
  final String label;
  final String subtitle;
  final VoidCallback onTap;

  const _DemoButton({
    required this.icon,
    required this.label,
    required this.subtitle,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.zero,
      child: ListTile(
        leading: Icon(icon, color: Theme.of(context).colorScheme.primary),
        title: Text(label, style: const TextStyle(fontWeight: FontWeight.w600)),
        subtitle: Text(subtitle, style: const TextStyle(fontSize: 12)),
        trailing: const Icon(Icons.chevron_right_rounded),
        onTap: onTap,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
      ),
    );
  }
}
2
likes
140
points
130
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Beautiful, animated, and highly customizable snackbar, toast, and notification package for Flutter with zero boilerplate support.

Topics

#animations #notification #overlay #snackbar #toast

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flashx