fluxy 1.2.1 copy "fluxy: ^1.2.1" to clipboard
fluxy: ^1.2.1 copied to clipboard

Core engine of the Fluxy framework including UI, state management, HTTP, and motion.

example/lib/main.dart

import 'dart:math' as math;
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:fluxy/fluxy.dart';
import 'package:fluxy_animations/fluxy_animations.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  Fluxy.autoRegister();
  await Fluxy.init();
  runApp(Fluxy.debug(child: const FluxyOrderHistoryApp()));
}

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

  @override
  Widget build(BuildContext context) {
    return FluxyApp(
      title: 'Fluxy Order History',
      theme: ThemeData(
        scaffoldBackgroundColor: const Color(0xFF0F172A),
        appBarTheme: const AppBarTheme(
          backgroundColor: Colors.transparent,
          elevation: 0,
        ),
      ),
      home: const FluxyErrorBoundary(child: FluxyMainNavigation()),
    );
  }
}

// --- FLUXY REACTIVE STATE ---
final appCurrentIndex = flux(1);

final selectedTabIndex = flux(0);
final tabsList = ['All', 'Active', 'Completed', 'Cancelled'];

final allOrders = fluxList<Map<String, dynamic>>([
  {
    'orderId': '#FLX-8472',
    'date': 'Oct 24, 2026',
    'status': 'Delivered',
    'statusColor': Colors.greenAccent,
    'items': '2x Fluxy Earbuds Pro\n1x Fluxy Charger',
    'amount': '\$249.00',
    'isActive': false,
    'tab': 'Completed',
  },
  {
    'orderId': '#FLX-8473',
    'date': 'Oct 22, 2026',
    'status': 'In Transit',
    'statusColor': Colors.blueAccent,
    'items': '1x Fluxy Smart Watch',
    'amount': '\$199.50',
    'isActive': true,
    'tab': 'Active',
  },
  {
    'orderId': '#FLX-8411',
    'date': 'Oct 15, 2026',
    'status': 'Cancelled',
    'statusColor': Colors.redAccent,
    'items': '1x Fluxy Phone Case',
    'amount': '\$29.99',
    'isActive': false,
    'tab': 'Cancelled',
  },
]);

