hux 0.1.2 copy "hux: ^0.1.2" to clipboard
hux: ^0.1.2 copied to clipboard

A modern Flutter UI package with beautiful, customizable components

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Hux UI Demo',
      theme: HuxTheme.lightTheme,
      darkTheme: HuxTheme.darkTheme,
      themeMode: ThemeMode.system,
      home: const MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  final _scrollController = ScrollController();
  bool _isLoading = false;

  // Theme state
  String _selectedTheme = 'white';
  Color get _currentPrimaryColor => HuxColors.getPresetColor(_selectedTheme);

  // Button size state
  HuxButtonSize _selectedButtonSize = HuxButtonSize.medium;

  // Global keys for each section
  final _buttonsKey = GlobalKey();
  final _textFieldsKey = GlobalKey();
  final _cardsKey = GlobalKey();
  final _chartsKey = GlobalKey();
  final _loadingKey = GlobalKey();

  // Navigation items
  late final List<NavigationItem> _navigationItems;

  @override
  void initState() {
    super.initState();
    _navigationItems = [
      NavigationItem(
        title: 'Buttons',
        icon: Icons.smart_button,
        key: _buttonsKey,
      ),
      NavigationItem(
        title: 'Text Fields',
        icon: Icons.text_fields,
        key: _textFieldsKey,
      ),
      NavigationItem(
        title: 'Cards',
        icon: Icons.credit_card,
        key: _cardsKey,
      ),
      NavigationItem(
        title: 'Charts',
        icon: Icons.analytics,
        key: _chartsKey,
      ),
      NavigationItem(
        title: 'Loading',
        icon: Icons.refresh,
        key: _loadingKey,
      ),
    ];
  }

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    _scrollController.dispose();
    super.dispose();
  }

  void _scrollToSection(GlobalKey key) {
    final context = key.currentContext;
    if (context != null) {
      Scrollable.ensureVisible(
        context,
        duration: const Duration(milliseconds: 800),
        curve: Curves.easeInOut,
      );
    }
  }

  void _toggleLoading() {
    setState(() {
      _isLoading = !_isLoading;
    });

    if (_isLoading) {
      Future.delayed(const Duration(seconds: 2), () {
        if (mounted) {
          setState(() {
            _isLoading = false;
          });
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          // Left Navigation Sidebar
          Container(
            width: 250,
            decoration: BoxDecoration(
              color: Theme.of(context).brightness == Brightness.dark
                  ? HuxColors.black90
                  : HuxColors.white,
              border: Border(
                right: BorderSide(
                  color: Theme.of(context).brightness == Brightness.dark
                      ? HuxColors.white20
                      : HuxColors.black20,
                ),
              ),
            ),
            child: Column(
              children: [
                // Header
                Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    border: Border(
                      bottom: BorderSide(
                        color: Theme.of(context).brightness == Brightness.dark
                            ? HuxColors.white20
                            : HuxColors.black20,
                      ),
                    ),
                  ),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'Hux UI',
                        style:
                            Theme.of(context).textTheme.headlineSmall?.copyWith(
                                  fontWeight: FontWeight.bold,
                                  color: Theme.of(context).brightness ==
                                          Brightness.dark
                                      ? HuxColors.white
                                      : HuxColors.black,
                                ),
                      ),
                      const SizedBox(height: 4),
                      Text(
                        'Component Library',
                        style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                              color: Theme.of(context).brightness ==
                                      Brightness.dark
                                  ? HuxColors.white60
                                  : HuxColors.black60,
                            ),
                      ),
                    ],
                  ),
                ),

                // Theme Selector
                Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    border: Border(
                      bottom: BorderSide(
                        color: Theme.of(context).brightness == Brightness.dark
                            ? HuxColors.white20
                            : HuxColors.black20,
                      ),
                    ),
                  ),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'Button Theme',
                        style:
                            Theme.of(context).textTheme.labelMedium?.copyWith(
                                  fontWeight: FontWeight.w600,
                                  color: Theme.of(context).brightness ==
                                          Brightness.dark
                                      ? HuxColors.white80
                                      : HuxColors.black80,
                                ),
                      ),
                      const SizedBox(height: 8),
                      Container(
                        width: double.infinity,
                        padding: const EdgeInsets.symmetric(
                            horizontal: 12, vertical: 8),
                        decoration: BoxDecoration(
                          color: Theme.of(context).brightness == Brightness.dark
                              ? HuxColors.black70
                              : HuxColors.white5,
                          borderRadius: BorderRadius.circular(8),
                          border: Border.all(
                            color:
                                Theme.of(context).brightness == Brightness.dark
                                    ? HuxColors.white20
                                    : HuxColors.black20,
                          ),
                        ),
                        child: DropdownButtonHideUnderline(
                          child: DropdownButton<String>(
                            value: _selectedTheme,
                            isExpanded: true,
                            dropdownColor:
                                Theme.of(context).brightness == Brightness.dark
                                    ? HuxColors.black80
                                    : HuxColors.white,
                            style: Theme.of(context)
                                .textTheme
                                .bodyMedium
                                ?.copyWith(
                                  color: Theme.of(context).brightness ==
                                          Brightness.dark
                                      ? HuxColors.white80
                                      : HuxColors.black80,
                                ),
                            icon: Icon(
                              Icons.keyboard_arrow_down,
                              color: Theme.of(context).brightness ==
                                      Brightness.dark
                                  ? HuxColors.white60
                                  : HuxColors.black60,
                            ),
                            onChanged: (String? newValue) {
                              if (newValue != null) {
                                setState(() {
                                  _selectedTheme = newValue;
                                });
                              }
                            },
                            items: HuxColors.availablePresetColors
                                .map<DropdownMenuItem<String>>(
                                    (String colorName) {
                              final color = HuxColors.getPresetColor(colorName);
                              return DropdownMenuItem<String>(
                                value: colorName,
                                child: Row(
                                  children: [
                                    Container(
                                      width: 16,
                                      height: 16,
                                      decoration: BoxDecoration(
                                        color: color,
                                        borderRadius: BorderRadius.circular(4),
                                        border: Border.all(
                                          color: Theme.of(context).brightness ==
                                                  Brightness.dark
                                              ? HuxColors.white30
                                              : HuxColors.black30,
                                          width: 0.5,
                                        ),
                                      ),
                                    ),
                                    const SizedBox(width: 8),
                                    Text(
                                      colorName[0].toUpperCase() +
                                          colorName.substring(1),
                                      style: Theme.of(context)
                                          .textTheme
                                          .bodyMedium
                                          ?.copyWith(
                                            color:
                                                Theme.of(context).brightness ==
                                                        Brightness.dark
                                                    ? HuxColors.white80
                                                    : HuxColors.black80,
                                          ),
                                    ),
                                  ],
                                ),
                              );
                            }).toList(),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),

                // Navigation Items
                Expanded(
                  child: ListView.builder(
                    padding: const EdgeInsets.symmetric(vertical: 16),
                    itemCount: _navigationItems.length,
                    itemBuilder: (context, index) {
                      final item = _navigationItems[index];
                      return Padding(
                        padding: const EdgeInsets.symmetric(
                            horizontal: 16, vertical: 4),
                        child: Material(
                          color: Colors.transparent,
                          child: InkWell(
                            borderRadius: BorderRadius.circular(8),
                            onTap: () => _scrollToSection(item.key),
                            child: Container(
                              padding: const EdgeInsets.symmetric(
                                  horizontal: 12, vertical: 12),
                              decoration: BoxDecoration(
                                borderRadius: BorderRadius.circular(8),
                              ),
                              child: Row(
                                children: [
                                  Icon(
                                    item.icon,
                                    size: 20,
                                    color: Theme.of(context).brightness ==
                                            Brightness.dark
                                        ? HuxColors.white70
                                        : HuxColors.black70,
                                  ),
                                  const SizedBox(width: 12),
                                  Text(
                                    item.title,
                                    style: Theme.of(context)
                                        .textTheme
                                        .bodyMedium
                                        ?.copyWith(
                                          fontWeight: FontWeight.w500,
                                          color: Theme.of(context).brightness ==
                                                  Brightness.dark
                                              ? HuxColors.white70
                                              : HuxColors.black70,
                                        ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      );
                    },
                  ),
                ),
              ],
            ),
          ),

          // Main Content Area
          Expanded(
            child: HuxLoadingOverlay(
              isLoading: _isLoading,
              message: 'Processing...',
              child: SingleChildScrollView(
                controller: _scrollController,
                padding: const EdgeInsets.all(32),
                child: Form(
                  key: _formKey,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      // Buttons Section
                      Container(
                        key: _buttonsKey,
                        child: HuxCard(
                          title: 'Buttons',
                          subtitle: 'Different button variants and sizes',
                          child: Column(
                            children: [
                              const SizedBox(height: 16),

                              // Size Selector Tabs
                              Container(
                                decoration: BoxDecoration(
                                  color: Theme.of(context).brightness ==
                                          Brightness.dark
                                      ? HuxColors.black70
                                      : HuxColors.white5,
                                  borderRadius: BorderRadius.circular(8),
                                  border: Border.all(
                                    color: Theme.of(context).brightness ==
                                            Brightness.dark
                                        ? HuxColors.white20
                                        : HuxColors.black20,
                                  ),
                                ),
                                child: Row(
                                  children: [
                                    Expanded(
                                      child: _buildSizeTab(
                                          'Small', HuxButtonSize.small),
                                    ),
                                    Expanded(
                                      child: _buildSizeTab(
                                          'Medium', HuxButtonSize.medium),
                                    ),
                                    Expanded(
                                      child: _buildSizeTab(
                                          'Large', HuxButtonSize.large),
                                    ),
                                  ],
                                ),
                              ),

                              const SizedBox(height: 20),

                              // Button Variants - Fixed Height Container
                              SizedBox(
                                height:
                                    48, // Fixed height to prevent layout shifts
                                child: Center(
                                  child: Wrap(
                                    spacing: 12,
                                    runSpacing: 12,
                                    children: [
                                      HuxButton(
                                        onPressed: () =>
                                            _showSnackBar('Primary pressed'),
                                        primaryColor: _currentPrimaryColor,
                                        size: _selectedButtonSize,
                                        child: const Text('Primary'),
                                      ),
                                      HuxButton(
                                        onPressed: () =>
                                            _showSnackBar('Secondary pressed'),
                                        variant: HuxButtonVariant.secondary,
                                        size: _selectedButtonSize,
                                        child: const Text('Secondary'),
                                      ),
                                      HuxButton(
                                        onPressed: () =>
                                            _showSnackBar('Outline pressed'),
                                        variant: HuxButtonVariant.outline,
                                        size: _selectedButtonSize,
                                        child: const Text('Outline'),
                                      ),
                                      HuxButton(
                                        onPressed: () =>
                                            _showSnackBar('Ghost pressed'),
                                        variant: HuxButtonVariant.ghost,
                                        size: _selectedButtonSize,
                                        child: const Text('Ghost'),
                                      ),
                                    ],
                                  ),
                                ),
                              ),

                              const SizedBox(height: 16),
                              const Divider(),
                              const SizedBox(height: 16),

                              // With Icon Example - Fixed Height Container
                              SizedBox(
                                height:
                                    48, // Fixed height to prevent layout shifts
                                child: Center(
                                  child: HuxButton(
                                    onPressed: _toggleLoading,
                                    primaryColor: _currentPrimaryColor,
                                    size: _selectedButtonSize,
                                    icon: FeatherIcons.upload,
                                    child: const Text('With Icon'),
                                  ),
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),

                      const SizedBox(height: 32),

                      // Text Fields Section
                      Container(
                        key: _textFieldsKey,
                        child: HuxCard(
                          title: 'Text Fields',
                          subtitle: 'Input components with validation',
                          child: Column(
                            children: [
                              const SizedBox(height: 16),
                              HuxTextField(
                                controller: _emailController,
                                label: 'Email',
                                hint: 'Enter your email address',
                                prefixIcon: const Icon(FeatherIcons.mail),
                                keyboardType: TextInputType.emailAddress,
                                validator: (value) {
                                  if (value == null || value.isEmpty) {
                                    return 'Please enter your email';
                                  }
                                  if (!value.contains('@')) {
                                    return 'Please enter a valid email';
                                  }
                                  return null;
                                },
                              ),
                              const SizedBox(height: 16),
                              HuxTextField(
                                controller: _passwordController,
                                label: 'Password',
                                hint: 'Enter your password',
                                prefixIcon: const Icon(FeatherIcons.lock),
                                suffixIcon: const Icon(FeatherIcons.eye),
                                obscureText: true,
                                validator: (value) {
                                  if (value == null || value.isEmpty) {
                                    return 'Please enter your password';
                                  }
                                  if (value.length < 6) {
                                    return 'Password must be at least 6 characters';
                                  }
                                  return null;
                                },
                              ),
                              const SizedBox(height: 16),
                              const Row(
                                children: [
                                  Expanded(
                                    child: HuxTextField(
                                      label: 'Small',
                                      size: HuxTextFieldSize.small,
                                      hint: 'Small text field',
                                    ),
                                  ),
                                  SizedBox(width: 8),
                                  Expanded(
                                    child: HuxTextField(
                                      label: 'Large',
                                      size: HuxTextFieldSize.large,
                                      hint: 'Large text field',
                                    ),
                                  ),
                                ],
                              ),
                            ],
                          ),
                        ),
                      ),

                      const SizedBox(height: 32),

                      // Cards Section
                      Container(
                        key: _cardsKey,
                        child: const HuxCard(
                          title: 'Cards',
                          subtitle:
                              'Container components for content organization',
                          child: Column(
                            children: [
                              SizedBox(height: 16),
                              Row(
                                children: [
                                  Expanded(
                                    child: HuxCard(
                                      title: 'Simple Card',
                                      child: Text(
                                          'This is a simple card with just a title and content.'),
                                    ),
                                  ),
                                  SizedBox(width: 16),
                                  Expanded(
                                    child: HuxCard(
                                      title: 'Card with Subtitle',
                                      subtitle:
                                          'This card has both title and subtitle',
                                      child: Text(
                                          'Cards can have optional subtitles for additional context.'),
                                    ),
                                  ),
                                ],
                              ),
                            ],
                          ),
                        ),
                      ),

                      const SizedBox(height: 32),

                      // Charts Section
                      Container(
                        key: _chartsKey,
                        child: HuxCard(
                          title: 'Charts',
                          subtitle: 'Data visualization with cristalyse',
                          child: Column(
                            children: [
                              const SizedBox(height: 16),

                              // Sample chart data
                              Row(
                                children: [
                                  Expanded(
                                    child: HuxChart(
                                      data: _getSampleLineData(),
                                      type: HuxChartType.line,
                                      xField: 'day',
                                      yField: 'calories',
                                      title: 'Daily Calories',
                                      subtitle: 'Calorie tracking over time',
                                      size: HuxChartSize.small,
                                      primaryColor: _currentPrimaryColor,
                                    ),
                                  ),
                                  const SizedBox(width: 16),
                                  Expanded(
                                    child: HuxChart(
                                      data: _getSampleBarData(),
                                      type: HuxChartType.bar,
                                      xField: 'product',
                                      yField: 'revenue',
                                      title: 'Product Revenue',
                                      subtitle: 'Revenue by product',
                                      size: HuxChartSize.small,
                                      primaryColor: _currentPrimaryColor,
                                    ),
                                  ),
                                ],
                              ),
                            ],
                          ),
                        ),
                      ),

                      const SizedBox(height: 32),

                      // Loading Section
                      Container(
                        key: _loadingKey,
                        child: HuxCard(
                          title: 'Loading Indicators',
                          subtitle: 'Different loading states and sizes',
                          child: Column(
                            children: [
                              const SizedBox(height: 16),
                              const Row(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceEvenly,
                                children: [
                                  Column(
                                    children: [
                                      HuxLoading(size: HuxLoadingSize.small),
                                      SizedBox(height: 8),
                                      Text('Small'),
                                    ],
                                  ),
                                  Column(
                                    children: [
                                      HuxLoading(size: HuxLoadingSize.medium),
                                      SizedBox(height: 8),
                                      Text('Medium'),
                                    ],
                                  ),
                                  Column(
                                    children: [
                                      HuxLoading(size: HuxLoadingSize.large),
                                      SizedBox(height: 8),
                                      Text('Large'),
                                    ],
                                  ),
                                  Column(
                                    children: [
                                      HuxLoading(
                                          size: HuxLoadingSize.extraLarge),
                                      SizedBox(height: 8),
                                      Text('XL'),
                                    ],
                                  ),
                                ],
                              ),
                              const SizedBox(height: 16),
                              HuxButton(
                                onPressed: _toggleLoading,
                                variant: HuxButtonVariant.outline,
                                child: Text(_isLoading
                                    ? 'Stop Loading'
                                    : 'Show Loading Overlay'),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  // Sample data generators for charts
  List<Map<String, dynamic>> _getSampleLineData() {
    return [
      {'day': 1, 'calories': 520, 'type': 'Daily Goal'},
      {'day': 2, 'calories': 480, 'type': 'Daily Goal'},
      {'day': 3, 'calories': 440, 'type': 'Daily Goal'},
      {'day': 4, 'calories': 580, 'type': 'Daily Goal'},
      {'day': 5, 'calories': 520, 'type': 'Daily Goal'},
      {'day': 6, 'calories': 610, 'type': 'Daily Goal'},
      {'day': 7, 'calories': 490, 'type': 'Daily Goal'},
      {'day': 8, 'calories': 550, 'type': 'Daily Goal'},
      {'day': 9, 'calories': 580, 'type': 'Daily Goal'},
      {'day': 10, 'calories': 470, 'type': 'Daily Goal'},
      {'day': 11, 'calories': 620, 'type': 'Daily Goal'},
      {'day': 12, 'calories': 540, 'type': 'Daily Goal'},
      {'day': 13, 'calories': 510, 'type': 'Daily Goal'},
      {'day': 14, 'calories': 590, 'type': 'Daily Goal'},
    ];
  }

  List<Map<String, dynamic>> _getSampleBarData() {
    return [
      {'product': 'Mobile', 'revenue': 450},
      {'product': 'Tablet', 'revenue': 320},
      {'product': 'Laptop', 'revenue': 580},
      {'product': 'Desktop', 'revenue': 290},
      {'product': 'Watch', 'revenue': 180},
    ];
  }

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        behavior: SnackBarBehavior.floating,
      ),
    );
  }

  Widget _buildSizeTab(String label, HuxButtonSize size) {
    final isSelected = _selectedButtonSize == size;

    return GestureDetector(
      onTap: () {
        setState(() {
          _selectedButtonSize = size;
        });
      },
      child: Container(
        padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
        decoration: BoxDecoration(
          color: isSelected
              ? (Theme.of(context).brightness == Brightness.dark
                  ? HuxColors.white20
                  : HuxColors.black10)
              : Colors.transparent,
          borderRadius: BorderRadius.circular(4),
        ),
        child: Center(
          child: Text(
            label,
            style: Theme.of(context).textTheme.bodySmall?.copyWith(
                  fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
                  color: isSelected
                      ? (Theme.of(context).brightness == Brightness.dark
                          ? HuxColors.white
                          : HuxColors.black)
                      : (Theme.of(context).brightness == Brightness.dark
                          ? HuxColors.white60
                          : HuxColors.black60),
                ),
          ),
        ),
      ),
    );
  }
}

class NavigationItem {
  final String title;
  final IconData icon;
  final GlobalKey key;

  NavigationItem({
    required this.title,
    required this.icon,
    required this.key,
  });
}
51
likes
0
points
732
downloads

Publisher

verified publisherthehuxdesign.com

Weekly Downloads

A modern Flutter UI package with beautiful, customizable components

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

cristalyse, flutter, flutter_feather_icons, google_fonts

More

Packages that depend on hux