vize 1.0.3 copy "vize: ^1.0.3" to clipboard
vize: ^1.0.3 copied to clipboard

Vize is a modern, developer-friendly Flutter package for effortless responsive UIs that match your Figma designs perfectly.

Vize #

Vize is a modern, developer-friendly Flutter package for effortless responsive UIs that match your Figma designs perfectly.

It uses percentage-based sizing, smart scaling for padding and typography, adaptive grids, breakpoint overrides, handy extensions, and responsive builders, making it smooth across mobile, tablet and desktop views.

Perfect for clean, production-ready apps and scalable design systems. No more responsiveness headaches!

Pub Points Build Status pub package License: MIT

Features #

  • Percentage-Based Layouts: Intuitive width/height sizing
  • Figma Scaling: Direct scaling from your designs
  • Device Detection: Automatic mobile, tablet, desktop detection
  • Orientation Support: Portrait and landscape handling
  • Elegant Source: Clean, concise syntax with extensions
  • Lightweight: Minimal overhead, maximum performance
  • Flexible: Customizable breakpoints and scaling
  • User Font Scaling: App-wide text size preference via textScalar

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  vize: ^1.0.3

Then run:

flutter pub get

Quick Start #

1. Initialize Vize #

Initialize Vize once in your app, typically in your root widget:

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

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    // Initialize Vize
    Vize.init(context);

    return const MaterialApp(
      home: HomePage(),
    );
  }
}

2. Use Vize Helpers #

Now you can use Vize's responsive helpers throughout your app:

Container(
  width: w(50),      // 50% of screen width
  height: h(30),     // 30% of screen height
  padding: pa(16),   // Scaled 16px padding
  child: Text(
    'Hello Vize!',
    style: const TextStyle(fontSize: ts(18)), // Scaled 18px text
  ),
)

3. Use Extensions (Optional) #

For even cleaner code, use Vize's number extensions:

Container(
  width: 50.w,       // 50% of screen width
  height: 30.h,      // 30% of screen height
  padding: 16.pa,    // Scaled 16px padding
  child: Text(
    'Hello Vize!',
    style: const TextStyle(fontSize: 18.ts), // Scaled 18px text
  ),
)

Usage Examples #

Percentage-Based Layouts #

Perfect for flexible, responsive designs:

Column(
  children: [
    Container(
      width: w(100),  // Full width
      height: h(25),  // 25% of screen height
      color: Colors.blue,
    ),
    hs(2),  // 2% height spacing
    Container(
      width: w(80),   // 80% width
      height: h(50),  // 50% height
      color: Colors.green,
    ),
  ],
)

Figma Scaling #

Scale your designs directly from Figma:

// Using Vize.I
Container(
  width: Vize.I.sw(200),   // Scale 200px from Figma
  height: Vize.I.sh(100),  // Scale 100px from Figma
  padding: Vize.I.pa(16),  // Scale 16px padding
  decoration: BoxDecoration(
    borderRadius: BorderRadius.circular(Vize.I.r(12)), // Scale 12px radius
  ),
)

// Or with extensions
Container(
  width: 200.fws,
  height: 100.fhs,
  padding: 16.pa,
  decoration: BoxDecoration(
    borderRadius: BorderRadius.circular(12.r),
  ),
)

Device-Specific Layouts #

Build different layouts for different devices:

VizeBuilder(
  mobile: (context) => const MobileLayout(),
  tablet: (context) => const TabletLayout(),
  desktop: (context) => const DesktopLayout(),
)

Or use conditional logic:

@override
Widget build(BuildContext context) {
  if (isMobile) {
    return const MobileLayout();
  } else if (isTablet) {
    return const TabletLayout();
  } else {
    return const DesktopLayout();
  }
}

Responsive Padding #

Multiple ways to add responsive padding:

// All sides
Container(padding: pa(16))

// Symmetric
Container(padding: ps(h: 20, v: 10))

// Individual sides
Container(padding: po(l: 10, t: 20, r: 10, b: 20))

// With extensions
Container(padding: 16.pa)

Spacing #

Easy spacing between widgets:

Column(
  children: [
    const Text('Item 1'),
    hs(2),  // 2% height spacing
    const Text('Item 2'),
    hs(3),  // 3% height spacing
    const Text('Item 3'),
  ],
)

Row(
  children: [
    const Text('A'),
    ws(5),  // 5% width spacing
    const Text('B'),
  ],
)

Standard Spacing (8px Grid) #

Use the sp() helper for standard spacing:

Column(
  children: [
    const Text('Item 1'),
    SizedBox(height: sp()),    // 8px scaled
    const Text('Item 2'),
    SizedBox(height: sp(2)),   // 16px scaled
    const Text('Item 3'),
    SizedBox(height: sp(3)),   // 24px scaled
  ],
)

Adaptive Grid #

Create responsive grid layouts:

GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: adaptiveColumns(
      mobile: 2,
      tablet: 4,
      desktop: 6,
    ),
    crossAxisSpacing: sp(2),
    mainAxisSpacing: sp(2),
  ),
  itemBuilder: (context, index) => const Card(child: Text('Item')),
)

Adaptive Values #

Return different values based on device:

final fontSize = adaptiveValue(
  mobile: 14.0,
  tablet: 16.0,
  desktop: 18.0,
);

final columns = adaptiveValue(
  mobile: 1,
  tablet: 2,
  desktop: 3,
);

Device Detection #

Check device type anywhere in your code:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(
        isMobile ? 'Mobile' : isTablet ? 'Tablet' : 'Desktop'
      ),
    ),
    body: Column(
      children: [
        if (isMobile) const MobileWidget(),
        if (isTablet) const TabletWidget(),
        if (isDesktop) const DesktopWidget(),
      ],
    ),
  );
}

Using VizeLayout #

Get screen info with constraints:

VizeLayout(
  builder: (context, info) {
    return Column(
      children: [
        Text('Device: ${info.device}'),
        Text('Orientation: ${info.orientation}'),
        Text('Screen: ${info.vizeScreenSize}'),
        Text('Widget: ${info.vizeWidgetSize}'),
      ],
    );
  },
)

Custom Breakpoints #

Customize device detection breakpoints:

Vize.init(
  context,
  breakpoints: VizeBreakpoints(
    mobile: 600,   // Mobile < 600px
    tablet: 1024,   // Tablet 600-1024px, Desktop >= 1024px
  ),
);

Custom Figma Dimensions #

Match your Figma design dimensions:

Vize.init(
  context,
  figmaWidth: 390,
  figmaHeight: 844,
);

User Font Scaling #

Vize.init accepts a textScalar parameter — a multiplier applied on top of the responsive text scale returned by ts(). Use it to honour a user's font-size preference (small / medium / large) so that every .ts call across the entire app scales accordingly without wrapping the widget tree in an extra MediaQuery.

// Pass the user's chosen scale (e.g. 0.85, 1.0, or 1.15) on every build.
Vize.init(
  context,
  figmaWidth: 390,
  figmaHeight: 844,
  textScalar: userFontScale, // default: 1.0
);

Because Vize.init is called inside MaterialApp.builder on every rebuild, the new scalar takes effect immediately whenever the preference changes - no hot-restart required.

Core Methods #

Method Description Example
Vize.init(context) Initialize Vize Vize.init(context)
w(percent) Width percentage w(50) - 50% width
h(percent) Height percentage h(30) - 30% height
ts(size) Scale text size ts(16) - scaled 16px
r(value) Scale radius r(12) - scaled 12px
pa(value) Padding all sides pa(16) - scaled padding
ps({h, v}) Symmetric padding ps(h: 20, v: 10)
po({l, t, r, b}) Individual padding po(l: 10, t: 20)
ws(percent) Width spacing ws(5) - 5% width
hs(percent) Height spacing hs(2) - 2% height
sp([step]) Standard spacing sp(2) - 16px scaled

Vize.init Parameters #

Parameter Type Default Description
context BuildContext required Used to read MediaQuery screen dimensions
figmaWidth double? 390 The artboard width from your Figma design
figmaHeight double? 844 The artboard height from your Figma design
breakpoints VizeBreakpoints? VizeBreakpoints() Thresholds for mobile / tablet / desktop
textScalar double 1.0 Multiplier applied to all ts() values; use to honour a user font-size preference

Vize.I Methods #

Access these via Vize.I:

