liquid_glacier 0.0.2 copy "liquid_glacier: ^0.0.2" to clipboard
liquid_glacier: ^0.0.2 copied to clipboard

Apple Liquid Glass design for Flutter Material widgets. Features translucent surfaces, dynamic blur effects, subtle reflections, and depth-based layering.

example/lib/main.dart

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

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

// ============================================================================
// ROOT APP WIDGET
// ============================================================================
// Holds the MaterialApp at the top level so ScaffoldMessenger is available
// to all descendants.
// ============================================================================

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

  @override
  State<LiquidGlassExampleApp> createState() => _LiquidGlassExampleAppState();
}

enum ThemeColor { purple, blue, teal, orange, pink }

class _LiquidGlassExampleAppState extends State<LiquidGlassExampleApp> {
  ThemeColor _selectedColor = ThemeColor.purple;

  Color get _seedColor {
    switch (_selectedColor) {
      case ThemeColor.purple:
        return Colors.deepPurple;
      case ThemeColor.blue:
        return Colors.blue;
      case ThemeColor.teal:
        return Colors.teal;
      case ThemeColor.orange:
        return Colors.deepOrange;
      case ThemeColor.pink:
        return Colors.pink;
    }
  }

  void _onColorChanged(ThemeColor color) {
    setState(() => _selectedColor = color);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: _seedColor,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: LiquidGlassTheme(
        data: const LiquidGlassThemeData(
          blurSigma: 25,
          opacity: 0.12,
          borderWidth: 1,
        ),
        child: LiquidGlassDemo(
          seedColor: _seedColor,
          selectedColor: _selectedColor,
          onColorChanged: _onColorChanged,
        ),
      ),
    );
  }
}

// ============================================================================
// DEMO CONTENT WIDGET
// ============================================================================
// The main demo content that showcases all Liquid Glass widgets.
// Now has access to ScaffoldMessenger via the context.
// ============================================================================

class LiquidGlassDemo extends StatefulWidget {
  const LiquidGlassDemo({
    required this.seedColor,
    required this.selectedColor,
    required this.onColorChanged,
    super.key,
  });

  final Color seedColor;
  final ThemeColor selectedColor;
  final ValueChanged<ThemeColor> onColorChanged;

  @override
  State<LiquidGlassDemo> createState() => _LiquidGlassDemoState();
}

class _LiquidGlassDemoState extends State<LiquidGlassDemo> {
  int _selectedIndex = 0;
  final TextEditingController _textController = TextEditingController();

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

  /// Shows a Liquid Glass SnackBar with the given message.
  void _showSnackBar(String message) {
    // Now context is below MaterialApp, so ScaffoldMessenger is available!
    showLiquidGlassSnackBar(
      context: context,
      message: message,
      type: LiquidGlassSnackBarType.info,
    );
  }

  Widget _buildSection(String title) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: TextStyle(
            fontSize: 14,
            fontWeight: FontWeight.w600,
            letterSpacing: 1.2,
            color: Colors.white.withValues(alpha: 0.6),
          ),
        ),
        const SizedBox(height: 12),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBody: true,
      backgroundColor: Colors.transparent,
      extendBodyBehindAppBar: true,
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: [
              widget.seedColor.withValues(
                alpha: 0.2,
              ), // Dynamic background based on selection
              const Color(0xFF16213e),
              const Color(0xFF0f3460),
              widget.seedColor.withValues(alpha: 0.4),
            ],
          ),
        ),
        child: SafeArea(
          child: SingleChildScrollView(
            padding: const EdgeInsets.all(20),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                const SizedBox(height: 20),
                // Title
                const Text(
                  'Liquid Glacier',
                  style: TextStyle(
                    fontSize: 32,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 8),
                Text(
                  'Apple-inspired glassmorphism for Flutter',
                  style: TextStyle(
                    fontSize: 16,
                    color: Colors.white.withValues(alpha: 0.7),
                  ),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 40),

                // Theme Selector (Radio Buttons)
                _buildSection('Theme Color'),
                LiquidGlassContainer(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 20,
                    vertical: 16,
                  ),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: ThemeColor.values.map((color) {
                      Color activeColor;
                      switch (color) {
                        case ThemeColor.purple:
                          activeColor = Colors.deepPurple;
                        case ThemeColor.blue:
                          activeColor = Colors.blue;
                        case ThemeColor.teal:
                          activeColor = Colors.teal;
                        case ThemeColor.orange:
                          activeColor = Colors.deepOrange;
                        case ThemeColor.pink:
                          activeColor = Colors.pink;
                      }
                      return LiquidGlassRadioButton<ThemeColor>(
                        value: color,
                        groupValue: widget.selectedColor,
                        activeColor: activeColor,
                        onChanged: (val) {
                          if (val != null) {
                            widget.onColorChanged(val);
                          }
                        },
                      );
                    }).toList(),
                  ),
                ),
                const SizedBox(height: 30),

                // Liquid Glass Card
                _buildSection('LiquidGlassCard'),
                LiquidGlassCard(
                  onTap: () => _showSnackBar('Card tapped!'),
                  child: const Padding(
                    padding: EdgeInsets.all(20),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Icon(
                          Icons.auto_awesome,
                          color: Colors.white,
                          size: 32,
                        ),
                        SizedBox(height: 12),
                        Text(
                          'Beautiful Glass Card',
                          style: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.w600,
                            color: Colors.white,
                          ),
                        ),
                        SizedBox(height: 8),
                        Text(
                          'Tap me! This card features blur, translucency, and subtle reflections.',
                          style: TextStyle(
                            fontSize: 14,
                            color: Colors.white70,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
                const SizedBox(height: 30),

                // Liquid Glass Buttons
                _buildSection('LiquidGlassButton'),
                Row(
                  children: [
                    Expanded(
                      child: LiquidGlassButton(
                        onPressed: () => _showSnackBar('Primary pressed!'),
                        child: const Text('Primary'),
                      ),
                    ),
                    const SizedBox(width: 12),
                    Expanded(
                      child: LiquidGlassButton(
                        onPressed: () => _showSnackBar('Secondary pressed!'),
                        tintColor: Colors.purple,
                        child: const Text('Tinted'),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 12),
                const LiquidGlassButton(
                  onPressed: null,
                  child: Text('Disabled Button'),
                ),
                const SizedBox(height: 30),

                // Liquid Glass TextField
                _buildSection('LiquidGlassTextField'),
                LiquidGlassTextField(
                  controller: _textController,
                  labelText: 'Email',
                  hintText: 'Enter your email',
                  prefixIcon: const Icon(
                    Icons.email_outlined,
                    color: Colors.white70,
                  ),
                ),
                const SizedBox(height: 12),
                const LiquidGlassTextField(
                  labelText: 'Password',
                  hintText: 'Enter your password',
                  obscureText: true,
                  prefixIcon: Icon(Icons.lock_outline, color: Colors.white70),
                ),
                const SizedBox(height: 30),

                // Liquid Glass Container
                _buildSection('LiquidGlassContainer'),
                LiquidGlassContainer(
                  padding: const EdgeInsets.all(20),
                  child: Row(
                    children: [
                      const Icon(Icons.info_outline, color: Colors.white70),
                      const SizedBox(width: 12),
                      Expanded(
                        child: Text(
                          'This is a custom glass container. Use it for any content!',
                          style: TextStyle(
                            color: Colors.white.withValues(alpha: 0.9),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 30),

                // Liquid Glass Chips
                _buildSection('LiquidGlassChip'),
                Wrap(
                  spacing: 8,
                  runSpacing: 8,
                  children: [
                    LiquidGlassChip(
                      label: const Text('Flutter'),
                      avatar: const Icon(Icons.flutter_dash, size: 18),
                      onTap: () => _showSnackBar('Flutter chip tapped!'),
                    ),
                    LiquidGlassChip(
                      label: const Text('Dart'),
                      avatar: const Icon(Icons.code, size: 18),
                      onTap: () => _showSnackBar('Dart chip tapped!'),
                    ),
                    const LiquidGlassChip(
                      label: Text('Design'),
                      avatar: Icon(Icons.palette, size: 18),
                      selected: true,
                    ),
                  ],
                ),
                const SizedBox(height: 30),

                // Liquid Glass SnackBar Showcase with Transitions
                _buildSection('LiquidGlassSnackBar'),
                LiquidGlassContainer(
                  padding: const EdgeInsets.all(16),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      Text(
                        'Snackbar types with smooth animated transitions:',
                        style: TextStyle(
                          color: Colors.white.withValues(alpha: 0.8),
                          fontSize: 13,
                        ),
                      ),
                      const SizedBox(height: 16),
                      // Row 1: Info (slide up) and Success (scale)
                      Row(
                        children: [
                          Expanded(
                            child: LiquidGlassButton(
                              onPressed: () => showLiquidGlassSnackBar(
                                context: context,
                                message: 'This is an info message.',
                                type: LiquidGlassSnackBarType.info,
                              ),
                              tintColor: const Color(0xFF007AFF),
                              child: const Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.info_outline, size: 18),
                                  SizedBox(width: 6),
                                  Text('Info'),
                                ],
                              ),
                            ),
                          ),
                          const SizedBox(width: 10),
                          Expanded(
                            child: LiquidGlassButton(
                              onPressed: () => showLiquidGlassSnackBar(
                                context: context,
                                message: 'Operation completed successfully!',
                                type: LiquidGlassSnackBarType.success,
                                transitionType: LiquidGlassTransitionType.scale,
                              ),
                              tintColor: const Color(0xFF34C759),
                              child: const Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.check_circle_outline, size: 18),
                                  SizedBox(width: 6),
                                  Text('Success'),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 10),
                      // Row 2: Warning (zoom) and Error (elastic)
                      Row(
                        children: [
                          Expanded(
                            child: LiquidGlassButton(
                              onPressed: () => showLiquidGlassSnackBar(
                                context: context,
                                message: 'Please check your settings.',
                                type: LiquidGlassSnackBarType.warning,
                                transitionType: LiquidGlassTransitionType.zoom,
                              ),
                              tintColor: const Color(0xFFFF9500),
                              child: const Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.warning_amber, size: 18),
                                  SizedBox(width: 6),
                                  Text('Warning'),
                                ],
                              ),
                            ),
                          ),
                          const SizedBox(width: 10),
                          Expanded(
                            child: LiquidGlassButton(
                              onPressed: () => showLiquidGlassSnackBar(
                                context: context,
                                message: 'Something went wrong!',
                                type: LiquidGlassSnackBarType.error,
                                transitionType:
                                    LiquidGlassTransitionType.elastic,
                                transitionDuration:
                                    const Duration(milliseconds: 500),
                              ),
                              tintColor: const Color(0xFFFF3B30),
                              child: const Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.error_outline, size: 18),
                                  SizedBox(width: 6),
                                  Text('Error'),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 10),
                      // Row 3: Top position
                      LiquidGlassButton(
                        onPressed: () => showLiquidGlassSnackBar(
                          context: context,
                          message: 'Notification from the top!',
                          type: LiquidGlassSnackBarType.info,
                          position: LiquidGlassSnackBarPosition.top,
                          transitionType: LiquidGlassTransitionType.slideDown,
                        ),
                        tintColor: Colors.purple,
                        child: const Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Icon(Icons.arrow_upward, size: 18),
                            SizedBox(width: 6),
                            Text('Top Position'),
                          ],
                        ),
                      ),
                      const SizedBox(height: 10),
                      // Row 4: With action and close button
                      LiquidGlassButton(
                        onPressed: () => showLiquidGlassSnackBar(
                          context: context,
                          message: 'File saved to Downloads folder.',
                          type: LiquidGlassSnackBarType.success,
                          transitionType: LiquidGlassTransitionType.scaleDown,
                          actionLabel: 'Open',
                          onActionPressed: () =>
                              _showSnackBar('Opening file...'),
                          showCloseIcon: true,
                        ),
                        child: const Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Icon(Icons.save_alt, size: 18),
                            SizedBox(width: 6),
                            Text('With Action & Close'),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 30),

                // Liquid Glass Dialog Showcase
                _buildSection('LiquidGlassDialog'),
                LiquidGlassContainer(
                  padding: const EdgeInsets.all(16),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      Text(
                        'Beautiful animated dialog transitions:',
                        style: TextStyle(
                          color: Colors.white.withValues(alpha: 0.8),
                          fontSize: 13,
                        ),
                      ),
                      const SizedBox(height: 16),
                      // Row 1: Scale Down (iOS) and Scale
                      Row(
                        children: [
                          Expanded(
                            child: LiquidGlassButton(
                              onPressed: () => showLiquidGlassDialog<void>(
                                context: context,
                                builder: (context) => LiquidGlassAlertDialog(
                                  icon: const Icon(
                                    Icons.star_rounded,
                                    color: Color(0xFFFFD60A),
                                  ),
                                  title: const Text('iOS Style'),
                                  content: const Text(
                                    'This dialog uses the signature iOS scale-down animation.',
                                  ),
                                  actions: [
                                    TextButton(
                                      onPressed: () => Navigator.pop(context),
                                      child: const Text(
                                        'Close',
                                        style: TextStyle(
                                          color: Color(0xFF007AFF),
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              tintColor: const Color(0xFF007AFF),
                              child: const Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.phone_iphone, size: 18),
                                  SizedBox(width: 6),
                                  Text('iOS Style'),
                                ],
                              ),
                            ),
                          ),
                          const SizedBox(width: 10),
                          Expanded(
                            child: LiquidGlassButton(
                              onPressed: () => showLiquidGlassDialog<void>(
                                context: context,
                                transitionType:
                                    LiquidGlassTransitionType.elastic,
                                transitionDuration:
                                    const Duration(milliseconds: 600),
                                builder: (context) => LiquidGlassAlertDialog(
                                  icon: const Icon(
                                    Icons.celebration,
                                    color: Color(0xFFFF9500),
                                  ),
                                  title: const Text('Bouncy!'),
                                  content: const Text(
                                    'This dialog has a playful elastic bounce animation.',
                                  ),
                                  actions: [
                                    TextButton(
                                      onPressed: () => Navigator.pop(context),
                                      child: const Text(
                                        'Awesome!',
                                        style: TextStyle(
                                          color: Color(0xFFFF9500),
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              tintColor: const Color(0xFFFF9500),
                              child: const Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.animation, size: 18),
                                  SizedBox(width: 6),
                                  Text('Elastic'),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 10),
                      // Row 2: Slide Up and Zoom
                      Row(
                        children: [
                          Expanded(
                            child: LiquidGlassButton(
                              onPressed: () => showLiquidGlassDialog<void>(
                                context: context,
                                transitionType:
                                    LiquidGlassTransitionType.slideUp,
                                builder: (context) => LiquidGlassAlertDialog(
                                  icon: const Icon(
                                    Icons.upload_rounded,
                                    color: Color(0xFF34C759),
                                  ),
                                  title: const Text('Slide Up'),
                                  content: const Text(
                                    'Perfect for bottom sheet-style dialogs.',
                                  ),
                                  actions: [
                                    TextButton(
                                      onPressed: () => Navigator.pop(context),
                                      child: const Text(
                                        'Got it!',
                                        style: TextStyle(
                                          color: Color(0xFF34C759),
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              tintColor: const Color(0xFF34C759),
                              child: const Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.arrow_upward, size: 18),
                                  SizedBox(width: 6),
                                  Text('Slide Up'),
                                ],
                              ),
                            ),
                          ),
                          const SizedBox(width: 10),
                          Expanded(
                            child: LiquidGlassButton(
                              onPressed: () => showLiquidGlassDialog<void>(
                                context: context,
                                transitionType: LiquidGlassTransitionType.zoom,
                                builder: (context) => LiquidGlassAlertDialog(
                                  icon: const Icon(
                                    Icons.zoom_in,
                                    color: Color(0xFFAF52DE),
                                  ),
                                  title: const Text('Zoom'),
                                  content: const Text(
                                    'A dramatic zoom entrance with subtle bounce.',
                                  ),
                                  actions: [
                                    TextButton(
                                      onPressed: () => Navigator.pop(context),
                                      child: const Text(
                                        'Nice!',
                                        style: TextStyle(
                                          color: Color(0xFFAF52DE),
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              tintColor: const Color(0xFFAF52DE),
                              child: const Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.zoom_in, size: 18),
                                  SizedBox(width: 6),
                                  Text('Zoom'),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 10),
                      // Confirmation dialog
                      LiquidGlassButton(
                        onPressed: () async {
                          final confirmed = await showLiquidGlassConfirmDialog(
                            context: context,
                            title: 'Delete Item',
                            message:
                                'Are you sure you want to delete this item? This action cannot be undone.',
                            confirmText: 'Delete',
                            isDestructive: true,
                          );
                          if ((confirmed ?? false) && context.mounted) {
                            await showLiquidGlassSnackBar(
                              context: context,
                              message: 'Item deleted successfully.',
                              type: LiquidGlassSnackBarType.success,
                            );
                          }
                        },
                        tintColor: const Color(0xFFFF3B30),
                        child: const Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Icon(Icons.delete_outline, size: 18),
                            SizedBox(width: 6),
                            Text('Confirmation Dialog'),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 100),
              ],
            ),
          ),
        ),
      ),
      floatingActionButton: LiquidGlassFAB(
        onPressed: () => _showSnackBar('FAB pressed!'),
        child: const Icon(Icons.add),
      ),
      bottomNavigationBar: LiquidGlassBottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: (index) => setState(() => _selectedIndex = index),
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home_outlined),
            activeIcon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search_outlined),
            activeIcon: Icon(Icons.search),
            label: 'Search',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.favorite_outline),
            activeIcon: Icon(Icons.favorite),
            label: 'Favorites',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person_outline),
            activeIcon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
      ),
    );
  }
}
1
likes
150
points
67
downloads

Publisher

unverified uploader

Weekly Downloads

Apple Liquid Glass design for Flutter Material widgets. Features translucent surfaces, dynamic blur effects, subtle reflections, and depth-based layering.

Repository (GitHub)
View/report issues

Topics

#ui #glassmorphism #design #material #apple

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on liquid_glacier