nova_ui 1.0.2 copy "nova_ui: ^1.0.2" to clipboard
nova_ui: ^1.0.2 copied to clipboard

A modern Flutter UI framework with reusable widgets, design system components, and beautiful developer-friendly APIs.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: NovaTheme.light(),
      darkTheme: NovaTheme.dark(),
      themeMode: ThemeMode.system,
      title: 'Nova UI Demo',
      debugShowCheckedModeBanner: false,
      home: const LoginScreen(),
    );
  }
}

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

  @override
  State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  bool _loading = false;

  Future<void> _onLogin() async {
    if (!_formKey.currentState!.validate()) return;
    setState(() => _loading = true);
    await Future.delayed(const Duration(seconds: 2));
    setState(() => _loading = false);
  }

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

  @override
  Widget build(BuildContext context) {
    final primary = NovaColors.indigo;
    final isLight = !context.isDark;

    return Scaffold(
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: isLight
                ? [
              NovaColors.slate[50]!,
              NovaColors.indigo[50]!,
              NovaColors.slate[100]!,
            ]
                : [
              NovaColors.slate[900]!,
              const Color(0xFF1E1B4B),
              NovaColors.slate[900]!,
            ],
          ),
        ),
        child: SafeArea(
          child: SingleChildScrollView(
            padding: NovaSpacing.paddingPage.copyWith(top: NovaSpacing.xxxl),
            child: Form(
              key: _formKey,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // Logo
                  NovaContainer(
                    width: 52,
                    height: 52,
                    borderRadius: NovaRadius.lg,
                    gradient: LinearGradient(
                      colors: [primary[500]!, primary[400]!],
                    ),
                    child: const Center(
                      child: Icon(
                        Icons.blur_circular_rounded,
                        color: Colors.white,
                        size: 26,
                      ),
                    ),
                  ),

                  NovaSpacing.gapXl,

                  // Tag
                  NovaContainer(
                    padding: NovaSpacing.paddingHV(10, 4),
                    borderRadius: NovaRadius.sm,
                    color: primary[500]!.withValues(alpha: 0.15),
                    child: Text(
                      'NOVA UI',
                      style: TextStyle(
                        color: primary[300],
                        fontSize: 11,
                        fontWeight: FontWeight.w700,
                        letterSpacing: 1,
                      ),
                    ),
                  ),

                  NovaSpacing.gapSm,

                  Text(
                    'Welcome back',
                    style: TextStyle(
                      color: context.novaTextPrimary,
                      fontSize: 28,
                      fontWeight: FontWeight.w700,
                      letterSpacing: -0.5,
                    ),
                  ),

                  const SizedBox(height: 6),

                  Text(
                    'Sign in to continue',
                    style: TextStyle(
                      color: context.novaTextSecondary,
                      fontSize: 15,
                    ),
                  ),

                  NovaSpacing.gapXl,

                  // Email
                  NovaTextField(
                    controller: _emailController,
                    label: 'Email',
                    hintText: 'you@example.com',
                    prefixIcon: const Icon(Icons.mail_outline_rounded),
                    keyboardType: TextInputType.emailAddress,
                    textInputAction: TextInputAction.next,
                    validator: (v) =>
                    v == null || !v.contains('@')
                        ? 'Valid email required'
                        : null,
                  ),

                  NovaSpacing.gapMd,

                  // Password
                  NovaTextField(
                    controller: _passwordController,
                    label: 'Password',
                    prefixIcon: const Icon(Icons.lock_outline_rounded),
                    obscureText: true,
                    textInputAction: TextInputAction.done,
                    onFieldSubmitted: (_) => _onLogin(),
                    validator: (v) =>
                    v == null || v.length < 6
                        ? 'Min 6 characters'
                        : null,
                  ),

                  // Forgot password
                  Align(
                    alignment: Alignment.centerRight,
                    child: TextButton(
                      onPressed: () {},
                      child: Text(
                        'Forgot password?',
                        style: TextStyle(color: context.novaPrimary),
                      ),
                    ),
                  ),

                  // Login button
                  NovaButton(
                    text: 'Login',
                    loading: _loading,
                    onPressed: _onLogin,
                    backgroundColor: primary[500],
                  ),

                  NovaSpacing.gapLg,

                  // Divider
                  Row(
                    children: [
                      const Expanded(
                        child: Divider(color: Color(0x1FFFFFFF)),
                      ),
                      Padding(
                        padding: NovaSpacing.paddingH(12),
                        child: Text(
                          'or continue with',
                          style: TextStyle(
                            color: context.novaTextSecondary
                                .withValues(alpha: 0.5),
                            fontSize: 13,
                          ),
                        ),
                      ),
                      const Expanded(
                        child: Divider(color: Color(0x1FFFFFFF)),
                      ),
                    ],
                  ),

                  NovaSpacing.gapMd,

                  // Google button
                  NovaButton(
                    text: 'Continue with Google',
                    variant: NovaButtonVariant.outlined,
                    icon: const Icon(Icons.g_mobiledata_rounded, size: 22),
                    onPressed: () {},
                    foregroundColor: context.novaTextSecondary,
                  ),

                  NovaSpacing.gapXl,

                  // Sign up link
                  Center(
                    child: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Text(
                          "Don't have an account? ",
                          style: TextStyle(color: context.novaTextSecondary),
                        ),
                        GestureDetector(
                          onTap: () {},
                          child: Text(
                            'Sign up',
                            style: TextStyle(
                              color: context.novaPrimary,
                              fontWeight: FontWeight.w600,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),

                  NovaSpacing.gapXl,

                  // ── Widget Showcase ───────────────────────────────

                  Divider(
                    color: context.novaTextSecondary.withValues(alpha: 0.15),
                  ),

                  NovaSpacing.gapMd,

                  Text(
                    'Widget Showcase',
                    style: TextStyle(
                      color: context.novaTextSecondary,
                      fontSize: 11,
                      fontWeight: FontWeight.w600,
                      letterSpacing: 1,
                    ),
                  ),

                  NovaSpacing.gapMd,

                  // ── NovaLoader ────────────────────────────────────
                  NovaCard(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'NovaLoader',
                          style: TextStyle(
                            color: context.novaTextPrimary,
                            fontWeight: FontWeight.w600,
                            fontSize: 13,
                          ),
                        ),
                        NovaSpacing.gapMd,
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceAround,
                          children: [
                            // Circular
                            Column(
                              children: [
                                NovaLoader(color: primary[500]),
                                NovaSpacing.gapSm,
                                Text(
                                  'circular',
                                  style: TextStyle(
                                    color: context.novaTextSecondary,
                                    fontSize: 11,
                                  ),
                                ),
                              ],
                            ),
                            // Dots
                            Column(
                              children: [
                                NovaLoader(
                                  type: NovaLoaderType.dots,
                                  color: primary[500],
                                  size: 28,
                                ),
                                NovaSpacing.gapSm,
                                Text(
                                  'dots',
                                  style: TextStyle(
                                    color: context.novaTextSecondary,
                                    fontSize: 11,
                                  ),
                                ),
                              ],
                            ),
                            // Linear
                            Column(
                              children: [
                                NovaLoader(
                                  type: NovaLoaderType.linear,
                                  color: primary[500],
                                  width: 80,
                                ),
                                NovaSpacing.gapSm,
                                Text(
                                  'linear',
                                  style: TextStyle(
                                    color: context.novaTextSecondary,
                                    fontSize: 11,
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),

                  NovaSpacing.gapMd,

                  // ── NovaDialog ────────────────────────────────────
                  NovaCard(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'NovaDialog',
                          style: TextStyle(
                            color: context.novaTextPrimary,
                            fontWeight: FontWeight.w600,
                            fontSize: 13,
                          ),
                        ),
                        NovaSpacing.gapMd,
                        Row(
                          children: [
                            Expanded(
                              child: NovaButton(
                                text: 'Success',
                                height: 40,
                                backgroundColor: const Color(0xFF22C55E),
                                onPressed: () => NovaDialog.show(
                                  context: context,
                                  title: 'Profile Saved',
                                  message:
                                  'Your changes have been saved successfully.',
                                  type: NovaDialogType.success,
                                ),
                              ),
                            ),
                            NovaSpacing.gapSmH,
                            Expanded(
                              child: NovaButton(
                                text: 'Warning',
                                height: 40,
                                backgroundColor: const Color(0xFFF59E0B),
                                onPressed: () => NovaDialog.show(
                                  context: context,
                                  title: 'Log Out?',
                                  message:
                                  'This will log you out of all devices.',
                                  type: NovaDialogType.warning,
                                  confirmText: 'Logout',
                                  cancelText: 'Cancel',
                                ),
                              ),
                            ),
                            NovaSpacing.gapSmH,
                            Expanded(
                              child: NovaButton(
                                text: 'Danger',
                                height: 40,
                                backgroundColor:
                                Theme.of(context).colorScheme.error,
                                onPressed: () => NovaDialog.show(
                                  context: context,
                                  title: 'Delete Account?',
                                  message:
                                  'This action cannot be undone.',
                                  type: NovaDialogType.danger,
                                  confirmText: 'Delete',
                                  cancelText: 'Cancel',
                                  barrierDismissible: false,
                                ),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),

                  NovaSpacing.gapMd,

                  // ── NovaBadge ─────────────────────────────────────
                  NovaCard(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'NovaBadge',
                          style: TextStyle(
                            color: context.novaTextPrimary,
                            fontWeight: FontWeight.w600,
                            fontSize: 13,
                          ),
                        ),
                        NovaSpacing.gapMd,

                        // Status labels
                        Wrap(
                          spacing: 8,
                          runSpacing: 8,
                          children: [
                            NovaBadge(
                              label: 'Active',
                              color: NovaBadgeColor.success,
                            ),
                            NovaBadge(
                              label: 'Pending',
                              color: NovaBadgeColor.warning,
                              variant: NovaBadgeVariant.soft,
                            ),
                            NovaBadge(
                              label: 'Failed',
                              color: NovaBadgeColor.danger,
                              variant: NovaBadgeVariant.outlined,
                            ),
                            NovaBadge(
                              label: 'Draft',
                              color: NovaBadgeColor.neutral,
                              variant: NovaBadgeVariant.soft,
                            ),
                            NovaBadge(
                              label: 'New',
                              color: NovaBadgeColor.primary,
                            ),
                          ],
                        ),

                        NovaSpacing.gapMd,

                        // Dot + Count + Overlay
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceAround,
                          children: [
                            // Dot
                            Column(
                              children: [
                                NovaBadge(
                                  isDot: true,
                                  color: NovaBadgeColor.success,
                                ),
                                NovaSpacing.gapSm,
                                Text(
                                  'dot',
                                  style: TextStyle(
                                    color: context.novaTextSecondary,
                                    fontSize: 11,
                                  ),
                                ),
                              ],
                            ),
                            // Count
                            Column(
                              children: [
                                NovaBadge(
                                  count: 5,
                                  color: NovaBadgeColor.danger,
                                ),
                                NovaSpacing.gapSm,
                                Text(
                                  'count',
                                  style: TextStyle(
                                    color: context.novaTextSecondary,
                                    fontSize: 11,
                                  ),
                                ),
                              ],
                            ),
                            // Overlay on icon
                            Column(
                              children: [
                                NovaBadge(
                                  count: 12,
                                  color: NovaBadgeColor.danger,
                                  child: Icon(
                                    Icons.notifications_outlined,
                                    size: 28,
                                    color: context.novaTextPrimary,
                                  ),
                                ),
                                NovaSpacing.gapSm,
                                Text(
                                  'overlay',
                                  style: TextStyle(
                                    color: context.novaTextSecondary,
                                    fontSize: 11,
                                  ),
                                ),
                              ],
                            ),
                            // 99+ overflow
                            Column(
                              children: [
                                NovaBadge(
                                  count: 150,
                                  color: NovaBadgeColor.primary,
                                ),
                                NovaSpacing.gapSm,
                                Text(
                                  '99+',
                                  style: TextStyle(
                                    color: context.novaTextSecondary,
                                    fontSize: 11,
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),

                  NovaSpacing.gapXl,
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}
4
likes
0
points
264
downloads

Publisher

unverified uploader

Weekly Downloads

A modern Flutter UI framework with reusable widgets, design system components, and beautiful developer-friendly APIs.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on nova_ui