layout_flow 0.1.0 copy "layout_flow: ^0.1.0" to clipboard
layout_flow: ^0.1.0 copied to clipboard

A constraint-driven adaptive layout system for Flutter. Write UI once — let it flow across every screen.

example/lib/main.dart

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

void main() {
  runApp(
    const LayoutFlow(
      designSize: Size(375, 812),
      child: MyApp(),
    ),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'layout_flow Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF1A73E8)),
        useMaterial3: true,
      ),
      home: const DemoHome(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: FlowText(
          'layout_flow',
          style: FlowTextStyle.title(context).copyWith(
            fontWeight: FontWeight.w600,
          ),
        ),
      ),
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // ── Login Card demo ──────────────────────────────
            const _SectionLabel('Login Screen Demo'),
            const _LoginCard(),
            SizedBox(height: FlowSpacing.lg(context)),

            // ── Dashboard FlowRow demo ────────────────────────
            const _SectionLabel('Dashboard — FlowRow'),
            Padding(
              padding: FlowSpacing.symmetric(
                context,
                horizontal: 16,
                vertical: 0,
              ),
              child: FlowRow(
                gap: FlowSpacing.md(context),
                children: const [
                  Expanded(child: _StatCard(label: 'Revenue', value: '\$12,400')),
                  Expanded(child: _StatCard(label: 'Users', value: '3,821')),
                  Expanded(child: _StatCard(label: 'Sessions', value: '9,104')),
                ],
              ),
            ),
            SizedBox(height: FlowSpacing.lg(context)),

            // ── Typography scale demo ────────────────────────
            const _SectionLabel('Typography Scale'),
            const _TypeScaleDemo(),
            SizedBox(height: FlowSpacing.xl(context)),
          ],
        ),
      ),
    );
  }
}

// ── Login Card ──────────────────────────────────────────────────────────────

class _LoginCard extends StatelessWidget {
  const _LoginCard();

  @override
  Widget build(BuildContext context) {
    return FlowContainer(
      child: Card(
        elevation: 2,
        shape: RoundedRectangleBorder(
          borderRadius: FlowRadius.lg(context),
        ),
        child: FlowContainer(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              FlowText(
                'Welcome back',
                style: FlowTextStyle.headline(context),
              ),
              SizedBox(height: FlowSpacing.xs(context)),
              FlowText(
                'Sign in to your account to continue.',
                style: FlowTextStyle.bodySmall(context).copyWith(
                  color: Colors.grey[600],
                ),
              ),
              SizedBox(height: FlowSpacing.lg(context)),
              TextField(
                decoration: InputDecoration(
                  labelText: 'Email',
                  border: OutlineInputBorder(
                    borderRadius: FlowRadius.sm(context),
                  ),
                ),
              ),
              SizedBox(height: FlowSpacing.md(context)),
              TextField(
                obscureText: true,
                decoration: InputDecoration(
                  labelText: 'Password',
                  border: OutlineInputBorder(
                    borderRadius: FlowRadius.sm(context),
                  ),
                ),
              ),
              SizedBox(height: FlowSpacing.lg(context)),
              ElevatedButton(
                onPressed: () {},
                style: ElevatedButton.styleFrom(
                  padding: FlowSpacing.symmetric(context, vertical: 14),
                  shape: RoundedRectangleBorder(
                    borderRadius: FlowRadius.md(context),
                  ),
                ),
                child: FlowText(
                  'Sign In',
                  style: FlowTextStyle.body(context).copyWith(
                    fontWeight: FontWeight.w600,
                    color: Colors.white,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// ── Stat Card ───────────────────────────────────────────────────────────────

class _StatCard extends StatelessWidget {
  final String label;
  final String value;

  const _StatCard({required this.label, required this.value});

  @override
  Widget build(BuildContext context) {
    return Card(
      shape: RoundedRectangleBorder(borderRadius: FlowRadius.md(context)),
      child: FlowContainer(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            FlowText(
              value,
              style: FlowTextStyle.title(context).copyWith(
                fontWeight: FontWeight.w700,
                color: Theme.of(context).colorScheme.primary,
              ),
            ),
            SizedBox(height: FlowSpacing.xs(context)),
            FlowText(
              label,
              style: FlowTextStyle.label(context).copyWith(
                color: Colors.grey[600],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ── Type Scale Demo ─────────────────────────────────────────────────────────

class _TypeScaleDemo extends StatelessWidget {
  const _TypeScaleDemo();

  @override
  Widget build(BuildContext context) {
    return FlowContainer(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          FlowText('Display — 48sp', style: FlowTextStyle.display(context)),
          SizedBox(height: FlowSpacing.sm(context)),
          FlowText('Headline — 32sp', style: FlowTextStyle.headline(context)),
          SizedBox(height: FlowSpacing.sm(context)),
          FlowText('Title — 22sp', style: FlowTextStyle.title(context)),
          SizedBox(height: FlowSpacing.sm(context)),
          FlowText('Body — 16sp', style: FlowTextStyle.body(context)),
          SizedBox(height: FlowSpacing.sm(context)),
          FlowText('Body Small — 14sp', style: FlowTextStyle.bodySmall(context)),
          SizedBox(height: FlowSpacing.sm(context)),
          FlowText('Label — 12sp', style: FlowTextStyle.label(context)),
          SizedBox(height: FlowSpacing.sm(context)),
          FlowText('Micro — 10sp', style: FlowTextStyle.micro(context)),
        ],
      ),
    );
  }
}

// ── Section Label ───────────────────────────────────────────────────────────

class _SectionLabel extends StatelessWidget {
  final String text;
  const _SectionLabel(this.text);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: FlowSpacing.only(context, left: 16, top: 16, bottom: 8),
      child: FlowText(
        text.toUpperCase(),
        style: FlowTextStyle.label(context).copyWith(
          color: Colors.grey[500],
          letterSpacing: 1.2,
          fontWeight: FontWeight.w600,
        ),
      ),
    );
  }
}
0
likes
0
points
205
downloads

Publisher

unverified uploader

Weekly Downloads

A constraint-driven adaptive layout system for Flutter. Write UI once — let it flow across every screen.

Repository (GitHub)
View/report issues

Topics

#responsive #layout #adaptive #scaling

License

unknown (license)

Dependencies

flutter

More

Packages that depend on layout_flow