Skip to content

Panels

CdxSlideInPanel is the canonical drawer / detail panel for CDX. It slides in from the right (default), left, or bottom — and hosts an inner navigator so you can drill into nested pages without stacking modal routes on the root navigator.

Open a single page

dart
CdxSlideInPanel.show<bool>(
  context: context,
  panel: CdxSlideInPanel(
    title: 'Edit area',
    icon: FluentIcons.edit_24_regular,
    width: const PanelDimension.clamped(fraction: 0.7, min: 540, max: 820),
    content: AreaEditor(area: area),
    actions: [
      DialogAction.cancel(onPressed: () => Navigator.of(context).pop(false)),
      DialogAction.primary(label: 'Save', onPressed: () => Navigator.of(context).pop(true)),
    ],
  ),
);

show<T> is a wrapper around showGeneralDialog (or showModalBottomSheet on compact viewports — see responsiveBottomSheet below).

For nested navigation, pass initialPage and use CdxPanelPage.push inside its content:

dart
CdxSlideInPanel.show(
  context: context,
  panel: CdxSlideInPanel(
    width: const PanelDimension.clamped(fraction: 0.7, min: 540, max: 820),
    initialPage: CdxPanelPage(
      title: 'Areas',
      icon: FluentIcons.building_factory_24_regular,
      content: AreasMaster(onSelect: (area) => CdxPanelPage.push(
        context: context,
        page: CdxPanelPage(
          title: area.name,
          content: AreaDetail(area: area),
          actions: [DialogAction.primary(label: 'Save', onPressed: ...)],
        ),
      )),
    ),
  ),
);

The pushed page slides in within the panel's bounds (not over the entire screen). The auto-derived dismiss button shows a back arrow on pushed pages and a close X on the root page.

CdxPanelPage

A page hosted inside the inner navigator. Mirrors DialogShell's header / content / footer API.

dart
CdxPanelPage(
  title: 'Audit Trail',
  icon: FluentIcons.history_24_regular,
  content: AuditList(),
  headerActions: [Button.icon(icon: FluentIcons.arrow_download_24_regular, ...)],
  footerMessage: const DialogMessage(text: 'Last refreshed 2 minutes ago.', severity: MessageSeverity.info),
  actions: [DialogAction.cancel(label: 'Close', onPressed: () => Navigator.of(context).pop())],
)

CdxPanelPage.push<T> returns the value passed to Navigator.pop from inside the pushed page — same contract as Navigator.push.

PanelDimension

Sizing primitive for the panel's width (and bottom-direction height).

dart
PanelDimension.size(720)                                          // absolute
PanelDimension.fraction(0.6)                                      // 60% of viewport
PanelDimension.clamped(fraction: 0.7, min: 540, max: 820)         // common — fluid + bounded

SlideInDirection

dart
enum SlideInDirection { right, left, bottom }

Right (default) pairs with the page-content layout that puts the primary action on the right. bottom always uses full screen width and defaults to 85% of viewport height.

Responsive bottom sheet

dart
CdxSlideInPanel.show(
  ...,
  responsiveBottomSheet: true,    // default
  compactBreakpoint: 900,
);

When the viewport is narrower than compactBreakpoint AND responsiveBottomSheet is true, the panel is shown as a showModalBottomSheet instead — gives mobile-style UX automatically. Set responsiveBottomSheet: false to always use the slide-in panel regardless of viewport.

Panel-aware navigation

When a button inside a panel needs to navigate the main app via go_router, call context.dismissAndGo instead of context.go — it walks up the panel stack and dismisses every enclosing CdxSlideInPanel before firing the navigation. Without this, the panel stays mounted on top of the destination page.

dart
// inside any widget hosted in a panel:
context.dismissAndGo('/areas/${area.id}');
context.dismissAndPush<bool>('/areas/${area.id}/audit');

The extension lives at CdxSlideInPanelNavigation on BuildContext — both methods are safe to call unconditionally (no-op outside any panel), so callers don't need to guard with a maybeOf check.

Manual dismiss

dart
CdxSlideInPanel.dismiss(context, result);   // pop the nearest enclosing panel
CdxSlideInPanel.dismissAll(context);        // pop every enclosing panel (drill-out)
  • DialogsDialogHeader / DialogFooter / DialogAction are reused by CdxPanelPage
  • LayoutMasterDetailScaffold is the in-page alternative to a slide-in panel
  • Overlays — root-overlay targeting so dropdowns inside a panel paint over it