A responsive design toolkit for Flutter apps. It supports familiar width
breakpoints (xs to xxl), semantic layout sizes (compact, medium,
expanded), container-aware layouts, adaptive navigation, and responsive
grids.
Bootstrap Breakpoints Reference
The example catalog can be published to GitHub Pages at:
This repository includes a GitHub Actions workflow that builds example/ as a
Flutter web app and deploys it directly to GitHub Pages on pushes to master.
To use the workflow-based deploy, set the repository's Pages source to
GitHub Actions.
Add this to pubspec.yaml:
media_break_points: ^2.0.0Import it:
import 'package:media_break_points/media_break_points.dart';Initialize the package once if you want custom breakpoints or orientation-aware resolution:
void main() {
initMediaBreakPoints(
const MediaBreakPointsConfig(
considerOrientation: true,
),
);
runApp(const MyApp());
}The package is organized around a small core. Start with these categories first:
- Core engine: breakpoint data, responsive values, fluid interpolation, container queries, animated layout builders, visibility, and debugging.
- Core primitives: reusable spatial behaviors such as panes, sections, inspectors, action bars, forms, clusters, and responsive grids.
- Core shells and surfaces: the small set of higher-level layouts that form the
main package story, such as
AdaptiveScaffold,AdaptiveWorkspaceShell,AdaptiveDataView,AdaptiveFilterLayout,AdaptiveResultBrowser,AdaptiveDocumentView, andAdaptiveDiffView. - Showcase patterns: product-shaped compositions built from the core APIs. They stay available and documented, but they are examples of composition, not the canonical starting point for the package.
If you are adopting the library, prefer the core engine, primitives, and
surfaces first. The Showcase: sections further down the README are meant to
demonstrate how those building blocks can be combined.
The core package lives in:
import 'package:media_break_points/media_break_points.dart';Showcase patterns now live in a separate library:
import 'package:media_break_points/patterns.dart';Use valueFor when you want the original exact-match breakpoint behavior:
final padding = valueFor<EdgeInsets>(
context,
xs: const EdgeInsets.all(12),
md: const EdgeInsets.all(20),
defaultValue: const EdgeInsets.all(16),
);Use ResponsiveValue or context.responsive when you want cascading fallback
and semantic sizes:
final gap = context.responsive<double>(
compact: 12,
medium: 20,
expanded: 28,
);
final cardPadding = const ResponsiveValue<EdgeInsets>(
md: EdgeInsets.all(20),
expanded: EdgeInsets.all(28),
).resolve(context);Use FluidResponsiveValue or context.fluidResponsive when you want values to
interpolate between anchors instead of jumping at breakpoints:
final fontSize = context.fluidResponsive<double>(
lerp: (a, b, t) => lerpDouble(a, b, t) ?? a,
sm: 16,
md: 20,
xl: 28,
);BreakPointData gives you the resolved width, height, orientation, raw
breakpoint, and semantic size class in one object:
final data = context.breakPointData;
Text('Breakpoint: ${data.breakPoint.label}');
Text('Layout class: ${data.adaptiveSize.name}');BreakPointData also includes a semantic height class:
final data = context.breakPointData;
Text('Height class: ${data.adaptiveHeight.name}');Semantic sizes map like this:
xs,sm->AdaptiveSize.compactmd->AdaptiveSize.mediumlg,xl,xxl->AdaptiveSize.expanded
Height classes map like this:
< 560->AdaptiveHeight.compact560 - 799->AdaptiveHeight.medium>= 800->AdaptiveHeight.expanded
ResponsiveValue can now fall back to semantic height classes when width-based
rules are not provided:
final detail = context.responsive<String>(
heightCompact: 'Prioritize primary actions.',
heightExpanded: 'Show richer supporting context.',
);Width-specific and semantic width rules still resolve first. Height rules are best used when the same width needs different density based on available vertical space.
Use ResponsiveContainerBuilder when a widget should adapt to its own width
instead of the full screen width:
ResponsiveContainerBuilder(
builder: (context, data) {
return data.isCompact
? const Column(children: [Text('Stacked')])
: const Row(children: [Text('Split')]);
},
)You can also make ResponsiveLayoutBuilder use parent constraints:
ResponsiveLayoutBuilder(
useContainerConstraints: true,
xs: (context, _) => const MobilePane(),
md: (context, _) => const TabletPane(),
lg: (context, _) => const DesktopPane(),
)Use AnimatedResponsiveLayoutBuilder when the layout should transition smoothly
as the active breakpoint changes:
AnimatedResponsiveLayoutBuilder(
duration: const Duration(milliseconds: 250),
useContainerConstraints: true,
xs: (context, _) => const CompactPane(),
md: (context, _) => const SplitPane(),
)AdaptiveContainer gives you a slot-based alternative to the builder APIs.
It can resolve exact breakpoints, semantic sizes, and parent constraints:
AdaptiveContainer(
enableAnimation: true,
animationDuration: 250,
animateOnAdaptiveSize: true,
compact: const AdaptiveSlot(
builder: _buildCompactLayout,
),
medium: const AdaptiveSlot(
builder: _buildMediumLayout,
),
expanded: const AdaptiveSlot(
builder: _buildExpandedLayout,
),
)Use useContainerConstraints: true when a nested panel should switch from its
own width instead of the full screen.
AdaptiveCluster lets one child list switch between stacked, wrapped, and
inline arrangements:
AdaptiveCluster(
compactLayout: AdaptiveClusterLayout.column,
mediumLayout: AdaptiveClusterLayout.wrap,
expandedLayout: AdaptiveClusterLayout.row,
children: const [
_ClusterCard(title: 'Ship faster'),
_ClusterCard(title: 'Stay flexible'),
_ClusterCard(title: 'Scale cleanly'),
],
)This works well for feature cards, KPI strips, tool groups, and nested control clusters where a full grid would be too rigid.
AdaptivePane gives you a reusable split-view primitive. It stacks on compact
containers and switches to a split pane from AdaptiveSize.medium by default:
AdaptivePane(
primary: const ConversationList(),
secondary: const ConversationDetails(),
)You can keep it screen-based with useContainerConstraints: false, or change
the split threshold with splitAt. Use minimumSplitHeight when short-but-wide
surfaces should stay stacked instead of splitting.
AdaptiveActionBar keeps high-priority actions inline and moves the rest into
an overflow menu when space becomes tight:
AdaptiveActionBar(
actions: const [
AdaptiveActionBarAction(
icon: Icon(Icons.add),
label: 'Create',
priority: 3,
variant: AdaptiveActionVariant.filled,
pinToPrimaryRow: true,
),
AdaptiveActionBarAction(
icon: Icon(Icons.share_outlined),
label: 'Share',
priority: 2,
),
AdaptiveActionBarAction(
icon: Icon(Icons.archive_outlined),
label: 'Archive',
priority: 0,
variant: AdaptiveActionVariant.text,
),
],
)Use priority to decide which actions stay visible longer, and
pinToPrimaryRow for actions that should remain inline whenever possible.
AdaptiveForm groups form fields into reusable sections. Compact containers
render those sections in a stepper, while medium and expanded containers lay
them out as cards:
AdaptiveForm(
sections: const [
AdaptiveFormSection(
title: 'Workspace',
description: 'Naming, routing, and owner defaults.',
leading: Icon(Icons.tune_outlined),
children: [
_SettingField(label: 'Workspace name'),
_SettingField(label: 'Primary region'),
],
),
AdaptiveFormSection(
title: 'Notifications',
description: 'Where review activity should be sent.',
leading: Icon(Icons.notifications_outlined),
children: [
_SettingField(label: 'Release channel'),
_SettingField(label: 'Escalation contact'),
],
),
],
)Use sectionedAt to change when grouped cards take over, or
useContainerConstraints: false to resolve the form from the full screen width.
AdaptivePriorityLayout keeps primary content visible and collapses
supporting content into an expandable card on compact containers:
AdaptivePriorityLayout(
supportingTitle: 'Workspace summary',
supportingDescription: 'Pinned modules and review counts.',
supportingLeading: const Icon(Icons.insights_outlined),
minimumSplitHeight: AdaptiveHeight.medium,
primary: const WorkspaceCanvas(),
supporting: const WorkspaceSummary(),
)From AdaptiveSize.medium by default, the supporting surface docks beside the
primary content instead of collapsing below it. Use minimumSplitHeight when
short wide surfaces should keep the supporting region collapsed.
AdaptiveInspectorLayout is useful when a sidebar should stay docked on larger
surfaces but become a modal inspector on compact widths:
AdaptiveInspectorLayout(
inspectorTitle: 'Layout inspector',
inspectorDescription: 'Tune density and compare responsive states.',
inspectorLeading: const Icon(Icons.tune_outlined),
minimumDockedHeight: AdaptiveHeight.medium,
primary: const EditorCanvas(),
inspector: const InspectorPanel(),
)Use dockedAt to control when the inspector becomes inline, or
minimumDockedHeight to keep wide-but-short layouts modal. Use
useContainerConstraints: true to make nested inspectors resolve from their
parent width instead of the full screen.
AdaptiveWorkspaceShell packages navigation, action overflow, and inspector
behavior into one higher-level workspace primitive:
AdaptiveWorkspaceShell(
title: 'Workspace overview',
description: 'Coordinate shell chrome without rebuilding every screen.',
appBarTitle: 'Adaptive Workspace Shell',
destinations: const [
AdaptiveScaffoldDestination(
icon: Icon(Icons.space_dashboard_outlined),
selectedIcon: Icon(Icons.space_dashboard),
label: 'Overview',
),
AdaptiveScaffoldDestination(
icon: Icon(Icons.fact_check_outlined),
selectedIcon: Icon(Icons.fact_check),
label: 'Review',
),
],
selectedIndex: selectedIndex,
onSelectedIndexChanged: (index) => setState(() => selectedIndex = index),
actions: const [
AdaptiveActionBarAction(
icon: Icon(Icons.add),
label: 'Create flow',
priority: 4,
variant: AdaptiveActionVariant.filled,
pinToPrimaryRow: true,
),
AdaptiveActionBarAction(
icon: Icon(Icons.ios_share_outlined),
label: 'Share',
priority: 3,
variant: AdaptiveActionVariant.tonal,
),
],
inspectorTitle: 'Workspace inspector',
inspectorDescription: 'Track adaptive state and pinned modules.',
minimumRailHeight: AdaptiveHeight.medium,
minimumDrawerHeight: AdaptiveHeight.medium,
minimumInspectorDockedHeight: AdaptiveHeight.medium,
content: const WorkspaceCanvas(),
inspector: const InspectorPanel(),
)Use AdaptiveWorkspaceShell when several screens share the same navigation,
top-level actions, and supporting inspector behavior. The inner content still
stays free to compose grids, panes, forms, and container-aware layouts.
AdaptiveSections is useful for settings, preferences, and workspace subpages
that should keep related sections on one screen:
AdaptiveSections(
minimumSidebarHeight: AdaptiveHeight.medium,
navigationHeader: const Text('Workspace areas'),
sections: const [
AdaptiveSection(
label: 'Profile',
icon: Icon(Icons.person_outline),
description: 'Identity and ownership settings.',
child: ProfileSection(),
),
AdaptiveSection(
label: 'Notifications',
icon: Icon(Icons.notifications_outlined),
description: 'Delivery rules and digest cadence.',
child: NotificationSection(),
),
AdaptiveSection(
label: 'Appearance',
icon: Icon(Icons.palette_outlined),
description: 'Theme, density, and preview defaults.',
child: AppearanceSection(),
),
],
)Compact containers render a horizontal chip row above the active section.
Medium and expanded containers render a docked sidebar. Use
minimumSidebarHeight when wide-but-short surfaces should stay in compact mode,
and useContainerConstraints: true when nested cards should resolve from their
own width instead of the full screen.
AdaptiveDataView helps data-heavy screens move from stacked record cards into
tables without maintaining two unrelated UIs:
AdaptiveDataView<WorkspaceRecord>(
records: records,
minimumTableHeight: AdaptiveHeight.medium,
compactTitleBuilder: (context, record) => Text(record.name),
compactSubtitleBuilder: (context, record) => Text(record.team),
compactTrailingBuilder: (context, record) =>
StatusBadge(status: record.status),
columns: [
AdaptiveDataColumn(
label: 'Owner',
cellBuilder: (context, record) => Text(record.name),
),
AdaptiveDataColumn(
label: 'Team',
cellBuilder: (context, record) => Text(record.team),
),
AdaptiveDataColumn(
label: 'Status',
cellBuilder: (context, record) => StatusBadge(status: record.status),
),
AdaptiveDataColumn(
label: 'Throughput',
numeric: true,
cellBuilder: (context, record) => Text('${record.throughput}'),
),
],
)Compact containers render cards. Medium and expanded containers render a
scrollable DataTable. Use minimumTableHeight when wide-but-short layouts
should stay in card mode, and useContainerConstraints: true when nested
panels should resolve from their own width.
Import package:media_break_points/patterns.dart alongside the core library
when you want the higher-level example patterns below.
AdaptiveBoard helps workflow and kanban-style screens keep one lane model
that can stack vertically or spread into board columns:
AdaptiveBoard(
minimumBoardHeight: AdaptiveHeight.medium,
lanes: const [
AdaptiveBoardLane(
title: 'Queued',
description: 'Ready for the next adaptive pass.',
items: [
TaskCard(title: 'Refine dashboard density'),
TaskCard(title: 'Audit nested forms'),
],
footer: LaneActionButton(label: 'Create task'),
),
AdaptiveBoardLane(
title: 'Building',
description: 'In active implementation.',
items: [
TaskCard(title: 'Workspace shell follow-up'),
],
),
],
)Compact containers render vertically stacked lanes. Medium and expanded
containers render horizontally scrollable columns. Use minimumBoardHeight
when wide-but-short layouts should stay stacked, and useContainerConstraints: true when nested cards or panes should resolve from their own width.
AdaptiveTimeline helps roadmap and milestone screens move between stacked
milestone cards and a horizontal timeline without keeping two separate views:
AdaptiveTimeline(
minimumHorizontalHeight: AdaptiveHeight.medium,
entries: const [
AdaptiveTimelineEntry(
title: 'Prototype the adaptive core',
label: 'Q1',
description: 'Validate semantic breakpoints and fluid values.',
leading: Icon(Icons.flag_outlined),
trailing: StageBadge(label: 'Foundation'),
child: MilestoneCard(title: 'Key result'),
),
AdaptiveTimelineEntry(
title: 'Systemize workflow surfaces',
label: 'Q2',
description: 'Bring navigation, inspectors, and sections together.',
leading: Icon(Icons.auto_awesome_outlined),
),
],
)Compact containers render vertically stacked milestones. Medium and expanded
containers render a horizontally scrollable timeline. Use
minimumHorizontalHeight when wide-but-short layouts should stay stacked, and
useContainerConstraints: true when nested cards should resolve from their own
width instead of the full screen.
AdaptiveComparison is useful for pricing tiers, rollout plans, and variant
decisions where compact layouts should focus on one option at a time:
AdaptiveComparison(
minimumColumnsHeight: AdaptiveHeight.medium,
items: const [
AdaptiveComparisonItem(
label: 'Starter',
description: 'Lean adaptive defaults for smaller teams.',
leading: Icon(Icons.eco_outlined),
trailing: PriceBadge(label: '\$29'),
child: ComparisonBody(title: 'Best for early rollout'),
),
AdaptiveComparisonItem(
label: 'Growth',
description: 'More workflow surfaces and inspector behavior.',
leading: Icon(Icons.trending_up_outlined),
trailing: PriceBadge(label: '\$79'),
child: ComparisonBody(title: 'Best for active teams'),
),
],
)Compact containers render a segmented selector and one active option. Medium and
expanded containers render all options side by side. Use
minimumColumnsHeight when wide-but-short layouts should stay in compact mode,
and useContainerConstraints: true when nested cards should resolve from their
own width.
AdaptiveDiffView helps review and approval screens move between a compact
toggle and a side-by-side diff:
AdaptiveDiffView(
minimumSplitHeight: AdaptiveHeight.medium,
primary: const AdaptiveDiffPane(
label: 'Current',
description: 'The shipped workspace shell.',
child: ReviewPaneBody(title: 'What is already working'),
),
secondary: const AdaptiveDiffPane(
label: 'Proposed',
description: 'The next review pass.',
child: ReviewPaneBody(title: 'What changes in this pass'),
),
)Compact containers show one selected pane at a time behind a segmented toggle.
Medium and expanded containers show both panes side by side. Use
minimumSplitHeight when wide-but-short layouts should stay in toggle mode,
and useContainerConstraints: true when nested review surfaces should resolve
from their own width.
AdaptiveSchedule helps planning and agenda screens switch between a stacked
day list and side-by-side day columns:
AdaptiveSchedule(
minimumColumnsHeight: AdaptiveHeight.medium,
days: const [
AdaptiveScheduleDay(
label: 'Monday',
description: 'Prototype and review',
entries: [
AdaptiveScheduleEntry(
timeLabel: '09:00',
title: 'Design review',
description: 'Walk through the adaptive shell catalog.',
),
AdaptiveScheduleEntry(
timeLabel: '13:30',
title: 'Spacing audit',
),
],
),
AdaptiveScheduleDay(
label: 'Tuesday',
description: 'Implementation',
entries: [
AdaptiveScheduleEntry(
timeLabel: '10:00',
title: 'Board refinement',
),
],
),
],
)Compact containers render a stacked agenda by day. Medium and expanded
containers render side-by-side day columns. Use minimumColumnsHeight when
wide-but-short layouts should stay in agenda mode, and
useContainerConstraints: true when nested cards should resolve from their own
width.
AdaptiveCalendar helps week and sprint views move between a stacked agenda and
a multi-column day grid:
AdaptiveCalendar(
minimumGridHeight: AdaptiveHeight.medium,
days: const [
AdaptiveCalendarDay(
label: 'Mon 1',
subtitle: 'Sprint kickoff',
entries: [
EventChip(label: 'Standup'),
EventChip(label: 'Design review'),
],
),
AdaptiveCalendarDay(
label: 'Tue 2',
subtitle: 'Build day',
entries: [
EventChip(label: 'Implementation'),
],
),
],
)Compact containers render a stacked day agenda. Medium and expanded containers
render a multi-column grid of day cards. Use minimumGridHeight when
wide-but-short layouts should stay in agenda mode, and
useContainerConstraints: true when nested cards should resolve from their own
width.
AdaptiveDeck helps overview and launch surfaces move between a focused card
pager and a responsive deck grid:
AdaptiveDeck(
minimumGridHeight: AdaptiveHeight.medium,
items: const [
AdaptiveDeckItem(
label: 'Foundation',
description: 'Core responsive primitives.',
leading: Icon(Icons.layers_outlined),
child: DeckBody(title: 'What ships here'),
),
AdaptiveDeckItem(
label: 'Workflow',
description: 'Compound workspace surfaces.',
leading: Icon(Icons.workspaces_outline),
child: DeckBody(title: 'What ships here'),
),
],
)Compact containers render a paged card deck. Medium and expanded containers
render a responsive card grid. Use minimumGridHeight when wide-but-short
layouts should stay in pager mode, and useContainerConstraints: true when
nested cards should resolve from their own width.
AdaptiveGallery helps preview-heavy screens move between a compact carousel
and a wider spotlight view with a selector list:
AdaptiveGallery(
minimumSpotlightHeight: AdaptiveHeight.medium,
items: const [
AdaptiveGalleryItem(
label: 'Workspace launch',
description: 'Preview the shell and nested inspector surfaces.',
leading: Icon(Icons.web_asset_outlined),
preview: PreviewSurface(title: 'One shell, many surfaces.'),
child: GalleryBody(title: 'What to inspect'),
),
AdaptiveGalleryItem(
label: 'Review queue',
description: 'Preview denser card stacks for active reviews.',
leading: Icon(Icons.fact_check_outlined),
preview: PreviewSurface(title: 'Review states stay scannable.'),
child: GalleryBody(title: 'What to inspect'),
),
],
)Compact containers render a paged preview carousel. Medium and expanded
containers render a selected spotlight card with a selector list. Use
minimumSpotlightHeight when wide-but-short layouts should stay in carousel
mode, and useContainerConstraints: true when nested cards should resolve from
their own width.
AdaptiveFilterLayout helps search-and-browse screens keep results visible on
compact layouts while docking filters inline on larger surfaces:
AdaptiveFilterLayout(
filtersTitle: 'Filter library',
filtersDescription: 'Tune component type, density, and release status.',
activeFilters: const [
Chip(label: Text('Mobile-ready')),
Chip(label: Text('Live')),
Chip(label: Text('Navigation')),
],
resultsHeader: const FilterResultsHeader(
title: '89 matching components',
),
results: const ResultsList(),
filters: const FilterControls(),
minimumDockedHeight: AdaptiveHeight.medium,
)Compact containers keep the results primary, show active filters above the
results, and move the filter controls into a modal sheet. Medium and expanded
containers dock the filter surface inline. Use minimumDockedHeight when
wide-but-short layouts should stay in modal mode, and
useContainerConstraints: true when nested browsing surfaces should resolve
from their own width.
AdaptiveResultBrowser helps search and asset flows keep the result list
primary on compact layouts while docking details inline on larger surfaces:
AdaptiveResultBrowser<SearchResult>(
results: results,
header: const SearchResultsHeader(
title: 'Component search results',
),
minimumSplitHeight: AdaptiveHeight.medium,
itemBuilder: (context, result, selected, onTap) {
return SearchResultTile(
result: result,
selected: selected,
onTap: onTap,
);
},
detailBuilder: (context, result) {
return SearchResultDetail(result: result);
},
)Compact containers keep the result list primary and open details in a modal
sheet when a result is tapped. Medium and expanded containers dock the list and
detail view side by side. Use minimumSplitHeight when wide-but-short layouts
should stay modal-first, and useContainerConstraints: true when nested result
surfaces should resolve from their own width.
AdaptiveExplorer helps library and search workspaces combine filters, results,
and details into one adaptive surface:
AdaptiveExplorer<SearchResult>(
results: results,
filtersTitle: 'Explorer filters',
filtersDescription: 'Focus the component library by status and type.',
activeFilters: const [
Chip(label: Text('Live')),
Chip(label: Text('Navigation')),
],
header: const SearchResultsHeader(
title: 'Component explorer',
),
filters: const FilterControls(),
itemBuilder: (context, result, selected, onTap) {
return SearchResultTile(
result: result,
selected: selected,
onTap: onTap,
);
},
detailBuilder: (context, result) {
return SearchResultDetail(result: result);
},
)Compact containers keep filters and details modal-first so the result list stays
primary. Larger containers dock filters, results, and detail side by side in a
single explorer workspace. Use minimumDockedHeight when short-but-wide
surfaces should stay modal-first, and useContainerConstraints: true when
nested explorers should resolve from their own width.
AdaptiveDocumentView helps specs, release notes, and guidelines keep the
document itself primary on compact layouts while docking a section outline
inline on larger surfaces:
AdaptiveDocumentView(
header: const DocumentHeader(
title: 'Adaptive package release notes',
),
outlineTitle: 'Release outline',
outlineDescription: 'Jump between the major changes in this pass.',
minimumDockedHeight: AdaptiveHeight.medium,
sections: const [
AdaptiveDocumentSection(
label: 'Overview',
summary: 'Why this release matters.',
leading: Icon(Icons.description_outlined),
child: DocumentSectionBody(title: 'What changed'),
),
AdaptiveDocumentSection(
label: 'Layout rules',
summary: 'Width and height decisions used by the new primitives.',
leading: Icon(Icons.rule_outlined),
child: DocumentSectionBody(title: 'How sizing works'),
),
],
)Compact containers keep reading flow primary and open the outline from a modal
bottom sheet. Medium and expanded containers dock the outline beside the
document. Use minimumDockedHeight when wide-but-short layouts should stay
modal-first, and useContainerConstraints: true when nested document surfaces
should resolve from their own width.
AdaptiveWorkbench helps builder, studio, and configuration screens stage a
library, a canvas, and an inspector from one adaptive surface:
AdaptiveWorkbench(
header: const WorkbenchHeader(
title: 'Adaptive studio',
),
libraryTitle: 'Asset library',
libraryDescription: 'Choose sections, cards, and workflow surfaces.',
library: const AssetLibraryPanel(),
inspectorTitle: 'Selection inspector',
inspectorDescription: 'Tune spacing, emphasis, and release state.',
inspector: const InspectorControls(),
canvas: const StudioCanvas(),
)Compact containers keep the canvas primary and move both side panels into modal
sheets. Medium containers dock the library first, then expanded containers dock
the inspector too. Use minimumInspectorDockedHeight when short-but-wide
surfaces should keep the inspector modal, and useContainerConstraints: true
when nested studio surfaces should resolve from their own width.
AdaptiveReviewDesk helps moderation, QA, and approval flows stage a queue, a
central review surface, and a decision panel from one adaptive workspace:
AdaptiveReviewDesk<ReviewItem>(
queueTitle: 'Review queue',
decisionTitle: 'Decision panel',
header: const ReviewHeader(
title: 'Workspace shell review',
),
items: items,
itemBuilder: (context, item, selected, onTap) {
return ReviewQueueTile(
item: item,
selected: selected,
onTap: onTap,
);
},
reviewBuilder: (context, item) => ReviewSurface(item: item),
decisionBuilder: (context, item) => DecisionPanel(item: item),
)Compact containers keep the review surface primary and move both the queue and
decision panel into modal sheets. Medium containers dock the queue first, then
expanded containers dock the decision panel too. Use
minimumDecisionDockedHeight when short-but-wide layouts should keep the
decision panel modal, and useContainerConstraints: true when nested review
surfaces should resolve from their own width.
AdaptiveConversationDesk helps messaging, support, and collaboration screens
stage a conversation list, an active thread, and a participant/context panel:
AdaptiveConversationDesk<Conversation>(
listTitle: 'Conversations',
contextTitle: 'Participant context',
header: const ThreadHeader(
title: 'Adaptive support inbox',
),
conversations: conversations,
itemBuilder: (context, conversation, selected, onTap) {
return ConversationTile(
conversation: conversation,
selected: selected,
onTap: onTap,
);
},
threadBuilder: (context, conversation) => ThreadView(conversation: conversation),
contextBuilder: (context, conversation) =>
ParticipantContext(conversation: conversation),
)Compact containers keep the active thread primary and move both the list and
the context panel into modal sheets. Medium containers dock the list first,
then expanded containers dock the context panel too. Use
minimumContextDockedHeight when short-but-wide layouts should keep the
context panel modal, and useContainerConstraints: true when nested messaging
surfaces should resolve from their own width.
AdaptiveComposer helps writing, content, and builder flows move between a
compact editor/preview toggle, a split editor-preview layout, and a fully
docked editor-preview plus settings surface:
AdaptiveComposer(
header: const ComposerHeader(
title: 'Adaptive release note composer',
),
editorTitle: 'Editor',
previewTitle: 'Preview',
settingsTitle: 'Settings',
editor: const EditorSurface(),
preview: const PreviewSurface(),
settings: const ComposerSettings(),
)Compact containers keep one surface visible at a time behind an editor/preview
toggle and move settings into a modal sheet. Medium containers split editor and
preview, then expanded containers dock settings too. Use
minimumSettingsDockedHeight when short-but-wide layouts should keep settings
modal, and useContainerConstraints: true when nested composer surfaces should
resolve from their own width.
AdaptivePresentationDesk helps deck-building, speaking, and review flows
stage a slide list, a main presentation stage, and speaker notes:
AdaptivePresentationDesk<Slide>(
listTitle: 'Slides',
notesTitle: 'Speaker notes',
header: const StageHeader(
title: 'Adaptive launch deck',
),
slides: slides,
itemBuilder: (context, slide, selected, onTap) {
return SlideThumbnail(
slide: slide,
selected: selected,
onTap: onTap,
);
},
stageBuilder: (context, slide) => SlideStage(slide: slide),
notesBuilder: (context, slide) => SpeakerNotes(slide: slide),
)Compact containers keep the active stage primary and move both the slide list
and speaker notes into modal sheets. Medium containers dock the slide list
first, then expanded containers dock the notes surface too. Use
minimumNotesDockedHeight when short-but-wide layouts should keep notes modal,
and useContainerConstraints: true when nested stage surfaces should resolve
from their own width.
AdaptiveControlCenter helps dense operations, monitoring, and command
surfaces stage a sidebar, a central dashboard, a right insights panel, and a
bottom activity stream from one adaptive model:
AdaptiveControlCenter(
header: const DashboardHeader(
title: 'Adaptive control center',
),
sidebarTitle: 'Service lanes',
insightsTitle: 'Incident insights',
activityTitle: 'Activity stream',
sidebar: const ServiceSidebar(),
main: const MonitoringDashboard(),
insights: const IncidentInsights(),
activity: const ActivityTimeline(),
)Compact containers keep the main dashboard primary and move all supporting
panels into modal sheets. Medium containers dock the sidebar first, expanded
containers dock the insights panel next, and tall expanded surfaces can dock
the activity stream below the main dashboard. Use
minimumActivityDockedHeight when short-but-wide layouts should keep activity
modal, and useContainerConstraints: true when nested control surfaces should
resolve from their own width.
AdaptiveIncidentDesk helps incident response, moderation, and operational
review flows stage an incident list, an active detail surface, a context
panel, and a timeline panel from one adaptive workspace:
AdaptiveIncidentDesk<Incident>(
listTitle: 'Active incidents',
contextTitle: 'Responder context',
timelineTitle: 'Incident timeline',
header: const IncidentHeader(
title: 'Adaptive incident desk',
),
incidents: incidents,
itemBuilder: (context, incident, selected, onTap) {
return IncidentTile(
incident: incident,
selected: selected,
onTap: onTap,
);
},
detailBuilder: (context, incident) => IncidentDetail(incident: incident),
contextBuilder: (context, incident) => ResponderContext(incident: incident),
timelineBuilder: (context, incident) => IncidentTimeline(incident: incident),
)Compact containers keep the active incident detail primary and move the list,
context, and timeline into modal sheets. Medium containers dock the incident
list first, expanded containers dock the context panel next, and tall expanded
surfaces can dock the timeline below the active detail surface. Use
minimumTimelineDockedHeight when short-but-wide layouts should keep the
timeline modal, and useContainerConstraints: true when nested incident
surfaces should resolve from their own width.
AdaptiveMetricsLab helps analytics, reporting, and observability flows stage
a query list, a main focus surface, annotations, and query history from one
adaptive workspace:
AdaptiveMetricsLab<MetricQuery>(
queryTitle: 'Saved queries',
annotationsTitle: 'Annotations',
historyTitle: 'Query history',
header: const MetricsHeader(
title: 'Adaptive metrics lab',
),
queries: queries,
itemBuilder: (context, query, selected, onTap) {
return QueryTile(
query: query,
selected: selected,
onTap: onTap,
);
},
focusBuilder: (context, query) => MetricFocus(query: query),
annotationsBuilder: (context, query) => MetricAnnotations(query: query),
historyBuilder: (context, query) => QueryHistory(query: query),
)Compact containers keep the active focus surface primary and move the query
list, annotations, and history into modal sheets. Medium containers dock the
query list first, expanded containers dock annotations next, and tall expanded
surfaces can dock history below the active focus surface. Use
minimumHistoryDockedHeight when short-but-wide layouts should keep history
modal, and useContainerConstraints: true when nested analytics surfaces
should resolve from their own width.
AdaptiveExperimentLab helps experimentation, rollout, and decision-review
flows stage an experiment list, an active focus surface, evidence, and a
decision log from one adaptive workspace:
AdaptiveExperimentLab<Experiment>(
experimentTitle: 'Active experiments',
evidenceTitle: 'Evidence',
decisionTitle: 'Decision log',
header: const ExperimentHeader(
title: 'Adaptive experiment lab',
),
experiments: experiments,
itemBuilder: (context, experiment, selected, onTap) {
return ExperimentTile(
experiment: experiment,
selected: selected,
onTap: onTap,
);
},
focusBuilder: (context, experiment) => ExperimentFocus(experiment: experiment),
evidenceBuilder: (context, experiment) => ExperimentEvidence(experiment: experiment),
decisionBuilder: (context, experiment) => ExperimentDecisionLog(experiment: experiment),
)Compact containers keep the active experiment focus primary and move the list,
evidence, and decision log into modal sheets. Medium containers dock the
experiment list first, expanded containers dock evidence next, and tall
expanded surfaces can dock the decision log below the active focus surface.
Use minimumDecisionDockedHeight when short-but-wide layouts should keep the
decision log modal, and useContainerConstraints: true when nested
experimentation surfaces should resolve from their own width.
AdaptivePlanningDesk helps planning, roadmap, and coordination flows stage a
plan list, an active plan focus surface, risks, and milestones from one
adaptive workspace:
AdaptivePlanningDesk<Plan>(
planTitle: 'Launch plans',
risksTitle: 'Key risks',
milestonesTitle: 'Milestones',
header: const PlanningHeader(
title: 'Adaptive planning desk',
),
plans: plans,
itemBuilder: (context, plan, selected, onTap) {
return PlanTile(
plan: plan,
selected: selected,
onTap: onTap,
);
},
focusBuilder: (context, plan) => PlanFocus(plan: plan),
risksBuilder: (context, plan) => PlanRisks(plan: plan),
milestonesBuilder: (context, plan) => PlanMilestones(plan: plan),
)Compact containers keep the active plan focus primary and move the list,
risks, and milestones into modal sheets. Medium containers dock the plan list
first, expanded containers dock risks next, and tall expanded surfaces can
dock milestones below the active focus surface. Use
minimumMilestonesDockedHeight when short-but-wide layouts should keep
milestones modal, and useContainerConstraints: true when nested planning
surfaces should resolve from their own width.
AdaptiveReleaseLab helps release coordination, launch readiness, and rollout
flows stage a release list, an active readiness surface, blockers, and a
rollout log from one adaptive workspace:
AdaptiveReleaseLab<Release>(
releaseTitle: 'Active releases',
blockersTitle: 'Launch blockers',
rolloutTitle: 'Rollout log',
header: const ReleaseHeader(
title: 'Adaptive release lab',
),
releases: releases,
itemBuilder: (context, release, selected, onTap) {
return ReleaseTile(
release: release,
selected: selected,
onTap: onTap,
);
},
readinessBuilder: (context, release) => ReleaseReadiness(release: release),
blockersBuilder: (context, release) => ReleaseBlockers(release: release),
rolloutBuilder: (context, release) => ReleaseRolloutLog(release: release),
)Compact containers keep the active readiness surface primary and move the
release list, blockers, and rollout log into modal sheets. Medium containers
dock the release list first, expanded containers dock blockers next, and tall
expanded surfaces can dock the rollout log below the active readiness surface.
Use minimumRolloutDockedHeight when short-but-wide layouts should keep the
rollout log modal, and useContainerConstraints: true when nested release
surfaces should resolve from their own width.
AdaptiveApprovalDesk helps approval, governance, and signoff flows stage an
approval list, an active proposal surface, criteria, and decision history from
one adaptive workspace:
AdaptiveApprovalDesk<ApprovalRequest>(
approvalTitle: 'Pending approvals',
criteriaTitle: 'Approval criteria',
historyTitle: 'Decision history',
header: const ApprovalHeader(
title: 'Adaptive approval desk',
),
approvals: approvals,
itemBuilder: (context, approval, selected, onTap) {
return ApprovalTile(
approval: approval,
selected: selected,
onTap: onTap,
);
},
proposalBuilder: (context, approval) => ApprovalProposal(approval: approval),
criteriaBuilder: (context, approval) => ApprovalCriteria(approval: approval),
historyBuilder: (context, approval) => ApprovalHistory(approval: approval),
)Compact containers keep the active proposal primary and move the approval list,
criteria, and history into modal sheets. Medium containers dock the approval
list first, expanded containers dock criteria next, and tall expanded surfaces
can dock history below the active proposal surface. Use
minimumHistoryDockedHeight when short-but-wide layouts should keep history
modal, and useContainerConstraints: true when nested approval surfaces
should resolve from their own width.
AdaptiveScaffold switches navigation patterns automatically:
compact->NavigationBarmedium->NavigationRailexpanded->NavigationDrawer
AdaptiveScaffold(
animateTransitions: true,
minimumRailHeight: AdaptiveHeight.medium,
minimumDrawerHeight: AdaptiveHeight.medium,
selectedIndex: selectedIndex,
onSelectedIndexChanged: (index) => setState(() => selectedIndex = index),
destinations: const [
AdaptiveScaffoldDestination(
icon: Icon(Icons.home_outlined),
selectedIcon: Icon(Icons.home),
label: 'Home',
),
AdaptiveScaffoldDestination(
icon: Icon(Icons.auto_awesome_mosaic_outlined),
selectedIcon: Icon(Icons.auto_awesome_mosaic),
label: 'Workspace',
),
],
body: const DashboardPage(),
)Use minimumRailHeight and minimumDrawerHeight when short-but-wide viewports
should demote their navigation chrome instead of keeping the same width-driven
mode.
Set animateTransitions: true to animate between bottom navigation, rail, and
drawer-style modes.
Use ResponsiveGrid for explicit 12-column spans:
ResponsiveGrid(
children: const [
ResponsiveGridItem(xs: 12, md: 6, lg: 4, child: Card(child: Text('A'))),
ResponsiveGridItem(xs: 12, md: 6, lg: 4, child: Card(child: Text('B'))),
],
)Use AutoResponsiveGrid when you want columns to derive from the available
width:
AutoResponsiveGrid(
minItemWidth: 220,
columnSpacing: 16,
rowSpacing: 16,
children: cards,
)Use ReorderableAutoResponsiveGrid when dashboard cards should stay adaptive
and be rearrangeable:
ReorderableAutoResponsiveGrid(
minItemWidth: 220,
onReorder: (oldIndex, newIndex) {
final item = cards.removeAt(oldIndex);
cards.insert(newIndex, item);
},
children: [
for (final card in cards)
DashboardCard(
key: ValueKey(card.id),
data: card,
),
],
)ResponsiveSpacing and ResponsiveTextStyle also expose fluid helpers:
padding: ResponsiveSpacing.fluidPadding(
context,
compact: const EdgeInsets.all(16),
expanded: const EdgeInsets.all(32),
),
style: ResponsiveTextStyle.fluid(
context,
compact: const TextStyle(fontSize: 24),
expanded: const TextStyle(fontSize: 40),
),ResponsiveDebugOverlay displays the active breakpoint, adaptive size, and
available size on top of the widget tree:
ResponsiveDebugOverlay(
label: 'screen',
child: DashboardPage(),
)Set useContainerConstraints: true to inspect a pane or card instead of the
full screen.
The package still includes:
ResponsiveSpacingfor padding and gapsResponsiveTextStylefor text styles and font sizesResponsiveVisibilityfor breakpoint-based visibilityAdaptiveContainerfor breakpoint-specific widget slotsDeviceDetectorandBuildContextdevice helpers
Run cd example && flutter run to open a catalog-style demo app with a
separate page for each major feature.
See example/lib/main.dart for demo pages covering:
- semantic responsive values
- fluid spacing and typography
- container-aware sections
AdaptivePaneAdaptiveActionBarAdaptiveFormAdaptivePriorityLayoutAnimatedResponsiveLayoutBuilderAdaptiveScaffoldAutoResponsiveGridReorderableAutoResponsiveGridAdaptiveDeckAdaptiveGalleryAdaptiveFilterLayoutAdaptiveResultBrowserAdaptiveExplorerAdaptiveDocumentViewAdaptiveWorkbenchAdaptiveReviewDeskAdaptiveConversationDeskAdaptiveComposerAdaptivePresentationDeskAdaptiveDiffViewResponsiveDebugOverlay
MIT
