PackageTrack
Sign in Get early access

adaptive_shell

Adaptive master-detail layout for Flutter — automatically switches between compact and two-pane layouts across mobile, tablet, and desktop.

2.0.0 RakeshGowdaR/adaptive_shell

What this package is like to depend on

Last release 4 months ago

29 Mar 2026

Too new to tell

only 2 release windows

Most releases are documented

notes for 3 of 5 stable releases

Nothing withdrawn

no release was ever pulled

5 months old

5 releases · first in 2026

5 releases in the last 12 months

see the full history below

Release timeline

5 releases · Mar 2026 to Mar 2026
Release Pre-release

Releases

latest 5
  1. 2.0.0 29 Mar 2026
    Release notes

    All changes are additive and backward compatible. Existing AdaptiveDestination(icon: Icons.people, label: '...') code compiles and runs with zero changes.

    ✨ New Features

    AdaptiveShellTheme — full navigation theming 🎨

    A single const-able class that controls every visual aspect of the navigation chrome. Pass it to AdaptiveShell.theme:

    AdaptiveShell(
      theme: const AdaptiveShellTheme(
        // Rail
        railMinExtendedWidth: 180,       // tighter default (was Flutter's 256)
        railBackgroundColor: Color(0xFFF8F9FA),
        railIndicatorColor: Color(0xFFD0BCFF),
        railSelectedLabelStyle: TextStyle(fontWeight: FontWeight.bold),
        railDecoration: BoxDecoration(
          border: Border(right: BorderSide(color: Color(0xFFE0E0E0))),
        ),
        // Nav bar
        navBarIndicatorColor: Color(0xFFD0BCFF),
        navBarLabelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
        navBarHeight: 72,
      ),
    )
    

    Supports copyWith and lerp.

    AdaptiveShellController — programmatic rail control 🎛️

    Collapse/expand the navigation rail from anywhere without prop-drilling:

    final _nav = AdaptiveShellController();
    
    AdaptiveShell(controller: _nav, ...)
    
    // From an AppBar action or FAB:
    IconButton(onPressed: _nav.toggleRail, icon: const Icon(Icons.menu))
    

    Methods: collapseRail(), expandRail(), toggleRail(). Property: isRailCollapsed.

    Widget icons for AdaptiveDestination — SVG, PNG, custom 🖼️

    icon is now optional (IconData?). Use iconWidget, selectedIconWidget, or iconBuilder for full widget-based icons:

    // Classic IconData — unchanged, still works
    const AdaptiveDestination(icon: Icons.home, label: 'Home')
    
    // SVG / PNG widget pair
    AdaptiveDestination(
      iconWidget: SvgPicture.asset('assets/home.svg'),
      selectedIconWidget: SvgPicture.asset('assets/home_filled.svg'),
      label: 'Home',
    )
    
    // Builder — recommended for theme-driven SVG colors
    AdaptiveDestination(
      iconBuilder: (context, isSelected) => SvgPicture.asset(
        'assets/home.svg',
        colorFilter: ColorFilter.mode(
          isSelected
            ? Theme.of(context).colorScheme.primary
            : Theme.of(context).colorScheme.onSurfaceVariant,
          BlendMode.srcIn,
        ),
      ),
      label: 'Home',
    )
    

    Custom nav builders 🏗️

    Replace the entire NavigationBar or NavigationRail with your own widget:

    AdaptiveShell(
      navigationBarBuilder: (context, destinations, index, onSelected) =>
          MyCustomBottomBar(...),
      navigationRailBuilder: (context, destinations, index, onSelected, isExtended) =>
          MyCustomSidebar(...),
    )
    

    More AdaptiveDestination fields

    Field Description
    iconSize: double? Wraps the resolved icon in a SizedBox for consistent SVG/PNG sizing
    tooltip: String? Custom tooltip (defaults to label)
    enabled: bool Disable individual destinations (grayed out, non-tappable)
    badgeLabel: String? Flexible badge: "" = dot, "NEW", "99+"

    🐛 Bug Fix

    • Navigation rail on desktop mode now defaults to minExtendedWidth: 160 (previously fell back to Flutter's built-in 256 default, which consumed too much horizontal space on typical laptop windows).

    Open source →
  2. 1.1.0 15 Mar 2026
    Release notes

    Full Changelog: v1.0.0...v1.1.0

    Open source →
    Release notes

    ✨ New Features

    AdaptiveBuilder 🏗️

    A standalone responsive builder widget that works without an AdaptiveShell ancestor — it uses LayoutBuilder and AdaptiveBreakpoints directly:

    AdaptiveBuilder(
      compact:  (context) => MobileWidget(),
      medium:   (context) => TabletWidget(),   // optional, falls back to compact
      expanded: (context) => DesktopWidget(),  // optional, falls back to medium
      breakpoints: AdaptiveBreakpoints.tabletFirst, // customisable
    )
    

    Keyboard Shortcuts ⌨️

    Map any ShortcutActivator (e.g. SingleActivator, LogicalKeySet) to a navigation destination index. Only active on medium/expanded layouts (tablet / desktop):

    AdaptiveShell(
      keyboardShortcuts: {
        SingleActivator(LogicalKeyboardKey.digit1, control: true): 0,
        SingleActivator(LogicalKeyboardKey.digit2, control: true): 1,
      },
      // ...
    )
    

    Collapsible Navigation Rail 📍

    A chevron toggle button above the rail destinations lets users collapse the rail to icon-only mode. railCollapseOnMedium auto-collapses when the layout enters medium mode:

    AdaptiveShell(
      railCollapsible: true,         // shows toggle button
      railCollapseOnMedium: true,    // auto-collapses on tablet breakpoint
      // ...
    )
    

    Custom Pane Divider ➗

    Replace the hardcoded VerticalDivider between the master and detail panes with any widget:

    AdaptiveShell(
      paneDivider: VerticalDivider(width: 2, color: Colors.blue),
      // ...
    )
    

    Context Extensions 🔧

    Quick access to layout information anywhere in your widget tree:

    • context.screenType / context.layoutMode — get current LayoutMode (usable in switch)
    • context.isCompact, context.isMedium, context.isExpanded — boolean checks
    • context.isMobile, context.isTablet, context.isDesktop — semantic aliases
    • context.isTwoPane — true when two panes are visible
    • context.adaptiveWidth(base) / context.adaptiveHeight(base) — scale dimensions
    • context.adaptivePadding() — responsive EdgeInsets (16 / 24 / 32)
    • context.adaptiveFontSize(base) / context.adaptiveSpacing(base) — scale text & gaps
    • context.adaptiveColumns — grid column count: 1 / 2 / 3 (compact / medium / expanded)
    • context.adaptiveValue<T>(compact:, medium:, expanded:) — any typed value per breakpoint
    // Boolean checks
    if (context.isCompact) { /* mobile */ }
    if (context.isTablet)  { /* medium or expanded */ }
    
    // Typed per-breakpoint value
    final padding = context.adaptiveValue(compact: 8.0, medium: 16.0, expanded: 24.0);
    
    // Grid columns
    GridView.count(crossAxisCount: context.adaptiveColumns, ...)
    
    // Layout mode in switch
    switch (context.layoutMode) {
      case LayoutMode.compact:  return MobileNav();
      case LayoutMode.medium:   return TabletNav();
      case LayoutMode.expanded: return DesktopNav();
    }
    

    Layout Change Callback

    React to layout mode transitions for analytics or state management:

    AdaptiveShell(
      onLayoutModeChanged: (oldMode, newMode) {
        print('Layout: $oldMode → $newMode');
      },
      // ...
    )
    

    Debug Overlay

    Visual indicator showing current layout mode and breakpoints during development:

    AdaptiveShell(
      debugShowLayoutMode: true, // Shows overlay in top-right corner
      // ...
    )
    

    AutoScale 📏

    Proportionally scales your layout to fill any screen size — the same technique that made responsive_framework's AutoScale popular:

    AdaptiveShell(
      autoScale: true,               // render at 360 dp design canvas, scale to screen
      scaleFactor: 1.2,              // optional: 20% boost on top of auto scale
      autoScaleDesignWidth: 390,     // optional: override canvas (e.g. iPhone 14 = 390 dp)
      // ...
    )
    

    Default autoScaleDesignWidth is 360 dp — a typical phone canvas that ensures a compact (single-pane, bottom-nav) layout by default. The debug overlay gains a live ⚖️ Scale ×N.NN line when autoScale is enabled.

    State Persistence 💾

    Preserves scroll positions and widget state when the device rotates, the window resizes, or the layout mode changes:

    AdaptiveShell(
      persistState: true,
      stateKey: 'my_shell',   // optional namespace (default: 'adaptive_shell')
      // ...
    )
    

    Uses stable GlobalKeys on child1/child2 so element subtrees survive compact ↔ wide transitions, plus a keyed PageStorage bucket for scroll restoration.

    Animated Transitions ✨

    Fine-tune detail-pane animations:

    AdaptiveShell(
      transitionCurve: Curves.easeInOutCubic,   // custom curve (default: easeInOut)
      enableHeroAnimations: true,               // slide + fade instead of cross-fade
      // ...
    )
    

    🔗 All new params available on AdaptiveMasterDetail

    autoScale, scaleFactor, autoScaleDesignWidth, persistState, stateKey, transitionCurve, enableHeroAnimations, paneDivider, railCollapsible, railCollapseOnMedium, keyboardShortcuts are all forwarded to the internal AdaptiveShell.

    🐛 Bug Fixes & Internal Improvements

    • AdaptiveShell refactored from StatelessWidget to StatefulWidget — fully backward-compatible.
    • onLayoutModeChanged now reliably fires across hot-reload and test pumps.
    • Fixed identical debug-overlay emoji for compact/medium modes.
    • AdaptiveMasterDetail._computeMode respects autoScale — navigation decisions (push vs in-place) now correctly match the visually rendered compact layout.
    • Fixed NavigationRail overflow when railCollapsible: true — the toggle button (~36 px) consumed height from the Column that also holds the NavigationRail, causing a RenderFlex overflowed by N pixels on the bottom assertion on short screens with many destinations. The rail is now wrapped in LayoutBuilder → SingleChildScrollView + ConstrainedBox(minHeight) + IntrinsicHeight so destinations scroll gracefully when they exceed the available height, while still centering correctly on taller screens. The wrapper is applied only when the toggle is present; the default (railCollapsible: false) path is unchanged.

    ✅ Tests

    • 37 new tests for AutoScale, State Persistence, Animated Transitions, new context extensions, and AdaptiveMasterDetail pass-through.
    • 29 new tests for AdaptiveBuilder, keyboard shortcuts, collapsible rail, and custom paneDivider.
    • 3 new regression tests for the railCollapsible overflow fix (expanded + medium layouts, and default path).
    • Total: 139 tests, all passing.

    ⚠️ Breaking Changes

    • None. All 1.0.x code compiles and runs unchanged.
    • New BuildContext extensions (layoutMode, adaptiveColumns, adaptiveValue, and all v1.1.0 additions) may conflict if you already define identically-named extensions. Resolve with a hide import: import 'package:adaptive_shell/adaptive_shell.dart' hide AdaptiveContextExtensions;

    Open source →
  3. 1.0.0 12 Mar 2026
    Release notes Open source →
    Release notes
    • Initial release with two APIs:
      • AdaptiveShell — flexible wrapper with child1/child2 for full manual control over both panes, navigation, and state.
      • AdaptiveMasterDetail<T> — zero-boilerplate generic widget with itemBuilder/detailBuilder. Handles selection state, navigation (push on mobile, side-pane on tablet), and responsive layout switching automatically.
    • Automatic NavigationBar (compact) / NavigationRail (medium/expanded) switching.
    • AdaptiveShell.of(context) for descendant layout-mode awareness.
    • AdaptiveShell.isTwoPane(context) convenience helper.
    • AdaptiveBreakpoints with Material 3 window size class defaults + tabletFirst preset.
    • AdaptiveDestination with badge support.
    • emptyDetailPlaceholder for large screens with no selection.
    • masterHeader and masterBuilder for custom master pane layouts.
    • compactDetailScaffoldBuilder for custom mobile detail screen wrapping.
    • Animated pane transitions with configurable duration.
    • Full support for Android, iOS, web, macOS, Windows, Linux.
    Open source →
  4. 1.0.0+1 12 Mar 2026

    Nothing published for this version

  5. 1.0.0+2 14 Mar 2026

    Nothing published for this version

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive