sixplace 0.0.2
sixplace: ^0.0.2 copied to clipboard
A mobile-first, responsive application foundation for Flutter.
Sixplace #
A mobile-first, responsive application foundation for Flutter.
Sixplace helps Flutter developers create adaptive mobile, tablet, desktop, and web interfaces with minimal code and without maintaining duplicate widget trees.
The responsive layout system is inspired by the simplicity of Bootstrap's 12-column grid while remaining designed specifically for Flutter.
Sixplace is under active development. The
SPLayoutfoundation is currently available. Additional application foundations will be introduced gradually through carefully designed and tested APIs.
Why Sixplace? #
Responsive Flutter interfaces often contain repeated widget trees:
if (isMobile) {
return MobilePage();
}
return DesktopPage();
This approach can duplicate:
- UI structure.
- State bindings.
- Loading and error states.
- Navigation behavior.
- Business logic.
- Maintenance effort.
Sixplace allows developers to define one mobile-first widget tree:
SPRow(
gap: 16,
children: [
SPCol(
md: 6,
child: firstCard,
),
SPCol(
md: 6,
child: secondCard,
),
],
)
The same widgets automatically become:
- One column on smaller screens.
- Two columns from the
mdbreakpoint. - Responsive without separate mobile and desktop pages.
Sixplace foundations #
Sixplace is designed around six coordinated application foundations:
| Foundation | Responsibility | Status |
|---|---|---|
SPLayout |
Responsive grids, containers, spacing, visibility, sizing and application shell | Available |
SPNetwork |
Requests, authentication, retry and error handling | Planned |
SPFeedback |
Toasts, alerts, loaders and messages | Planned |
SPTheme |
Colours, typography, spacing and design tokens | Planned |
SPForms |
Inputs, validation and submission handling | Planned |
SPStorage |
Preferences, secure storage and caching abstractions | Planned |
Only foundations marked as available should be considered part of the current public API.
Available layout features #
The current SPLayout foundation includes:
- Mobile-first responsive resolution.
- Bootstrap-inspired 12-column grid.
- Six default breakpoints.
- Custom breakpoint support.
- Responsive value inheritance.
- Viewport information through
context.sp. - Automatic responsive width and height.
- Fixed and fluid containers.
- Responsive container padding.
- Wrapping rows with static or responsive gaps.
- Responsive column spans.
- Responsive offsets.
- Responsive visual ordering.
- Responsive padding and margin.
- Breakpoint-based visibility.
- Platform-adaptive application bar.
- Responsive application scaffold.
- Permanent desktop drawers.
- Tablet navigation rails.
- Responsive bottom-navigation visibility.
- No duplicate responsive widget trees.
- No third-party runtime dependencies.
Installation #
Add Sixplace to your Flutter project:
flutter pub add sixplace
When using FVM:
fvm flutter pub add sixplace
Or add it manually:
dependencies:
sixplace: ^0.0.2
For local package development:
dependencies:
sixplace:
path: ../sixplace
Import the complete public API:
import 'package:sixplace/sixplace.dart';
Or import only the layout API:
import 'package:sixplace/layout.dart';
Breakpoints #
Sixplace uses familiar mobile-first breakpoint boundaries:
| Breakpoint | Minimum width | Effective range |
|---|---|---|
xs |
0 px | 0–575.99 px |
sm |
576 px | 576–767.99 px |
md |
768 px | 768–991.99 px |
lg |
992 px | 992–1199.99 px |
xl |
1200 px | 1200–1399.99 px |
xxl |
1400 px | 1400 px and above |
A responsive value continues applying until it is overridden at a larger breakpoint.
For example:
SPCol(
sm: 6,
lg: 4,
child: content,
)
This column occupies:
- 12 columns on
xs. - 6 columns on
smandmd. - 4 columns on
lg,xl, andxxl.
Public API overview #
| API | Responsibility |
|---|---|
SPBreakpoint |
Identifies the active responsive tier |
SPBreakpoints |
Defines and resolves breakpoint boundaries |
SPResponsiveValue<T> |
Stores a value that changes by breakpoint |
SPResponsive |
Provides viewport size, breakpoint and device-category helpers |
context.sp |
Convenient access to SPResponsive |
SPContainer |
Provides fixed or fluid responsive content containers |
SPRow |
Provides a wrapping 12-column responsive row |
SPCol |
Defines responsive span, offset and order |
SPResponsiveSizedBox |
Automatically resolves responsive width and height |
SPPadding |
Applies responsive padding |
SPMargin |
Applies responsive outer spacing |
SPVisibility |
Shows or hides content by breakpoint |
SPAppBar |
Provides a platform-adaptive application bar |
SPScaffold |
Provides a responsive application shell |
Resolution behavior #
Sixplace intentionally distinguishes between viewport-responsive and parent-responsive behavior.
| API | Resolution basis |
|---|---|
context.sp |
Viewport width |
SPResponsiveValue.resolveFrom(context) |
Viewport width |
SPResponsiveSizedBox |
Viewport width |
SPPadding |
Viewport width |
SPMargin |
Viewport width |
SPVisibility |
Viewport width |
SPScaffold |
Viewport width |
SPContainer |
Immediate parent width |
SPRow |
Immediate parent width |
SPCol inside an SPRow |
SPRow parent width |
This distinction allows nested grids to respond to their actual available space while screen-level behavior continues to use the viewport.
Usage #
Responsive two-column layout #
import 'package:flutter/material.dart';
import 'package:sixplace/sixplace.dart';
class DashboardPage extends StatelessWidget {
const DashboardPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const SPAppBar(
title: 'Dashboard',
),
body: SingleChildScrollView(
child: SPContainer.fluid(
padding: const EdgeInsets.all(16),
child: const SPRow(
gap: 16,
children: [
SPCol(
md: 6,
child: Card(
child: Padding(
padding: EdgeInsets.all(20),
child: Text('First card'),
),
),
),
SPCol(
md: 6,
child: Card(
child: Padding(
padding: EdgeInsets.all(20),
child: Text('Second card'),
),
),
),
],
),
),
),
);
}
}
This is conceptually equivalent to:
<div class="row g-3">
<div class="col-12 col-md-6">First card</div>
<div class="col-12 col-md-6">Second card</div>
</div>
Three-column responsive layout #
SPRow(
gap: 16,
children: [
SPCol(
sm: 6,
lg: 4,
child: firstCard,
),
SPCol(
sm: 6,
lg: 4,
child: secondCard,
),
SPCol(
sm: 6,
lg: 4,
child: thirdCard,
),
],
)
This produces:
- One column on extra-small screens.
- Two columns from
sm. - Three columns from
lg.
Responsive dashboard cards #
SPRow(
responsiveGap: const SPResponsiveValue<double>(
base: 8,
md: 12,
lg: 16,
),
children: [
SPCol(
span: 12,
sm: 6,
xl: 3,
child: firstCard,
),
SPCol(
span: 12,
sm: 6,
xl: 3,
child: secondCard,
),
SPCol(
span: 12,
sm: 6,
xl: 3,
child: thirdCard,
),
SPCol(
span: 12,
sm: 6,
xl: 3,
child: fourthCard,
),
],
)
Responsive values #
SPResponsiveValue<T> stores one value that can change across breakpoints:
const chartHeight = SPResponsiveValue<double?>(
base: null,
lg: 350,
);
Missing breakpoint values inherit from the nearest configured smaller breakpoint.
For example:
const spacing = SPResponsiveValue<double>(
base: 8,
md: 16,
xl: 24,
);
This resolves to:
8onxsandsm.16onmdandlg.24onxlandxxl.
Resolve a responsive value from context #
Use resolveFrom(context) when a normal Flutter property needs a responsive
value:
final borderRadius = const SPResponsiveValue<double>(
base: 8,
md: 12,
lg: 16,
).resolveFrom(context);
This avoids application-level MediaQuery boilerplate.
Responsive width and height #
Use SPResponsiveSizedBox when width or height changes by viewport
breakpoint:
SPResponsiveSizedBox(
height: const SPResponsiveValue<double?>(
base: null,
lg: 350,
),
child: StockOverviewChart(),
)
The example applies:
- Natural child height below
lg. - A fixed height of
350fromlgupward.
Responsive width and height can be combined:
SPResponsiveSizedBox(
width: const SPResponsiveValue<double?>(
base: double.infinity,
lg: 480,
),
height: const SPResponsiveValue<double?>(
base: 240,
lg: 350,
),
child: content,
)
Viewport information with context.sp #
Use context.sp for breakpoint information and non-layout responsive
decisions:
final responsive = context.sp;
responsive.width;
responsive.height;
responsive.breakpoint;
responsive.isMobile;
responsive.isTablet;
responsive.isDesktop;
responsive.isLargeDesktop;
Device-category behavior is:
isMobile:xsandsm.isTablet:md.isDesktop:lgand above.isLargeDesktop:xxland above.
isDesktop remains true on large desktops.
You can also perform explicit breakpoint checks:
final responsive = context.sp;
if (responsive.atLeast(SPBreakpoint.lg)) {
// Desktop-specific non-layout behavior.
}
if (responsive.below(SPBreakpoint.md)) {
// Mobile-specific non-layout behavior.
}
Prefer SPRow, SPCol, SPVisibility, and SPScaffold for layout changes.
Do not use context.sp to rebuild separate full mobile and desktop pages.
Responsive container padding #
Use responsivePadding when container padding changes according to its
available parent width:
SPContainer.fluid(
responsivePadding:
const SPResponsiveValue<EdgeInsetsGeometry>(
base: EdgeInsets.all(8),
md: EdgeInsets.all(12),
lg: EdgeInsets.all(16),
),
child: content,
)
The original static padding API remains available:
SPContainer.fluid(
padding: const EdgeInsets.all(16),
child: content,
)
When responsivePadding is provided, it takes precedence over padding.
Responsive row gaps #
Use a static gap:
SPRow(
gap: 16,
children: columns,
)
Or use a responsive gap:
SPRow(
responsiveGap: const SPResponsiveValue<double>(
base: 8,
md: 12,
lg: 16,
),
children: columns,
)
An explicit horizontalGap or verticalGap overrides responsiveGap for
that axis:
SPRow(
horizontalGap: 20,
responsiveGap: const SPResponsiveValue<double>(
base: 8,
lg: 16,
),
children: columns,
)
In this example:
- Horizontal gap always remains
20. - Vertical gap changes from
8to16atlg.
Responsive offset #
Offsets reserve empty grid columns before a column:
SPRow(
children: [
SPCol(
span: 12,
md: 8,
offsetMd: 2,
child: centeredContent,
),
],
)
From md, the content occupies eight columns with two empty columns before
it.
Responsive visual order #
Use responsive order to change visual position without duplicating widgets:
SPRow(
gap: 16,
children: [
SPCol(
span: 12,
lg: 8,
order: 2,
orderLg: 1,
child: mainContent,
),
SPCol(
span: 12,
lg: 4,
order: 1,
orderLg: 2,
child: sidebar,
),
],
)
The sidebar appears first on smaller screens and moves after the main content
from lg.
Responsive visibility #
Use SPVisibility to show or hide a specific interface element:
SPVisibility(
hiddenXs: true,
hiddenSm: true,
child: desktopAction,
)
Use a replacement when necessary:
SPVisibility(
hiddenLg: true,
hiddenXl: true,
hiddenXxl: true,
replacement: const Text('Desktop navigation'),
child: const Text('Mobile navigation'),
)
Avoid using visibility to maintain two complete versions of the same page.
Responsive padding #
SPPadding(
base: const EdgeInsets.all(8),
md: const EdgeInsets.all(16),
lg: const EdgeInsets.all(24),
child: content,
)
Responsive margin #
SPMargin(
base: const EdgeInsets.only(bottom: 8),
md: const EdgeInsets.only(bottom: 16),
child: content,
)
Platform-adaptive app bar #
Scaffold(
appBar: const SPAppBar(
title: 'Sixplace',
),
body: const YourPageContent(),
)
SPAppBar automatically provides:
- Material styling on Android, web, and desktop.
- iOS-style height, colors, typography, alignment, and separator on iOS.
- Dark-mode-aware colors.
- Automatic back-navigation handling.
- Optional drawer-button handling.
Override the automatic title alignment when necessary:
SPAppBar(
title: 'Sixplace',
centerTitle: false,
)
Display a drawer button explicitly:
SPAppBar(
title: 'Dashboard',
showDrawerIcon: true,
onDrawerPressed: openDrawer,
)
Responsive application shell #
SPScaffold can reuse the same navigation widgets across screen sizes:
SPScaffold(
appBar: const SPAppBar(
title: 'Dashboard',
),
drawer: const AppDrawer(),
permanentDrawerBreakpoint: SPBreakpoint.lg,
navigationRail: const AppNavigationRail(),
navigationRailBreakpoint: SPBreakpoint.md,
bottomNavigationBar: const AppBottomNavigation(),
hideBottomNavBreakpoint: SPBreakpoint.md,
body: const DashboardContent(),
)
Behavior:
- Mobile: fly-out drawer and bottom navigation.
- Tablet: navigation rail.
- Desktop: permanent drawer.
- The navigation rail is hidden when the permanent drawer becomes active.
- Bottom navigation is hidden from the configured breakpoint.
Real-world chart layout #
SPContainer.fluid(
responsivePadding:
const SPResponsiveValue<EdgeInsetsGeometry>(
base: EdgeInsets.all(8),
lg: EdgeInsets.all(16),
),
child: SPRow(
responsiveGap: const SPResponsiveValue<double>(
base: 12,
lg: 16,
),
children: [
SPCol(
span: 12,
lg: 6,
child: SPResponsiveSizedBox(
height: const SPResponsiveValue<double?>(
base: null,
lg: 350,
),
child: InventoryCompositionChart(),
),
),
SPCol(
span: 12,
lg: 6,
child: SPResponsiveSizedBox(
height: const SPResponsiveValue<double?>(
base: null,
lg: 350,
),
child: StockOverviewChart(),
),
),
],
),
)
This layout provides:
- One chart per row below
lg. - Two charts per row from
lg. - Responsive page padding.
- Responsive grid gaps.
- Automatic chart-height resolution.
- No direct
MediaQueryusage. - No duplicate mobile and desktop widget trees.
Custom breakpoints #
Create a custom breakpoint configuration:
const customBreakpoints = SPBreakpoints(
sm: 500,
md: 700,
lg: 900,
xl: 1100,
xxl: 1300,
);
Apply it to a grid:
SPRow(
breakpoints: customBreakpoints,
children: [
SPCol(
md: 6,
child: content,
),
],
)
Apply it to responsive viewport information:
final responsive = SPResponsive.of(
context,
breakpoints: customBreakpoints,
);
Apply it to responsive sizing:
SPResponsiveSizedBox(
breakpoints: customBreakpoints,
height: const SPResponsiveValue<double?>(
base: null,
lg: 350,
),
child: content,
)
Keep the same breakpoint configuration across related widgets to ensure predictable behavior.
Performance #
Sixplace uses:
LayoutBuilderwhere immediate parent width is required.MediaQuery.sizeOfwhere viewport size is required.- Immutable responsive configuration objects.
- Breakpoint inheritance without maintaining duplicated widget trees.
- Flutter-native layout widgets.
- No third-party runtime dependencies.
For best performance:
- Declare responsive values as
constwhere possible. - Avoid deeply nesting responsive wrappers unnecessarily.
- Keep large lists lazy using
ListView.builderor equivalent widgets. - Avoid creating separate full-page trees based on
context.sp. - Preserve stateful children instead of rebuilding equivalent mobile and desktop versions.
Migration from 0.0.1 #
Version 0.0.2 is backward-compatible with the 0.0.1 layout API.
Existing code remains valid:
SPContainer.fluid(
padding: const EdgeInsets.all(16),
child: SPRow(
gap: 16,
children: [
SPCol(
md: 6,
child: firstCard,
),
SPCol(
md: 6,
child: secondCard,
),
],
),
)
New APIs are optional:
final responsive = context.sp;
final value = responsiveValue.resolveFrom(context);
SPResponsiveSizedBox(
height: responsiveHeight,
child: content,
)
SPContainer.fluid(
responsivePadding: responsivePadding,
child: content,
)
SPRow(
responsiveGap: responsiveGap,
children: columns,
)
No existing SPRow, SPCol, SPContainer, SPResponsiveValue,
SPPadding, SPMargin, SPVisibility, SPAppBar, or SPScaffold usage
needs to be rewritten.
Design principles #
Sixplace follows these principles:
- Mobile-first responsive behavior.
- One widget tree for every screen size.
- Minimal and readable APIs.
- Predictable breakpoint inheritance.
- Flutter-first implementation.
- Zero unnecessary runtime dependencies.
- Tested public behavior.
- Backward-compatible APIs whenever possible.
- Clear separation between viewport and parent-width resolution.
- Reduced cognitive complexity instead of line-count optimization.
Development #
Format and validate the package before submitting changes:
fvm dart format .
fvm flutter analyze
fvm flutter test
Run the visual example:
cd example
fvm flutter pub get
fvm flutter run -d chrome
Resize the browser window to verify breakpoint transitions.
Before publishing:
fvm flutter pub publish --dry-run
Publish after the dry run completes successfully:
fvm flutter pub publish
Contributing #
Contributions are welcome.
You can contribute by:
- Reporting bugs.
- Suggesting focused features.
- Improving documentation.
- Adding tests.
- Fixing valid issues.
- Improving performance or accessibility.
- Submitting carefully scoped pull requests.
Recommended workflow:
- Fork the repository.
- Create a branch from
main. - Implement a focused change.
- Add or update tests.
- Run formatting, analysis, and tests.
- Submit a pull request with a clear description.
git checkout -b feature/short-description
fvm dart format .
fvm flutter analyze
fvm flutter test
For large features or architectural changes, open an issue before starting implementation.
Pull requests are reviewed for correctness, test coverage, API consistency, maintainability, backward compatibility, and alignment with the Sixplace architecture.
By submitting a contribution, you agree that your contribution may be distributed under the MIT License used by this project.
Bootstrap inspiration #
Sixplace is inspired by responsive grid concepts popularized by Bootstrap.
Sixplace is an independent Flutter implementation and is not affiliated with, sponsored by, or endorsed by Bootstrap or its maintainers. The Sixplace source code is implemented independently in Dart and Flutter.
License #
Sixplace is available under the MIT License.
Maintainer #
Innovate Nest Labs
Digital Solutions, Bangladesh