Method Description
Vize.I.wp(percent) Width percentage
Vize.I.hp(percent) Height percentage
Vize.I.sw(value) Scale width from Figma
Vize.I.sh(value) Scale height from Figma
Vize.I.ts(size) Scale text size (respects textScalar)
Vize.I.r(value) Scale radius
Vize.I.pa(value) Padding all sides
Vize.I.ps({h, v}) Symmetric padding
Vize.I.po({l, t, r, b}) Individual padding
Vize.I.isMobile Check if mobile
Vize.I.isTablet Check if tablet
Vize.I.isDesktop Check if desktop
Vize.I.device Get device type
Vize.I.textScalar Current text scale multiplier

Device Flags #

Flag Description
isMobile True if mobile device
isTablet True if tablet device
isDesktop True if desktop device

Extensions #

All extensions work on numbers:

50.w        // Width percentage
30.h        // Height percentage
18.ts       // Text size scaling (respects textScalar)
12.r        // Radius scaling
16.pa       // Padding all sides
5.ws        // Width spacing
2.hs        // Height spacing
100.fws     // Scale width from Figma
50.fhs      // Scale height from Figma

Widgets #

Widget Description
VizeBuilder Build different layouts per device
VizeWrapper Wrap with screen info
VizeLayout LayoutBuilder with VizeInfo

Models #

VizeInfo properties:

  • orientation - Current orientation
  • device - Device type (mobile/tablet/desktop)
  • vizeScreen - Full screen size
  • vizeWidget - Local widget size
  • isPortrait - Portrait orientation check
  • isLandscape - Landscape orientation check
  • isMobile - Mobile device check
  • isTablet - Tablet device check
  • isDesktop - Desktop device check

Default Breakpoints #

Device Width Range Default
Mobile < 600px < 600
Tablet 600-1024px 600-1024
Desktop >= 1024px >= 1024

Best Practices #

  1. Initialize Early

    Vize.init(context); // In MaterialApp builder or root widget
    
  2. Use Helpers for Layouts: Prefer percentage-based for flexible containers.

  3. Use Figma Scaling for Components: Ensures pixel-perfect UI.

  4. Combine Approaches: Percentages for overall layout, Figma scaling for UI elements.

  5. Use Extensions: Makes code much cleaner and readable.

  6. Test on Multiple Devices: Small phones, tablets, and desktops.

  7. Pass textScalar on every init: Since Vize.init is called in MaterialApp.builder, pass your font-size preference on every build so the scalar stays in sync with the user's choice.

Complete Example #

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, child) {
        Vize.init(
          context,
          figmaWidth: 390,
          figmaHeight: 844,
        );
        return child!;
      },
      home: const HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        padding: 20.pa,
        child: Column(
          children: [
            Container(
              width: 100.w,
              height: 20.h,
              decoration: BoxDecoration(
                color: Colors.blueAccent,
                borderRadius: BorderRadius.circular(12.r),
              ),
              child: Center(
                child: Text(
                  'Header',
                  style: TextStyle(fontSize: 22.ts),
                ),
              ),
            ),
            2.hs,
            GridView.builder(
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              itemCount: 4,
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: adaptiveColumns(
                  mobile: 1,
                  tablet: 2,
                  desktop: 4,
                ),
                mainAxisSpacing: sp(2),
                crossAxisSpacing: sp(2),
              ),
              itemBuilder: (context, i) => Container(
                color: Colors.grey[200],
                alignment: Alignment.center,
                child: Text('Item $i'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Contributing #

Contributions are very welcome! We'd love to see new features, bug fixes, documentation improvements, or anything that makes Vize better.

Local Development & Verification #

To ensure consistency, we've included a "pre-flight" script. Before pushing your changes or opening a PR, please run the checks to verify formatting, analysis, and tests:

On Windows (PowerShell):

./check.ps1

On Linux/macOS:

chmod +x check.sh # Only needed the first time
./check.sh

How to Contribute #

  1. Fork the repository
  2. Create a feature branch
    git checkout -b new-feature
    
  3. Commit your changes
    git commit -am 'Add new feature'
    
  4. Push to the branch
    git push origin new-feature
    
  5. Open a Pull Request on GitHub

Please make sure your code follows the existing style, includes tests where appropriate, and updates documentation if needed.

Thank you for helping improve Vize!

License #

This project is licensed under the MIT License - see the LICENSE file for details.

Support #

If you find Vize helpful, please give it a ⭐ on GitHub!

Contact #


Made with ❤️ for the Flutter community

4
likes
160
points
98
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Vize is a modern, developer-friendly Flutter package for effortless responsive UIs that match your Figma designs perfectly.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on vize