virnavi_ui_bootstrap 0.0.1 copy "virnavi_ui_bootstrap: ^0.0.1" to clipboard
virnavi_ui_bootstrap: ^0.0.1 copied to clipboard

A Flutter UI bootstrap providing responsive Screen/ScreenLayout architecture, adaptive design scaling, SectionBox widgets, SVG image helpers, and async stream builders.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:virnavi_common_sdk/virnavi_common_sdk.dart';
import 'package:virnavi_ui_bootstrap/virnavi_ui_bootstrap.dart';

void main() {
  VirnaviUIBootstrap.init(
    mobileDesignSize: const Size(402, 874),
    tabletDesignSize: const Size(768, 1024),
  );
  runApp(const ExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'virnavi_ui_bootstrap',
      navigatorKey: ContextHolder.navigatorKey,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: const CounterScreen(),
    );
  }
}

// ── ScreenData ────────────────────────────────────────────────────────────────

class CounterData extends ScreenData<CounterScreen> {
  int count = 0;

  void increment() => setState(() => count++);
  void decrement() => setState(() => count--);
  void reset() => setState(() => count = 0);
}

// ── Screen ────────────────────────────────────────────────────────────────────

class CounterScreen extends Screen {
  const CounterScreen({super.key});

  @override
  CounterData createScreenData() => CounterData();

  CounterData get data => screenData as CounterData;

  @override
  Widget buildTemplate(BuildContext context, Widget child) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('virnavi_ui_bootstrap example'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: child,
    );
  }

  @override
  ScreenLayout buildMobilePortrait(BuildContext context) =>
      const _PortraitLayout();

  @override
  ScreenLayout? buildTabletPortrait(BuildContext context) =>
      const _TabletLayout();
}

// ── Mobile portrait ───────────────────────────────────────────────────────────

class _PortraitLayout extends ScreenLayout<CounterScreen> {
  const _PortraitLayout();

  @override
  Widget build(BuildContext context, CounterScreen screen) {
    return SingleChildScrollView(
      padding: EdgeInsets.all(16.r),
      child: Column(
        children: [
          _CounterSection(data: screen.data),
          SizedBox(height: 20.r),
          const _SectionBoxDemo(),
          SizedBox(height: 20.r),
          _AutoSizeTextDemo(),
        ],
      ),
    );
  }
}

// ── Tablet portrait (side-by-side) ────────────────────────────────────────────

class _TabletLayout extends ScreenLayout<CounterScreen> {
  const _TabletLayout();

  @override
  Widget build(BuildContext context, CounterScreen screen) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Expanded(
          child: SingleChildScrollView(
            padding: EdgeInsets.all(24.r),
            child: _CounterSection(data: screen.data),
          ),
        ),
        Expanded(
          child: SingleChildScrollView(
            padding: EdgeInsets.all(24.r),
            child: Column(
              children: [
                const _SectionBoxDemo(),
                SizedBox(height: 20.r),
                _AutoSizeTextDemo(),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

// ── Counter section ───────────────────────────────────────────────────────────

class _CounterSection extends StatelessWidget {
  final CounterData data;
  const _CounterSection({required this.data});

  @override
  Widget build(BuildContext context) {
    final scheme = Theme.of(context).colorScheme;
    return SectionBox(
      color: scheme.surface,
      borderColor: scheme.primary,
      borderRadius: 16,
      padding: EdgeInsets.symmetric(horizontal: 20.r, vertical: 24.r),
      child: Column(
        children: [
          AppAutoSizeText(
            'ScreenData counter',
            style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
          ),
          SizedBox(height: 12.r),
          AppAutoSizeText(
            '${data.count}',
            style: TextStyle(
              fontSize: 72.sp,
              fontWeight: FontWeight.bold,
              color: scheme.primary,
            ),
            maxLines: 1,
          ),
          SizedBox(height: 16.r),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              IconButton.filled(
                onPressed: data.decrement,
                icon: const Icon(Icons.remove),
              ),
              OutlinedButton(
                onPressed: data.reset,
                child: const Text('Reset'),
              ),
              IconButton.filled(
                onPressed: data.increment,
                icon: const Icon(Icons.add),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

// ── SectionBox demo ───────────────────────────────────────────────────────────

class _SectionBoxDemo extends StatelessWidget {
  const _SectionBoxDemo();

  @override
  Widget build(BuildContext context) {
    final scheme = Theme.of(context).colorScheme;
    final border = scheme.outlineVariant;
    const bg = Colors.white;
    const pad = EdgeInsets.symmetric(horizontal: 16, vertical: 12);

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: EdgeInsets.only(bottom: 8.r),
          child: AppAutoSizeText(
            'SectionBox family',
            style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w600),
          ),
        ),
        SectionBoxStart(
          borderColor: border,
          color: bg,
          borderRadius: 12,
          padding: pad,
          child: const _Row(Icons.person_outline, 'Profile'),
        ),
        SectionBoxMid(
          borderColor: border,
          color: bg,
          padding: pad,
          child: const _Row(Icons.notifications_outlined, 'Notifications'),
        ),
        SectionBoxMid(
          borderColor: border,
          color: bg,
          padding: pad,
          child: const _Row(Icons.lock_outline, 'Privacy'),
        ),
        SectionBoxEnd(
          borderColor: border,
          color: bg,
          borderRadius: 12,
          padding: pad,
          child: const _Row(Icons.help_outline, 'Help'),
        ),
      ],
    );
  }
}

class _Row extends StatelessWidget {
  final IconData icon;
  final String label;
  const _Row(this.icon, this.label);

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Icon(icon, size: 20),
        const SizedBox(width: 12),
        Expanded(child: Text(label)),
        const Icon(Icons.chevron_right, size: 18),
      ],
    );
  }
}

// ── AppAutoSizeText demo ──────────────────────────────────────────────────────

class _AutoSizeTextDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SectionBox(
      color: Theme.of(context).colorScheme.secondaryContainer,
      borderColor: Theme.of(context).colorScheme.secondary,
      borderRadius: 16,
      padding: EdgeInsets.all(16.r),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          AppAutoSizeText(
            'AppAutoSizeText',
            style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w600),
          ),
          SizedBox(height: 8.r),
          AppAutoSizeText(
            'This text shrinks to fit its container. '
            'Try resizing the window.',
            style: TextStyle(fontSize: 14.sp),
            maxLines: 2,
          ),
        ],
      ),
    );
  }
}
0
likes
160
points
94
downloads

Documentation

API reference

Publisher

verified publishervirnavi.com

Weekly Downloads

A Flutter UI bootstrap providing responsive Screen/ScreenLayout architecture, adaptive design scaling, SectionBox widgets, SVG image helpers, and async stream builders.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

auto_size_text, flutter, flutter_screenutil, flutter_svg, loader_overlay, vector_graphics, virnavi_common_sdk

More

Packages that depend on virnavi_ui_bootstrap