final GlobalKey<ScaffoldState> fluxyAppScaffoldKey = GlobalKey<ScaffoldState>();

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

  @override
  Widget build(BuildContext context) {
    return Fx(() {
      final isDark = FxTheme.isDarkMode;

      final body = IndexedStack(
        index: appCurrentIndex.value,
        children: const [
          ECommerceShopPage(),
          OrderHistoryPage(),
          CartAndCheckoutPage(),
          UserProfilePage(),
          MotionShowcasePage(),
        ],
      );

      final navbar = Theme(
        // Ensure correct theme context for native fallback
        data: isDark ? ThemeData.dark() : ThemeData.light(),
        child: FxBottomBar(
          currentIndex: appCurrentIndex.value,
          onTap: (i) => appCurrentIndex.value = i,
          activeColor: Fx.primary,
          baseColor: isDark ? Colors.white54 : Colors.black45,
          containerStyle: FxStyle(
            backgroundColor: isDark ? const Color(0xFF1E293B) : Colors.white,
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
            borderRadius: const BorderRadius.vertical(top: Radius.circular(32)),
            shadows: isDark
                ? [
                    BoxShadow(
                      color: Fx.primary.withValues(alpha: 0.15),
                      blurRadius: 30,
                      offset: const Offset(0, -5),
                    ),
                  ]
                : [
                    BoxShadow(
                      color: Fx.primary.withValues(alpha: 0.1),
                      blurRadius: 40,
                      offset: const Offset(0, -10),
                    ),
                  ],
          ),
          items: const [
            FxBottomBarItem(icon: Icons.storefront_rounded, label: 'Shop'),
            FxBottomBarItem(icon: Icons.receipt_long_rounded, label: 'Orders'),
            FxBottomBarItem(icon: Icons.shopping_bag_rounded, label: 'Cart'),
            FxBottomBarItem(icon: Icons.person_rounded, label: 'Profile'),
            FxBottomBarItem(icon: Icons.auto_awesome_rounded, label: 'Motion'),
          ],
        ),
      );

      final sidebar = FxSidebar(
        style: FxStyle(
          backgroundColor: isDark ? const Color(0xFF1E293B) : Colors.white,
        ),
        header: Fx.col(
          gap: 20,
          alignItems: CrossAxisAlignment.start,
          style: const FxStyle(
            padding: EdgeInsets.only(left: 16, right: 16, top: 32, bottom: 16),
          ),
          children: [
            Fx.row(
              gap: 12,
              alignItems: CrossAxisAlignment.center,
              children: [
                Fx.box(
                  style: FxStyle(
                    backgroundColor: Fx.primary.withValues(alpha: 0.15),
                    padding: const EdgeInsets.all(12),
                    borderRadius: BorderRadius.circular(16),
                  ),
                  child: Fx.icon(
                    Icons.bubble_chart_rounded,
                    color: Fx.primary,
                    size: 32,
                  ),
                ),
                Fx.col(
                  alignItems: CrossAxisAlignment.start,
                  children: [
                    Fx.text('Fluxy UI').style(
                      FxStyle(
                        fontSize: 22,
                        fontWeight: FontWeight.bold,
                        color: isDark ? Colors.white : Colors.black87,
                      ),
                    ),
                    Fx.text('v2.0.0 Pro').style(
                      FxStyle(
                        fontSize: 12,
                        fontWeight: FontWeight.w600,
                        color: Fx.primary,
                      ),
                    ),
                  ],
                ),
              ],
            ),
            const SizedBox(height: 8),
            // User profile mini
            Fx.box(
              style: FxStyle(
                backgroundColor: isDark
                    ? const Color(0xFF334155)
                    : Colors.grey[100],
                borderRadius: BorderRadius.circular(16),
                padding: const EdgeInsets.all(12),
              ),
              child: Fx.row(
                gap: 12,
                children: [
                  const FxAvatar(
                    image: 'https://i.pravatar.cc/150?img=11',
                    fallback: 'JS',
                    size: FxAvatarSize.md,
                  ),
                  Expanded(
                    child: Fx.col(
                      alignItems: CrossAxisAlignment.start,
                      children: [
                        Fx.text('Jane Smith').style(
                          FxStyle(
                            fontSize: 14,
                            fontWeight: FontWeight.w600,
                            color: isDark ? Colors.white : Colors.black87,
                          ),
                        ),
                        Fx.text('Pro Member').style(
                          FxStyle(
                            fontSize: 12,
                            color: isDark ? Colors.white54 : Colors.black54,
                          ),
                        ),
                      ],
                    ),
                  ),
                  Fx.icon(
                    Icons.unfold_more_rounded,
                    color: isDark ? Colors.white54 : Colors.black54,
                    size: 18,
                  ),
                ],
              ),
            ),
          ],
        ),
        currentIndex: appCurrentIndex.value,
        onTap: (index) {
          if (index < 4) {
            appCurrentIndex.value = index;
          } else {
            Fx.toast.info('Feature unavailable');
          }
        },
        items: [
          const FxSidebarItem(icon: Icons.storefront_rounded, label: 'Shop Explore'),
          FxSidebarItem(
              icon: Icons.receipt_long_rounded, 
              label: 'Order History',
              trailing: FxPulsar(
                child: Fx.box(
                  style: FxStyle(
                    backgroundColor: Fx.primary,
                    padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: Fx.text('3').style(const FxStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold)),
                ),
              ),
          ),
          const FxSidebarItem(icon: Icons.shopping_bag_rounded, label: 'My Cart'),
          const FxSidebarItem(icon: Icons.person_rounded, label: 'Profile'),
          const FxSidebarItem(icon: Icons.auto_awesome_rounded, label: 'Motion'),
          const FxSidebarItem(label: 'Preferences', isHeader: true),
          const FxSidebarItem(icon: Icons.settings_suggest_rounded, label: 'Advanced Settings'),
        ],
        footer: Fx.col(
          gap: 16,
          style: const FxStyle(
            padding: EdgeInsets.symmetric(horizontal: 16, vertical: 24),
          ),
          children: [
            Fx.box(
              style: FxStyle(
                padding: const EdgeInsets.all(16),
                borderRadius: BorderRadius.circular(16),
                backgroundColor: isDark
                    ? Fx.primary.withValues(alpha: 0.1)
                    : Fx.primary.withValues(alpha: 0.05),
                border: Border.all(color: Fx.primary.withValues(alpha: 0.2)),
              ),
              child: Fx.col(
                gap: 12,
                alignItems: CrossAxisAlignment.start,
                children: [
                  Fx.icon(Icons.auto_awesome_rounded, color: Fx.primary),
                  Fx.text(
                    'Unlock Premium features & advanced analytics.',
                  ).style(
                    FxStyle(
                      fontSize: 13,
                      color: isDark ? Colors.white70 : Colors.black87,
                    ),
                  ),
                  FxBoing(
                    onTap: () {
                      Fx.toast.info('Upgrading to Pro...');
                    },
                    child: Fx.box(
                      style: FxStyle(
                        backgroundColor: Fx.primary,
                        borderRadius: BorderRadius.circular(8),
                        padding: const EdgeInsets.symmetric(
                          horizontal: 16,
                          vertical: 8,
                        ),
                        width: double.infinity,
                        alignment: Alignment.center,
                      ),
                      child: Fx.text('Upgrade Now').style(
                        const FxStyle(
                          color: Colors.white,
                          fontWeight: FontWeight.bold,
                          fontSize: 14,
                        ),
                      ),
                    ),
                  )
                ],
              ),
            ),
            Material(
              color: Colors.transparent,
              child: InkWell(
                borderRadius: BorderRadius.circular(12),
                onTap: () {
                  Fx.toast.info('Logged out');
                },
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
                  child: Row(
                    children: [
                      Icon(Icons.exit_to_app_rounded, color: isDark ? Colors.white70 : Colors.black87),
                      const SizedBox(width: 14),
                      Text(
                        'Log Out', 
                        style: TextStyle(
                          fontSize: 15,
                          fontWeight: FontWeight.w500,
                          color: isDark ? Colors.white70 : Colors.black87,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      );

      // Demonstrating standalone Sidebar execution without specialized widgets.
      // Utilize Fx.layout to decide structural positioning manually.
      return Fx.layout(
        mobile: Scaffold(
          key: fluxyAppScaffoldKey,
          drawer: Drawer(child: sidebar),
          body: Fx.page(
            // Fx.page acts as a container for our view to hook in the bottom nav bar correctly
            bottomNavigationBar: navbar,
            child: body,
          ),
        ),
        desktop: Scaffold(
          key: fluxyAppScaffoldKey,
          body: Fx.row(
            children: [
               sidebar,
               Expanded(
                 child: Fx.page(
                   bottomNavigationBar: navbar,
                 child: body,
                ),
              )
            ],
          ),
        ),
      );
    });
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Fx(() {
      final isDark = FxTheme.isDarkMode;

      return Fx.safe(
        Scaffold(
          backgroundColor: isDark ? const Color(0xFF0F172A) : Colors.grey[50],
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            elevation: 0,
            title: Fx.text('Order History').style(
              FxStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
                color: isDark ? Colors.white : Colors.black87,
              ),
            ),
            centerTitle: false,
            actions: [
              GestureDetector(
                onTap: () {
                  FxTheme.toggle();
                },
                child: Padding(
                  padding: const EdgeInsets.only(right: 16.0),
                  child: Fx.icon(
                    isDark ? Icons.light_mode_rounded : Icons.dark_mode_rounded,
                    color: isDark ? Colors.amber : Colors.indigo,
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(right: 16.0),
                child: FxAvatar(
                  image: 'https://i.pravatar.cc/150?img=11',
                  fallback: 'U',
                  size: FxAvatarSize.sm,
                ),
              )
            ],
          ),
          body: Fx.col(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // Native Fluxy Tab Bar (Switches index signal)
              FxTabBar(currentIndex: selectedTabIndex, tabs: tabsList),

              Divider(
                color: isDark ? Colors.white12 : Colors.black12,
                height: 1,
              ),

              // Native Fluxy Tab View (Responds to index signal and gestures)
              Expanded(
                child: FxTabView(
                  currentIndex: selectedTabIndex,
                  children: [
                    _buildTabContent('All'),
                    _buildTabContent('Active'),
                    _buildTabContent('Completed'),
                    _buildTabContent('Cancelled'),
                  ],
                ),
              ),
            ],
          ),
        ),
      );
    });
  }

  Widget _buildTabContent(String tabName) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16.0),
      child: Fx(() {
        final filteredOrders = allOrders.where((order) {
          if (tabName == 'All') return true;
          return order['tab'] == tabName;
        }).toList();

        final isDark = FxTheme.isDarkMode;

        if (filteredOrders.isEmpty) {
          return Padding(
            padding: const EdgeInsets.symmetric(vertical: 40),
            child: Center(
              child: Fx.text(
                'No ${tabName.toLowerCase()} orders found.',
              ).style(FxStyle(color: isDark ? Colors.white54 : Colors.black54)),
            ),
          );
        }

        return FxStaggeredReveal(
          interval: const Duration(milliseconds: 100),
          children: filteredOrders.map((order) {
            return FxEntrance(
              delay: Duration(milliseconds: (filteredOrders.indexOf(order) * 50)),
              slideOffset: const Offset(0, 40),
              child: _buildOrderCard(
                orderId: order['orderId'],
                date: order['date'],
                status: order['status'],
                statusColor: order['statusColor'],
                items: order['items'],
                amount: order['amount'],
                isActive: order['isActive'],
                isDark: isDark,
              ),
            );
          }).toList(),
        );
      }),
    );
  }

  Widget _buildOrderCard({
    required String orderId,
    required String date,
    required String status,
    required Color statusColor,
    required String items,
    required String amount,
    required bool isActive,
    required bool isDark,
  }) {
    return Fx.box(
      style: FxStyle(
        backgroundColor: isDark ? const Color(0xFF1E293B) : Colors.white,
        borderRadius: BorderRadius.circular(16),
        padding: const EdgeInsets.all(20),
        border: Border.all(color: isDark ? Colors.white12 : Colors.black12),
        shadows: isDark
            ? []
            : [
                BoxShadow(
                  color: Colors.black.withValues(alpha: 0.05),
                  blurRadius: 10,
                  offset: const Offset(0, 4),
                ),
              ],
      ),
      child: Fx.col(
        gap: 16,
        alignItems: CrossAxisAlignment.start,
        children: [
          // Header: Order ID & Status
          Fx.row(
            justify: MainAxisAlignment.spaceBetween,
            alignItems: CrossAxisAlignment.center,
            children: [
              Fx.col(
                alignItems: CrossAxisAlignment.start,
                gap: 4,
                children: [
                  Fx.text(orderId).style(
                    FxStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                      color: isDark ? Colors.white : Colors.black87,
                    ),
                  ),
                  Fx.text(date).style(
                    FxStyle(
                      fontSize: 14,
                      color: isDark ? Colors.white54 : Colors.black54,
                    ),
                  ),
                ],
              ),
              Fx.box(
                style: FxStyle(
                  backgroundColor: statusColor.withValues(alpha: 0.15),
                  borderRadius: BorderRadius.circular(20),
                  padding: const EdgeInsets.symmetric(
                    horizontal: 12,
                    vertical: 6,
                  ),
                  border: Border.all(color: statusColor.withValues(alpha: 0.5)),
                ),
                child: Fx.text(status).style(
                  FxStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.bold,
                    color: statusColor,
                  ),
                ),
              ),
            ],
          ),
          
          Divider(color: isDark ? Colors.white12 : Colors.black12, height: 1),

          // Items & Amount
          Fx.row(
            justify: MainAxisAlignment.spaceBetween,
            alignItems: CrossAxisAlignment.center,
            children: [
              Expanded(
                child: Fx.text(items).style(
                  FxStyle(
                    fontSize: 14,
                    color: isDark ? Colors.white70 : Colors.black54,
                  ),
                ),
              ),
              Fx.text(amount).style(
                FxStyle(
                  fontSize: 22,
                  fontWeight: FontWeight.bold,
                  color: isDark ? Colors.white : Colors.black,
                ),
              ),
            ],
          ),
          
          // Actions
          Fx.row(
            gap: 12,
            children: [
              Expanded(
                child: Fx.outlineButton(
                  'Remove',
                  onTap: () {
                    // Reactive mutation
                    allOrders.removeWhere(
                      (o) => o['orderId'] == orderId,
                    ); // removes and if using removeWhere natively it works, but let's batch manually to notify
                    // Or safely via internal remove matching:
                    final toRemove = allOrders.firstWhere(
                      (o) => o['orderId'] == orderId,
                    );
                    allOrders.remove(toRemove);
                    Fx.toast.info('Removed $orderId');
                  },
                ),
              ),
              if (isActive)
                Expanded(
                  child: Fx.primaryButton(
                    'Cancel Order', // Update to show reactive change
                    onTap: () {
                      // Uses fluxList's reactive updater
                      allOrders.updateWhere(
                        (item) => item['orderId'] == orderId,
                        (current) => {
                          ...current,
                          'status': 'Cancelled',
                          'statusColor': Colors.redAccent,
                          'tab': 'Cancelled',
                          'isActive': false,
                        },
                      );
                      Fx.toast.success('Cancelled $orderId');
                    },
                  ),
                )
              else if (status != 'Cancelled')
                Expanded(
                  child: Fx.secondaryButton(
                    'Reorder',
                    onTap: () {
                      Fx.toast.success(
                        'Successfully Reordered items from $orderId',
                      );
                    },
                  ),
                ),
            ],
          ),
        ],
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Fx(() {
      final isDark = FxTheme.isDarkMode;

      return Fx.safe(
        Scaffold(
          backgroundColor: isDark ? const Color(0xFF0F172A) : Colors.grey[50],
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            elevation: 0,
            title: Fx.text('Profile').style(
              FxStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
                color: isDark ? Colors.white : Colors.black87,
              ),
            ),
            centerTitle: false,
            actions: [
              Padding(
                padding: const EdgeInsets.only(right: 16.0),
                child: Fx.icon(
                  Icons.settings_rounded,
                  color: isDark ? Colors.white70 : Colors.black54,
                ),
              ),
            ],
          ),
          body: SingleChildScrollView(
            padding: const EdgeInsets.all(24.0),
            child: Fx.col(
              gap: 24,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                // Profile Header
                Fx.col(
                  gap: 12,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    FxAvatar(
                      image: 'https://i.pravatar.cc/150?img=11',
                      fallback: 'JS',
                      size: FxAvatarSize.xl,
                    ),
                    Fx.text('Jane Smith').style(
                      FxStyle(
                        fontSize: 22,
                        fontWeight: FontWeight.bold,
                        color: isDark ? Colors.white : Colors.black87,
                      ),
                    ),
                    Fx.text('jane.smith@fluxyui.com').style(
                      FxStyle(
                        fontSize: 14,
                        color: isDark ? Colors.white54 : Colors.black54,
                      ),
                    ),
                  ],
                ),

                const SizedBox(height: 8),

                // Settings Card
                Fx.box(
                  style: FxStyle(
                    backgroundColor: isDark
                        ? const Color(0xFF1E293B)
                        : Colors.white,
                    borderRadius: BorderRadius.circular(16),
                    border: Border.all(
                      color: isDark ? Colors.white12 : Colors.black12,
                    ),
                    shadows: isDark
                        ? []
                        : [
                            BoxShadow(
                              color: Colors.black.withValues(alpha: 0.05),
                              blurRadius: 10,
                              offset: const Offset(0, 4),
                            ),
                          ],
                  ),
                  child: Fx.col(
                    children: [
                      _buildSettingsTile(
                        icon: Icons.person_outline_rounded,
                        title: 'Personal Information',
                        isDark: isDark,
                      ),
                      Divider(
                        color: isDark ? Colors.white12 : Colors.black12,
                        height: 1,
                      ),
                      _buildSettingsTile(
                        icon: Icons.shield_outlined,
                        title: 'Privacy & Security',
                        isDark: isDark,
                      ),
                      Divider(
                        color: isDark ? Colors.white12 : Colors.black12,
                        height: 1,
                      ),
                      _buildSettingsTile(
                        icon: Icons.notifications_none_rounded,
                        title: 'Notifications',
                        isDark: isDark,
                      ),
                      Divider(
                        color: isDark ? Colors.white12 : Colors.black12,
                        height: 1,
                      ),
                      GestureDetector(
                        onTap: () {
                          FxTheme.toggle();
                        },
                        child: _buildSettingsTile(
                          icon: isDark
                              ? Icons.light_mode_outlined
                              : Icons.dark_mode_outlined,
                          title: 'Toggle Theme',
                          isDark: isDark,
                          showArrow: false,
                        ),
                      ),
                    ],
                  ),
                ),

                // Logout Button
                const SizedBox(height: 16),
                SizedBox(
                  width: double.infinity,
                  child: Fx.outlineButton(
                    'Log Out',
                    onTap: () {
                      Fx.toast.info('Logged out successfully');
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    });
  }

  Widget _buildSettingsTile({
    required IconData icon,
    required String title,
    required bool isDark,
    bool showArrow = true,
  }) {
    return Fx.box(
      style: const FxStyle(padding: EdgeInsets.all(16)),
      child: Fx.row(
        justify: MainAxisAlignment.spaceBetween,
        children: [
          Fx.row(
            gap: 16,
            children: [
              Fx.icon(icon, color: isDark ? Colors.white70 : Colors.black54),
              Fx.text(title).style(
                FxStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                  color: isDark ? Colors.white : Colors.black87,
                ),
              ),
            ],
          ),
          if (showArrow)
            Fx.icon(
              Icons.chevron_right_rounded,
              color: isDark ? Colors.white30 : Colors.black38,
            ),
        ],
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Fx(() {
      final isDark = FxTheme.isDarkMode;
      
      return Fx.safe(
        Scaffold(
          backgroundColor: isDark ? const Color(0xFF0F172A) : Colors.grey[50],
          appBar: _buildAppBar(isDark),
          body: SingleChildScrollView(
            padding: const EdgeInsets.all(24.0),
            child: Fx.col(
              gap: 24,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                // Search Bar
                FxTextField(
                  signal: flux(''),
                  placeholder: 'Search for products...',
                  icon: Icons.search_rounded,
                  style: FxStyle(
                    backgroundColor: isDark
                        ? const Color(0xFF1E293B)
                        : Colors.white,
                    borderRadius: BorderRadius.circular(16),
                    padding: const EdgeInsets.symmetric(
                      horizontal: 16,
                      vertical: 4,
                    ),
                    border: Border.all(
                      color: isDark ? Colors.white12 : Colors.black12,
                    ),
                    shadows: isDark
                        ? []
                        : [
                            BoxShadow(
                              color: Colors.black.withValues(alpha: 0.05),
                              blurRadius: 10,
                              offset: const Offset(0, 4),
                            ),
                          ],
                  ),
                ),

                // Categories (Horizontal Scroll)
                Fx.col(
                  gap: 12,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Fx.row(
                      justify: MainAxisAlignment.spaceBetween,
                      children: [
                        Fx.text('Categories').style(
                          FxStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.bold,
                            color: isDark ? Colors.white : Colors.black87,
                          ),
                        ),
                        Fx.text('View All').style(
                          FxStyle(
                            fontSize: 14,
                            fontWeight: FontWeight.w600,
                            color: Fx.primary,
                          ),
                        ),
                      ],
                    ),
                    SingleChildScrollView(
                      scrollDirection: Axis.horizontal,
                      child: Fx.row(
                        gap: 12,
                        children: [
                          _buildCategoryChip('All', true, isDark),
                          _buildCategoryChip('Electronics', false, isDark),
                          _buildCategoryChip('Wearables', false, isDark),
                          _buildCategoryChip('Audio', false, isDark),
                          _buildCategoryChip('Accessories', false, isDark),
                        ],
                      ),
                    ),
                  ],
                ),
                
                // Popular Products Row 1
                Fx.row(
                  gap: 16,
                  children: [
                    Expanded(
                      child: _buildProductCard(
                        'Fluxy Earbuds Pro',
                        '\$199.00',
                        'https://images.unsplash.com/photo-1590658268037-6bf12165a8df?w=400&q=80',
                        isDark,
                      ),
                    ),
                    Expanded(
                      child: _buildProductCard(
                        'Smart Watch Elite',
                        '\$299.00',
                        'https://images.unsplash.com/photo-1546868871-7041f2a55e12?w=400&q=80',
                        isDark,
                      ),
                    ),
                  ],
                ),

                // Popular Products Row 2
                Fx.row(
                  gap: 16,
                  children: [
                    Expanded(
                      child: _buildProductCard(
                        'Magnetic Charger',
                        '\$49.00',
                        'https://images.unsplash.com/photo-1585338107529-13afc5f02586?w=400&q=80',
                        isDark,
                      ),
                    ),
                    Expanded(
                      child: _buildProductCard(
                        'Mechanical Keyboard',
                        '\$129.00',
                        'https://images.unsplash.com/photo-1595225476474-87563907a212?w=400&q=80',
                        isDark,
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      );
    });
  }

  PreferredSizeWidget _buildAppBar(bool isDark) {
    return AppBar(
      backgroundColor: Colors.transparent,
      elevation: 0,
      leading: IconButton(
        icon: Fx.icon(
          Icons.menu_rounded,
          color: isDark ? Colors.white : Colors.black87,
        ),
        onPressed: () {
          // Open the root drawer guaranteed via the global key
          fluxyAppScaffoldKey.currentState?.openDrawer();
        },
      ),
      title: Fx.text('Fluxy Store').style(
        FxStyle(
          fontSize: 24,
          fontWeight: FontWeight.bold,
          color: isDark ? Colors.white : Colors.black87,
        ),
      ),
      centerTitle: false,
      actions: [
        Padding(
          padding: const EdgeInsets.only(right: 16.0),
          child: FxBadge(
            color: Colors.redAccent,
            label: '3',
            offset: const Offset(4, 4),
            child: Fx.icon(
              Icons.shopping_bag_outlined,
              color: isDark ? Fx.primary : Colors.indigo,
            ),
          ),
        ),
        Padding(
          padding: const EdgeInsets.only(right: 16.0),
          child: FxAvatar(
            image: 'https://i.pravatar.cc/150?img=11',
            fallback: 'JS',
            size: FxAvatarSize.sm,
          ),
        )
      ],
    );
  }

  Widget _buildCategoryChip(String label, bool isSelected, bool isDark) {
    return Fx.box(
      style: FxStyle(
        backgroundColor: isSelected
            ? Fx.primary
            : (isDark
                  ? const Color(0xFF1E293B)
                  : Fx.primary.withValues(alpha: 0.05)),
        borderRadius: BorderRadius.circular(20),
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
        border: Border.all(
          color: isSelected
              ? Fx.primary
              : (isDark ? Colors.white12 : Fx.primary.withValues(alpha: 0.15)),
        ),
      ),
      child: Fx.text(label).style(
        FxStyle(
          fontWeight: isSelected ? FontWeight.bold : FontWeight.w600,
          color: isSelected
              ? Colors.white
              : (isDark ? Colors.white70 : Fx.primary),
        )
      ),
    );
  }

  Widget _buildProductCard(
    String title,
    String price,
    String imgUrl,
    bool isDark,
  ) {
    return Fx.box(
      style: FxStyle(
        backgroundColor: isDark ? const Color(0xFF1E293B) : Colors.white,
        borderRadius: BorderRadius.circular(16),
        border: Border.all(
          color: isDark ? Colors.white12 : Fx.primary.withValues(alpha: 0.1),
        ),
        shadows: isDark
            ? []
            : [
                BoxShadow(
                  color: Fx.primary.withValues(alpha: 0.08),
                  blurRadius: 15,
                  offset: const Offset(0, 8),
                ),
              ],
      ),
      child: Fx.col(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          // Product Image area
          Box(
            style: FxStyle(
              height: 140,
              backgroundColor: isDark ? Colors.black26 : Colors.grey[100],
              borderRadius: const BorderRadius.vertical(
                top: Radius.circular(16),
              ),
              clipBehavior: Clip.antiAlias,
            ),
            child: Image.network(
              imgUrl,
              fit: BoxFit.cover,
              errorBuilder: (c, e, s) =>
                  Center(child: Fx.icon(Icons.image_not_supported_outlined)),
            ),
          ),
          
          // Product Details
          Padding(
            padding: const EdgeInsets.all(12.0),
            child: Fx.col(
              gap: 8,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Fx.text(title).style(
                  FxStyle(
                    fontSize: 14,
                    fontWeight: FontWeight.bold,
                    color: isDark ? Colors.white : Colors.black87,
                  ),
                ),
                Fx.text(price).style(
                  FxStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                    color: Fx.primary,
                  ),
                ),

                const SizedBox(height: 4),
                // Add to Cart Button
                SizedBox(
                  width: double.infinity,
                  child: Fx.primaryButton(
                    'Add',
                    onTap: () {
                      Fx.toast.success('Added $title to cart!');
                    },
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

// Simple state for the checkout form
final promoCodeSignal = flux('');
final saveCardSignal = flux(true);

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

  @override
  Widget build(BuildContext context) {
    return Fx(() {
      final isDark = FxTheme.isDarkMode;

      return Fx.safe(
        Scaffold(
          backgroundColor: isDark ? const Color(0xFF0F172A) : Colors.grey[50],
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            elevation: 0,
            title: Fx.text('Checkout').style(
              FxStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
                color: isDark ? Colors.white : Colors.black87,
              ),
            ),
            centerTitle: false,
          ),
          body: SingleChildScrollView(
            padding: const EdgeInsets.all(24.0),
            child: Fx.col(
              gap: 24,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                // Order Summary Card
                Fx.box(
                  style: FxStyle(
                    backgroundColor: isDark
                        ? const Color(0xFF1E293B)
                        : Colors.white,
                    borderRadius: BorderRadius.circular(16),
                    padding: const EdgeInsets.all(20),
                    border: Border.all(
                      color: isDark ? Colors.white12 : Colors.black12,
                    ),
                    shadows: isDark
                        ? []
                        : [
                            BoxShadow(
                              color: Colors.black.withValues(alpha: 0.05),
                              blurRadius: 10,
                              offset: const Offset(0, 4),
                            ),
                          ],
                  ),
                  child: Fx.col(
                    gap: 16,
                    children: [
                      Fx.text('Order Summary').style(
                        FxStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                          color: isDark ? Colors.white : Colors.black87,
                        ),
                      ),
                      _buildCartItem('Fluxy Earbuds Pro', '\$199.00', isDark),
                      _buildCartItem('Magnetic Charger', '\$49.00', isDark),
                      Divider(
                        color: isDark ? Colors.white12 : Colors.black12,
                        height: 1,
                      ),
                      Fx.row(
                        justify: MainAxisAlignment.spaceBetween,
                        children: [
                          Fx.text('Total').style(
                            FxStyle(
                              fontSize: 16,
                              color: isDark ? Colors.white54 : Colors.black54,
                            ),
                          ),
                          Fx.text('\$248.00').style(
                            FxStyle(
                              fontSize: 24,
                              fontWeight: FontWeight.bold,
                              color: Fx.primary,
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),

                // Payment Info
                Fx.text('Payment Information').style(
                  FxStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                    color: isDark ? Colors.white : Colors.black87,
                  ),
                ),
                Fx.box(
                  style: FxStyle(
                    backgroundColor: isDark
                        ? const Color(0xFF1E293B)
                        : Colors.white,
                    borderRadius: BorderRadius.circular(16),
                    padding: const EdgeInsets.all(20),
                    border: Border.all(
                      color: isDark ? Colors.white12 : Colors.black12,
                    ),
                  ),
                  child: Fx.col(
                    gap: 16,
                    children: [
                      // Using Fluxy's Reactive inputs!
                      FxTextField(
                        signal: flux(''), // placeholder signal
                        label: 'Card Number',
                        placeholder: '0000 0000 0000 0000',
                        icon: Icons.credit_card_rounded,
                        keyboardType: TextInputType.number,
                        style: FxStyle(
                          backgroundColor: isDark
                              ? const Color(0xFF0F172A)
                              : Colors.grey[50]!,
                          borderRadius: BorderRadius.circular(12),
                          padding: const EdgeInsets.symmetric(
                            horizontal: 16,
                            vertical: 4,
                          ),
                          border: Border.all(
                            color: isDark ? Colors.white12 : Colors.black12,
                          ),
                          color: isDark ? Colors.white : Colors.black87,
                        ),
                      ),
                      Fx.row(
                        gap: 16,
                        children: [
                          Expanded(
                            child: FxTextField(
                              signal: flux(''),
                              label: 'Expiry',
                              placeholder: 'MM/YY',
                              style: FxStyle(
                                backgroundColor: isDark
                                    ? const Color(0xFF0F172A)
                                    : Colors.grey[50]!,
                                borderRadius: BorderRadius.circular(12),
                                padding: const EdgeInsets.symmetric(
                                  horizontal: 16,
                                  vertical: 4,
                                ),
                                border: Border.all(
                                  color: isDark
                                      ? Colors.white12
                                      : Colors.black12,
                                ),
                                color: isDark ? Colors.white : Colors.black87,
                              ),
                            ),
                          ),
                          Expanded(
                            child: FxTextField(
                              signal: flux(''),
                              label: 'CVC',
                              placeholder: '123',
                              obscureText: true,
                              keyboardType: TextInputType.number,
                              style: FxStyle(
                                backgroundColor: isDark
                                    ? const Color(0xFF0F172A)
                                    : Colors.grey[50]!,
                                borderRadius: BorderRadius.circular(12),
                                padding: const EdgeInsets.symmetric(
                                  horizontal: 16,
                                  vertical: 4,
                                ),
                                border: Border.all(
                                  color: isDark
                                      ? Colors.white12
                                      : Colors.black12,
                                ),
                                color: isDark ? Colors.white : Colors.black87,
                              ),
                            ),
                          ),
                        ],
                      ),
                      
                      const SizedBox(height: 8),
                      // Reactive Checkbox
                      Fx.row(
                        gap: 12,
                        children: [
                          FxCheckbox(
                            signal: saveCardSignal,
                            activeColor: Fx.primary,
                          ),
                          Fx.text('Save card information later').style(
                            FxStyle(
                              fontSize: 14,
                              color: isDark ? Colors.white70 : Colors.black87,
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),

                // Promo code
                Fx.row(
                  gap: 12,
                  children: [
                    Expanded(
                      child: FxTextField(
                        signal: promoCodeSignal,
                        placeholder: 'Enter Promo Code',
                        style: FxStyle(
                          backgroundColor: isDark
                              ? const Color(0xFF1E293B)
                              : Colors.white,
                          borderRadius: BorderRadius.circular(12),
                          padding: const EdgeInsets.symmetric(
                            horizontal: 16,
                            vertical: 4,
                          ),
                          border: Border.all(
                            color: isDark ? Colors.white12 : Colors.black12,
                          ),
                          color: isDark ? Colors.white : Colors.black87,
                        ),
                      ),
                    ),
                    Fx.outlineButton(
                      'Apply',
                      onTap: () {
                        if (promoCodeSignal.value.isNotEmpty) {
                          Fx.toast.success('Promo code applied!');
                        }
                      },
                    ),
                  ],
                ),

                const SizedBox(height: 16),

                // Checkout large button
                SizedBox(
                  width: double.infinity,
                  height: 56,
                  child: Fx.primaryButton(
                    'Pay \$248.00',
                    onTap: () {
                      Fx.loader.show();
                      // Simulate network request
                      Future.delayed(const Duration(seconds: 2), () {
                        Fx.loader.hide();
                        Fx.toast.success('Payment successful!');
                      });
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    });
  }

  Widget _buildCartItem(String name, String price, bool isDark) {
    return Fx.row(
      justify: MainAxisAlignment.spaceBetween,
      children: [
        Fx.text(name).style(
          FxStyle(
            fontSize: 16,
            fontWeight: FontWeight.w500,
            color: isDark ? Colors.white70 : Colors.black87,
          ),
        ),
        Fx.text(price).style(
          FxStyle(
            fontSize: 16,
            fontWeight: FontWeight.bold,
            color: isDark ? Colors.white : Colors.black,
          ),
        ),
      ],
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Fx(() {
      final isDark = FxTheme.isDarkMode;

      return Scaffold(
        backgroundColor: isDark ? const Color(0xFF0F172A) : Colors.grey[50],
        appBar: AppBar(
          backgroundColor: Colors.transparent,
          elevation: 0,
          title: Fx.text('Motion Lab').style(
            FxStyle(
              fontSize: 24,
              fontWeight: FontWeight.bold,
              color: isDark ? Colors.white : Colors.black87,
            ),
          ),
        ),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(24),
          child: Fx.col(
            gap: 32,
            children: [
              // 1. MAGNETIC PHYSICS
              _buildSection(
                title: "Magnetic Physics",
                description: "Interactive widgets that stick to your touch and snap back with elite spring physics.",
                isDark: isDark,
                child: Center(
                  child: FxMagnetic(
                    reach: 120,
                    intensity: 0.5,
                    child: Fx.box(
                      style: FxStyle(
                        width: 200,
                        padding: const EdgeInsets.all(24),
                        backgroundColor: Fx.primary,
                        borderRadius: BorderRadius.circular(20),
                        shadows: [
                          BoxShadow(
                            color: Fx.primary.withOpacity(0.4),
                            blurRadius: 20,
                            offset: const Offset(0, 10),
                          )
                        ],
                      ),
                      child: Fx.col(
                        gap: 8,
                        children: [
                          const Icon(Icons.touch_app, color: Colors.white, size: 32),
                          Fx.text("Touch Me").style(const FxStyle(color: Colors.white, fontWeight: FontWeight.bold)).center(),
                        ],
                      ),
                    ),
                  ),
                ),
              ),

              // 2. CHOREOGRAPHY
              _buildSection(
                title: "Timeline Choreography",
                description: "Chained animations (Scale -> Rotate -> Pulse) without nesting boilerplate.",
                isDark: isDark,
                child: Center(
                  child: FxChoreography(
                    repeat: true,
                    steps: [
                      FxStep(
                        duration: const Duration(milliseconds: 600),
                        scale: Tween(begin: 1.0, end: 1.4),
                        curve: Curves.elasticOut,
                      ),
                      FxStep(
                        duration: const Duration(milliseconds: 400),
                        rotate: Tween(begin: 0.0, end: 3.14 / 4), // 45 deg
                        curve: Curves.easeInOutBack,
                      ),
                      FxStep(
                        duration: const Duration(milliseconds: 600),
                        fade: Tween(begin: 1.0, end: 0.5),
                        scale: Tween(begin: 1.4, end: 1.0),
                      ),
                      FxStep(
                        duration: const Duration(milliseconds: 400),
                        fade: Tween(begin: 0.5, end: 1.0),
                        rotate: Tween(begin: 3.14 / 4, end: 0.0),
                      ),
                    ],
                    child: Fx.box(
                      style: FxStyle(
                        width: 80,
                        height: 80,
                        backgroundColor: Colors.amber,
                        borderRadius: BorderRadius.circular(20),
                      ),
                      child: const Icon(Icons.auto_awesome, color: Colors.white, size: 40),
                    ),
                  ),
                ),
              ),

              // 3. LIQUID SHIMMER
              _buildSection(
                title: "Liquid Shimmer",
                description: "Elite shader-based loading states that feel smooth and organic.",
                isDark: isDark,
                child: FxLiquidShimmer(
                  child: Fx.col(
                    gap: 16,
                    children: [
                      Fx.row(
                        gap: 12,
                        children: [
                          Fx.box(style: FxStyle(width: 50, height: 50, borderRadius: BorderRadius.circular(25), backgroundColor: isDark ? Colors.white10 : Colors.black12)),
                          Expanded(
                            child: Fx.col(
                              gap: 8,
                              children: [
                                Fx.box(style: FxStyle(height: 12, borderRadius: BorderRadius.circular(6), backgroundColor: isDark ? Colors.white10 : Colors.black12)),
                                Fx.box(style: FxStyle(width: 100, height: 12, borderRadius: BorderRadius.circular(6), backgroundColor: isDark ? Colors.white10 : Colors.black12)),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),

              // 4. 3D PERSPECTIVE Tilt
              _buildSection(
                title: "3D Perspective Tilt",
                description: "Cards that tilt and rotate in 3D space based on your touch location.",
                isDark: isDark,
                child: Center(
                  child: FxPerspective(
                    intensity: 0.3,
                    child: Fx.box(
                      style: FxStyle(
                        width: 200,
                        height: 120,
                        backgroundColor: isDark ? Colors.indigo[900]! : Colors.indigo[50]!,
                        borderRadius: BorderRadius.circular(16),
                        border: Border.all(color: Colors.indigo.withOpacity(0.3)),
                        alignment: Alignment.center,
                      ),
                      child: Fx.col(
                        gap: 8,
                        children: [
                          Icon(Icons.layers_rounded, color: isDark ? Colors.indigo[200] : Colors.indigo[800], size: 32),
                          Fx.text("3D Perspective").style(FxStyle(color: isDark ? Colors.indigo[200] : Colors.indigo[800], fontWeight: FontWeight.bold)),
                        ],
                      ),
                    ),
                  ),
                ),
              ),

              // 5. ELASTIC JELLY
              _buildSection(
                title: "Elastic Jelly Wobble",
                description: "Physical distortion that makes widgets feel like they are made of jelly.",
                isDark: isDark,
                child: Center(
                  child: FxJelly(
                    child: Fx.box(
                      style: FxStyle(
                        width: 100,
                        height: 100,
                        backgroundColor: Colors.pink,
                        borderRadius: BorderRadius.circular(50),
                        alignment: Alignment.center,
                      ),
                      child: const Icon(Icons.favorite, color: Colors.white, size: 40),
                    ),
                  ),
                ),
              ),

              // 6. ORGANIC WAVE FILL
              _buildSection(
                title: "Organic Wave Fill",
                description: "Realistic liquid dynamics for progress and loading states.",
                isDark: isDark,
                child: Center(
                  child: Fx.box(
                    style: FxStyle(
                      width: 120,
                      height: 120,
                      borderRadius: BorderRadius.circular(60),
                      border: Border.all(color: Fx.primary, width: 3),
                      backgroundColor: Colors.transparent,
                      clipBehavior: Clip.antiAlias,
                    ),
                    child: FxWave(
                      progress: 0.6,
                      color: Fx.primary.withOpacity(0.5),
                      waveHeight: 6,
                      child: Center(
                        child: Fx.text("60%").style(FxStyle(fontSize: 20, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black87)),
                      ),
                    ),
                  ),
                ),
              ),

              // 7. METABALL LIQUID BUTTON
              _buildSection(
                title: "Metaball Liquid Button",
                description: "Morphing geometry that makes buttons feel like splitting liquid drops.",
                isDark: isDark,
                child: Center(
                  child: FxLiquidButton(
                    child: Fx.box(
                      style: FxStyle(
                        width: 160,
                        padding: const EdgeInsets.all(16),
                        backgroundColor: Fx.primary,
                        borderRadius: BorderRadius.circular(30),
                        alignment: Alignment.center,
                      ),
                      child: Fx.text("Launch").style(const FxStyle(color: Colors.white, fontWeight: FontWeight.bold)),
                    ),
                  ),
                ),
              ),
              // 8. INTERACTIVE SPOTLIGHT
              _buildSection(
                title: "Interactive Spotlight",
                description: "A movie-screen reveal effect that follows the cursor.",
                isDark: isDark,
                child: FxSpotlight(
                  radius: 100,
                  overlayColor: isDark ? Colors.black : Colors.black87,
                  child: Fx.box(
                    style: const FxStyle(height: 150, alignment: Alignment.center),
                    child: Fx.text("TOP SECRET REVEAL").style(const FxStyle(fontSize: 24, fontWeight: FontWeight.w900, color: Colors.white)),
                  ),
                ),
              ),

              // 9. LIQUID GOOEY MERGE
              _buildSection(
                title: "Gooey Liquid Merge",
                description: "Objects that physically 'melt' into each other using metaball filters.",
                isDark: isDark,
                child: Center(
                  child: FxGooey(
                    intensity: 25,
                    children: [
                      // Moving Blobs
                      _AnimatedBlob(color: Fx.primary, offset: const Offset(-25, 0)),
                      _AnimatedBlob(color: Colors.purple, offset: const Offset(25, 0)),
                      _AnimatedBlob(color: Colors.blue, offset: const Offset(0, 0)),
                    ],
                  ),
                ),
              ),

              // 10. ORGANIC CONFETTI
              _buildSection(
                title: "Organic Confetti",
                description: "High-performance celebratory particles. Tap to celebrate!",
                isDark: isDark,
                child: Center(
                  child: FxConfetti(
                    count: 40,
                    child: Fx.box(
                      style: FxStyle(
                        padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
                        backgroundColor: Colors.amber,
                        borderRadius: BorderRadius.circular(12),
                      ),
                      child: Fx.text("TAP TO WIN!").style(const FxStyle(color: Colors.black, fontWeight: FontWeight.bold)),
                    ),
                  ),
                ),
              ),

              // 11. MESH GRADIENT (ULTRA-MODERN)
              _buildSection(
                title: "Mesh Gradient",
                description: "Fluid, organic background movement. The hallmark of elite 2024 design.",
                isDark: isDark,
                child: Fx.box(
                  style: FxStyle(
                    height: 200,
                    borderRadius: BorderRadius.circular(24),
                    clipBehavior: Clip.antiAlias,
                  ),
                  child: Stack(
                    children: [
                      const FxMeshGradient(
                        colors: [Colors.blue, Colors.purple, Colors.pink, Colors.orange],
                        speed: 0.5,
                      ),
                      Center(
                        child: Fx.text("FLUID MOTION").style(const FxStyle(
                          color: Colors.white,
                          fontSize: 28,
                          fontWeight: FontWeight.w900,
                          shadows: [BoxShadow(color: Colors.black26, blurRadius: 10)],
                        )),
                      ),
                    ],
                  ),
                ),
              ),

              // 12. ANIMATED GLOW BORDER
              _buildSection(
                title: "Animated Glow Border",
                description: "A premium light trail that travels around the perimeter of any widget.",
                isDark: isDark,
                child: Center(
                  child: FxAnimatedBorder(
                    color: Fx.primary,
                    width: 3,
                    borderRadius: 24,
                    child: Fx.box(
                      style: FxStyle(
                        width: 250,
                        padding: const EdgeInsets.all(24),
                        backgroundColor: isDark ? const Color(0xFF1E293B) : Colors.white,
                        borderRadius: BorderRadius.circular(24),
                      ),
                      child: Fx.col(
                        gap: 8,
                        children: [
                          Fx.text("Premium Card").style(const FxStyle(fontWeight: FontWeight.bold, fontSize: 18)),
                          Fx.text("Notice the glowing light traveling along the edge.").style(const FxStyle(fontSize: 14)),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      );
    });
  }

  Widget _buildSection({required String title, required String description, required Widget child, required bool isDark}) {
    return Fx.col(
      gap: 16,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Fx.col(
          gap: 4,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Fx.text(title).style(FxStyle(fontSize: 18, fontWeight: FontWeight.bold, color: isDark ? Colors.white : Colors.black87)),
            Fx.text(description).style(FxStyle(fontSize: 14, color: isDark ? Colors.white54 : Colors.black54)),
          ],
        ),
        Fx.box(
          style: FxStyle(
            padding: const EdgeInsets.all(32),
            backgroundColor: isDark ? const Color(0xFF1E293B) : Colors.white,
            borderRadius: BorderRadius.circular(24),
            border: Border.all(color: isDark ? Colors.white12 : Colors.black12),
          ),
          child: child,
        ),
      ],
    );
  }
}

class _AnimatedBlob extends StatefulWidget {
  final Color color;
  final Offset offset;

  const _AnimatedBlob({required this.color, required this.offset});

  @override
  State<_AnimatedBlob> createState() => _AnimatedBlobState();
}

class _AnimatedBlobState extends State<_AnimatedBlob> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 3),
    )..repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        final double dist = 30 * math.sin(_controller.value * 2 * math.pi);
        return Transform.translate(
          offset: widget.offset + Offset(dist, dist * 0.5),
          child: Container(
            width: 60,
            height: 60,
            decoration: BoxDecoration(
              color: widget.color,
              shape: BoxShape.circle,
            ),
          ),
        );
      },
    );
  }
}
3
likes
140
points
1.77k
downloads

Publisher

unverified uploader

Weekly Downloads

Core engine of the Fluxy framework including UI, state management, HTTP, and motion.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

args, crypto, flutter, flutter_secure_storage, flutter_timezone, http, path, path_provider, shared_preferences, timezone, vector_math

More

Packages that depend on fluxy