adaptive_kit 2.0.1
adaptive_kit: ^2.0.1 copied to clipboard
The Tailwind CSS of Flutter. Zero-config adaptive UI toolkit with responsive breakpoints, adaptive widgets, design tokens, animated transitions, slivers, and utility extensions.
The Tailwind CSS of Flutter.
Zero-config adaptive UI toolkit with responsive breakpoints, platform-aware widgets, design tokens, and powerful extensions.
Why adaptive_kit? #
Building responsive & adaptive UIs in Flutter is painful:
| Problem | Solution |
|---|---|
| MediaQuery boilerplate everywhere | context.responsive() returns values per breakpoint |
| No unified breakpoint system | 5-tier system: watch, mobile, tablet, desktop, tv |
| Manual Material vs Cupertino checks | SmartButton, SmartSwitch auto-adapt to platform |
| Magic numbers for spacing | Design tokens: SmartSpacing.md, SmartRadius.lg |
| No grid system like Bootstrap | SmartGrid + SmartCol with 12-column layout |
Before vs After #
// BEFORE: Verbose MediaQuery checks
final columns = MediaQuery.of(context).size.width > 900
? 4 : MediaQuery.of(context).size.width > 600 ? 2 : 1;
// AFTER: Declarative responsive values
final columns = context.responsive<int>(mobile: 1, tablet: 2, desktop: 4);
// BEFORE: Platform checks everywhere
if (Platform.isIOS) {
return CupertinoButton(child: Text('Save'), onPressed: () {});
}
return ElevatedButton(child: Text('Save'), onPressed: () {});
// AFTER: Auto platform adaptation
SmartButton(onPressed: () {}, child: Text('Save'))
// BEFORE: Magic numbers
Padding(padding: EdgeInsets.all(16.0), child: ...)
// AFTER: Design tokens
SmartPadding.all(SpacingSize.md, child: ...)
Features #
| Category | Features |
|---|---|
| Responsive | 5 breakpoints, context.responsive(), SmartLayout, ResponsiveBuilder |
| Grid System | 12-column SmartGrid, SmartCol with per-breakpoint spans |
| Adaptive Widgets | SmartButton, SmartSwitch, SmartDialog, SmartScaffold |
| Design Tokens | SmartSpacing, SmartTypography, SmartRadius, SmartTheme |
| Visibility | SmartVisible, MobileOnly, DesktopOnly, HideOnMobile |
| Extensions | Context, Widget, and Number extensions |
| Platform | Auto Material/Cupertino, platform detection |
| v2.0 NEW | SmartApp, SmartImage, SmartForm, SmartWrap, Animated Transitions, Slivers, Test Helpers |
Zero dependencies - Only Flutter SDK, fully tree-shakeable.
Quick Start #
1. Install #
dependencies:
adaptive_kit: ^2.0.0
2. Wrap Your App #
Option A: Zero-config with SmartApp (Recommended)
import 'package:adaptive_kit/adaptive_kit.dart';
void main() {
runApp(
SmartApp(
title: 'My App',
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
home: HomeScreen(),
),
);
}
Option B: With Router (go_router, auto_route, etc.)
SmartApp.router(
routerConfig: myGoRouter,
)
Option C: Manual SmartUi wrapper
SmartUi(
breakpoints: SmartBreakpoints.custom(
mobile: 320,
tablet: 768,
desktop: 1024,
),
child: MaterialApp(...),
)
3. Use It! #
// Responsive values
final columns = context.responsive<int>(mobile: 1, tablet: 2, desktop: 4);
// Breakpoint checks
if (context.isDesktop) {
return DesktopLayout();
}
// Design tokens
SmartPadding.all(SpacingSize.md, child: MyWidget())
Breakpoints #
Five-tier responsive system with smart defaults:
| Breakpoint | Min Width | Use Case |
|---|---|---|
watch |
0px | Wearables |
mobile |
300px | Phones |
tablet |
600px | Tablets |
desktop |
900px | Laptops/Desktops |
tv |
1200px | Large screens |
// Boolean checks
context.isMobile // true on mobile
context.isTablet // true on tablet
context.isDesktop // true on desktop
context.isTabletOrLarger // tablet, desktop, or tv
context.isMobileOrSmaller // watch or mobile
// Get current breakpoint
final bp = context.breakpoint; // SmartBreakpoint.tablet
Responsive Values #
Get different values based on the current breakpoint:
// Generic
final columns = context.responsive<int>(
mobile: 1,
tablet: 2,
desktop: 4,
);
// Convenience methods
final padding = context.responsiveDouble(mobile: 8, tablet: 16, desktop: 24);
final showSidebar = context.responsiveBool(mobile: false, desktop: true);
final edges = context.responsivePadding(
mobile: EdgeInsets.all(8),
tablet: EdgeInsets.all(16),
);
SmartLayout #
Switch entire layouts based on breakpoint with optional animated transitions:
// Basic usage
SmartLayout(
mobile: MobileHomeScreen(),
tablet: TabletHomeScreen(),
desktop: DesktopHomeScreen(),
)
// With animated transitions (NEW in v2.0)
SmartLayout(
transition: SmartTransition.fadeSlide,
transitionDuration: Duration(milliseconds: 300),
mobile: MobileHomeScreen(),
desktop: DesktopHomeScreen(),
)
// Available transitions: none, fade, fadeSlide, crossFade, scale
Responsive Grid #
Bootstrap-style 12-column grid:
SmartGrid(
columns: 12,
spacing: SmartSpacing.md,
children: [
SmartCol(
mobile: 12, // Full width on mobile
tablet: 6, // Half width on tablet
desktop: 4, // Third width on desktop
child: ProductCard(),
),
SmartCol(
mobile: 12,
tablet: 6,
desktop: 4,
child: ProductCard(),
),
SmartCol(
mobile: 12,
tablet: 6,
desktop: 4,
child: ProductCard(),
),
],
)
Adaptive Widgets #
Widgets that automatically use Material on Android and Cupertino on iOS/macOS:
SmartButton #
SmartButton(onPressed: () {}, child: Text('Default'))
SmartButton.filled(onPressed: () {}, child: Text('Filled'))
SmartButton.outlined(onPressed: () {}, child: Text('Outlined'))
SmartButton.text(onPressed: () {}, child: Text('Text'))
// Force specific style
SmartButton(forceCupertino: true, ...)
SmartSwitch, SmartCheckbox, SmartRadio #
SmartSwitch(
value: isDarkMode,
onChanged: (value) => setState(() => isDarkMode = value),
)
SmartCheckbox(value: isChecked, onChanged: (v) => ...)
SmartRadio<String>(
value: 'option1',
groupValue: selectedOption,
onChanged: (value) => ...,
)
SmartIndicator #
SmartIndicator() // Indeterminate
SmartIndicator(value: 0.5) // 50% progress
SmartLinearIndicator(value: 0.7) // Linear bar
SmartDialog #
// Alert dialog
showSmartDialog(
context: context,
title: 'Alert',
content: 'Something happened!',
actions: [
SmartDialogAction(
label: 'OK',
onPressed: () => Navigator.pop(context),
),
],
);
// Confirm dialog
final confirmed = await showSmartConfirmDialog(
context: context,
title: 'Delete Item?',
content: 'This cannot be undone.',
isDestructive: true,
);
SmartScaffold #
Adaptive navigation: bottom nav on mobile, rail on tablet, drawer on desktop.
SmartScaffold(
selectedIndex: _currentIndex,
onDestinationSelected: (index) => setState(() => _currentIndex = index),
destinations: [
SmartDestination(icon: Icon(Icons.home), label: 'Home'),
SmartDestination(icon: Icon(Icons.search), label: 'Search'),
SmartDestination(icon: Icon(Icons.settings), label: 'Settings'),
],
body: _pages[_currentIndex],
)
Design Tokens #
Spacing #
// Constants
SmartSpacing.xs // 4px
SmartSpacing.sm // 8px
SmartSpacing.md // 16px
SmartSpacing.lg // 24px
SmartSpacing.xl // 32px
SmartSpacing.xxl // 48px
// Padding widget
SmartPadding.all(SpacingSize.md, child: ...)
SmartPadding.symmetric(horizontal: SpacingSize.lg, child: ...)
// Gap widgets
VGap.md() // Vertical 16px gap
HGap.sm() // Horizontal 8px gap
Typography #
SmartText('Heading', style: TypographyStyle.headlineLarge)
SmartText('Body text', style: TypographyStyle.bodyMedium)
// Responsive typography
SmartText.responsive(
'Title',
mobile: TypographyStyle.titleSmall,
tablet: TypographyStyle.titleMedium,
desktop: TypographyStyle.titleLarge,
)
| Style | Size |
|---|---|
displayLarge |
57px |
displayMedium |
45px |
displaySmall |
36px |
headlineLarge |
32px |
headlineMedium |
28px |
headlineSmall |
24px |
titleLarge |
22px |
titleMedium |
16px |
titleSmall |
14px |
bodyLarge |
16px |
bodyMedium |
14px |
bodySmall |
12px |
labelLarge |
14px |
labelMedium |
12px |
labelSmall |
11px |
Border Radius #
SmartRadius.none // 0
SmartRadius.xs // 2px
SmartRadius.sm // 4px
SmartRadius.md // 8px
SmartRadius.lg // 12px
SmartRadius.xl // 16px
SmartRadius.xxl // 24px
SmartRadius.full // 9999px (circular)
Container(
decoration: BoxDecoration(borderRadius: SmartRadius.md),
)
Visibility #
Show/hide widgets by breakpoint:
// Show only on specific breakpoints
SmartVisible(
visibleOn: [SmartBreakpoint.desktop, SmartBreakpoint.tv],
child: Sidebar(),
)
// Hide on specific breakpoints
SmartVisible(
hiddenOn: [SmartBreakpoint.mobile, SmartBreakpoint.watch],
child: AdvancedOptions(),
)
// Convenience widgets
MobileOnly(child: BottomNav())
TabletOnly(child: SidePanel())
DesktopOnly(child: Sidebar())
HideOnMobile(child: DetailedView())
HideOnDesktop(child: MobileMenu())
// Widget extensions
myWidget.showOnMobile()
myWidget.hideOnDesktop()
Context Extensions #
// Screen dimensions
context.screenWidth
context.screenHeight
context.aspectRatio
context.devicePixelRatio
// Orientation
context.isPortrait
context.isLandscape
// Platform
context.platform // SmartPlatform enum
context.isIOS
context.isAndroid
context.isWeb
context.isMacOS
context.usesMaterial
context.usesCupertino
// Safe areas
context.safeAreaPadding
context.viewInsets
context.isKeyboardVisible
Widget Extensions #
// Padding
myWidget.paddedAll(16)
myWidget.paddedHorizontal(8)
myWidget.withPadding(SpacingSize.md)
// Layout
myWidget.centered()
myWidget.expanded()
myWidget.flexible()
myWidget.sized(width: 100, height: 50)
// Decoration
myWidget.clipped(borderRadius: SmartRadius.md)
myWidget.opacity(0.5)
// Gestures
myWidget.onTap(() => print('tapped'))
// Safe area & scrolling
myWidget.safeArea()
myWidget.scrollable()
Number Extensions #
// Spacing
16.horizontalSpace // SizedBox(width: 16)
16.verticalSpace // SizedBox(height: 16)
// EdgeInsets
16.paddingAll // EdgeInsets.all(16)
16.paddingHorizontal // EdgeInsets.symmetric(horizontal: 16)
// BorderRadius
8.borderRadius // BorderRadius.circular(8)
// Duration
300.ms // Duration(milliseconds: 300)
2.seconds // Duration(seconds: 2)
Comparison #
| Feature | adaptive_kit | sizer | flutter_screenutil | responsive_framework |
|---|---|---|---|---|
| Breakpoint system | 5-tier | No | No | 4-tier |
| Responsive values | context.responsive() |
No | No | Limited |
| 12-column grid | SmartGrid |
No | No | No |
| Adaptive widgets | 10+ widgets | No | No | No |
| Design tokens | Spacing, Typography, Radius | No | No | No |
| Platform detection | Full | No | No | No |
| Zero dependencies | Yes | Yes | Yes | No |
๐ Dashboard Preview #
The example app is a premium interactive playground with 8 demo pages:
cd example
flutter run -d chrome # Web
flutter run -d macos # macOS
8 demo pages:
- Home / Overview
- Breakpoints Demo
- Responsive Layout Demo
- Responsive Grid Demo
- Adaptive Widgets Demo
- Design Tokens Demo
- Visibility Demo
- Extensions Demo
v2.0 New Features #
SmartImage - Responsive Images #
SmartImage(
mobile: AssetImage('assets/hero_mobile.png'),
tablet: AssetImage('assets/hero_tablet.png'),
desktop: AssetImage('assets/hero_desktop.png'),
fit: BoxFit.cover,
)
// From asset paths
SmartImage.asset(
mobile: 'assets/mobile.png',
desktop: 'assets/desktop.png',
)
// From network URLs
SmartImage.network(
mobile: 'https://example.com/small.jpg',
desktop: 'https://example.com/large.jpg',
)
SmartForm - Responsive Forms #
SmartForm(
// Auto: 1 col mobile, 2 col tablet, 3 col desktop
children: [
SmartFormField(child: TextField(decoration: InputDecoration(labelText: 'Name'))),
SmartFormField(child: TextField(decoration: InputDecoration(labelText: 'Email'))),
SmartFormField(
span: 2, // Takes 2 columns
child: TextField(decoration: InputDecoration(labelText: 'Address')),
),
],
)
SmartWrap - Responsive Wrap #
SmartWrap(
mobileItemsPerRow: 2,
tabletItemsPerRow: 4,
desktopItemsPerRow: 6,
fillRow: true,
children: items.map((i) => ItemChip(i)).toList(),
)
SmartTheme - Breakpoint-Aware Tokens #
SmartTheme(
mobile: SmartThemeData.mobile,
tablet: SmartThemeData.tablet,
desktop: SmartThemeData.desktop,
child: MyApp(),
)
// Access in widgets
final theme = SmartTheme.of(context);
Text('Hello', style: TextStyle(fontSize: theme.baseFontSize));
SmartSliver Widgets #
CustomScrollView(
slivers: [
SmartSliverGrid(
mobileColumns: 2,
desktopColumns: 4,
children: items.map((i) => Card(child: i)).toList(),
),
SliverSmartPadding(
mobile: EdgeInsets.all(8),
desktop: EdgeInsets.all(24),
sliver: SliverList(...),
),
SliverSmartVisible(
visibleOn: [SmartBreakpoint.desktop],
sliver: SliverToBoxAdapter(child: DesktopBanner()),
),
],
)
New Context Extensions #
// Platform-adaptive values
final radius = context.adaptive<double>(material: 4.0, cupertino: 8.0);
// Show/hide helpers
context.showOnly(breakpoints: [SmartBreakpoint.desktop], child: Sidebar());
context.hideOn(breakpoints: [SmartBreakpoint.mobile], child: Options());
// Shorter responsive syntax
final cols = context.bp<int>(mobile: 1, tablet: 2, desktop: 4);
// Simple mobile/desktop checks
final padding = context.mobileOr<double>(mobile: 12, other: 24);
final maxWidth = context.desktopOr<double>(desktop: 1200, other: double.infinity);
Golden Test Helpers #
testWidgets('renders correctly on mobile', (tester) async {
await tester.pumpWidget(
createSmartTestWidget(
width: 375,
child: MyResponsiveWidget(),
),
);
expect(find.text('Mobile'), findsOneWidget);
});
// Test multiple breakpoints
for (final config in SmartTestConfigs.all) {
testWidgets('works on ${config.displayName}', (tester) async {
await tester.pumpWidget(
createSmartTestWidgetForConfig(config: config, child: MyWidget()),
);
});
}
Custom Breakpoints #
SmartUi(
breakpoints: SmartBreakpoints.custom(
watch: 0,
mobile: 320,
tablet: 768,
desktop: 1024,
tv: 1440,
),
child: MyApp(),
)
Contributing #
Contributions welcome! Please read our contributing guidelines.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License #
MIT License - see LICENSE for details.