genai_components 4.1.0 copy "genai_components: ^4.1.0" to clipboard
genai_components: ^4.1.0 copied to clipboard

A comprehensive Flutter UI component library with theming, routing, state management, charts, and 30+ reusable widgets. Built for rapid app development with sensible defaults.

example/main.dart

// ignore_for_file: unused_local_variable
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:genai_components/genai_components.dart';

/// Example app showcasing CL Components usage.
///
/// Run with: `flutter run -d chrome`
void main() {
  runApp(const ExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      // Provide a custom theme (all colors are optional, defaults are sensible)
      create: (_) => CLThemeProvider(
        lightTheme: const LightModeTheme(
          primary: Color(0xFF6366F1),
          secondary: Color(0xFF4F46E5),
        ),
        darkTheme: const DarkModeTheme(
          primary: Color(0xFF818CF8),
          secondary: Color(0xFF6366F1),
        ),
      ),
      child: Builder(
        builder: (context) {
          return MaterialApp(
            title: 'CL Components Example',
            debugShowCheckedModeBanner: false,
            theme: ThemeData.light(useMaterial3: true),
            darkTheme: ThemeData.dark(useMaterial3: true),
            home: const ExampleHome(),
          );
        },
      ),
    );
  }
}

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

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

class _ExampleHomeState extends State<ExampleHome> {
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();

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

  @override
  Widget build(BuildContext context) {
    final theme = CLTheme.of(context);

    return Scaffold(
      backgroundColor: theme.primaryBackground,
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 800),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // ── Header ──────────────────────────────
                Text('CL Components', style: theme.heading1),
                const SizedBox(height: 4),
                Text('A comprehensive Flutter UI library', style: theme.subTitle),
                const SizedBox(height: 32),

                // ── Buttons ─────────────────────────────
                _SectionTitle('Buttons'),
                const SizedBox(height: 12),
                Wrap(
                  spacing: 12,
                  runSpacing: 12,
                  children: [
                    CLButton(
                      context: context,
                      text: 'Primary',
                      onTap: () {},
                      iconAlignment: IconAlignment.start,
                    ),
                    CLOutlineButton(
                      context: context,
                      text: 'Outline',
                      onTap: () {},
                      color: theme.primary,
                      iconAlignment: IconAlignment.start,
                    ),
                    CLSoftButton(
                      context: context,
                      text: 'Soft',
                      onTap: () {},
                      color: theme.primary,
                      iconAlignment: IconAlignment.start,
                    ),
                    CLGhostButton(
                      context: context,
                      text: 'Ghost',
                      onTap: () {},
                      color: theme.primary,
                      iconAlignment: IconAlignment.start,
                    ),
                  ],
                ),

                const SizedBox(height: 32),

                // ── Text Field ──────────────────────────
                _SectionTitle('Form'),
                const SizedBox(height: 12),
                CLTextField(
                  controller: _emailController,
                  labelText: 'Email',
                ),
                const SizedBox(height: 12),
                CLTextField(
                  controller: _passwordController,
                  labelText: 'Password',
                  isObscured: true,
                ),

                const SizedBox(height: 32),

                // ── Status Badges ───────────────────────
                _SectionTitle('Badges & Pills'),
                const SizedBox(height: 12),
                Wrap(
                  spacing: 8,
                  runSpacing: 8,
                  children: [
                    CLStatusBadge(label: 'Active', color: theme.success),
                    CLStatusBadge(label: 'Pending', color: theme.warning),
                    CLStatusBadge(label: 'Error', color: theme.danger),
                    CLPill(pillText: 'Flutter', pillColor: theme.primary),
                    CLPill(pillText: 'Dart', pillColor: theme.info),
                  ],
                ),

                const SizedBox(height: 32),

                // ── Alerts ──────────────────────────────
                _SectionTitle('Alerts'),
                const SizedBox(height: 12),
                CLAlert.border(
                  'Success',
                  'Operation completed successfully.',
                  backgroundColor: theme.success,
                ),
                const SizedBox(height: 8),
                CLAlert.border(
                  'Warning',
                  'Please review before proceeding.',
                  backgroundColor: theme.warning,
                ),
                const SizedBox(height: 8),
                CLAlert.border(
                  'Error',
                  'Something went wrong.',
                  backgroundColor: theme.danger,
                ),

                const SizedBox(height: 32),

                // ── Bar Chart ───────────────────────────
                _SectionTitle('Charts'),
                const SizedBox(height: 12),
                SizedBox(
                  height: 250,
                  child: CLBarChart<Map<String, dynamic>>(
                    data: const [
                      {'month': 'Jan', 'value': 30.0},
                      {'month': 'Feb', 'value': 45.0},
                      {'month': 'Mar', 'value': 28.0},
                      {'month': 'Apr', 'value': 60.0},
                      {'month': 'May', 'value': 52.0},
                      {'month': 'Jun', 'value': 40.0},
                    ],
                    xValueMapper: (item, _) => item['month'] as String,
                    yValueMapper: (item, _) => item['value'] as double,
                    showGrid: true,
                  ),
                ),

                const SizedBox(height: 32),

                // ── Theme Colors ────────────────────────
                _SectionTitle('Theme Colors'),
                const SizedBox(height: 12),
                Wrap(
                  spacing: 8,
                  runSpacing: 8,
                  children: [
                    _ColorChip('Primary', theme.primary),
                    _ColorChip('Secondary', theme.secondary),
                    _ColorChip('Success', theme.success),
                    _ColorChip('Warning', theme.warning),
                    _ColorChip('Danger', theme.danger),
                    _ColorChip('Info', theme.info),
                  ],
                ),

                const SizedBox(height: 48),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

// ── Helper widgets ──────────────────────────────────────────────────────

class _SectionTitle extends StatelessWidget {
  const _SectionTitle(this.text);

  final String text;

  @override
  Widget build(BuildContext context) {
    final theme = CLTheme.of(context);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(text, style: theme.heading5),
        const SizedBox(height: 4),
        Container(height: 2, width: 40, color: theme.primary),
      ],
    );
  }
}

class _ColorChip extends StatelessWidget {
  const _ColorChip(this.label, this.color);

  final String label;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
      decoration: BoxDecoration(
        color: color.withValues(alpha: 0.12),
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: color.withValues(alpha: 0.3)),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 16,
            height: 16,
            decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(4)),
          ),
          const SizedBox(width: 8),
          Text(label, style: TextStyle(color: color, fontWeight: FontWeight.w600, fontSize: 13)),
        ],
      ),
    );
  }
}