Containers
Sheets
LiqSheet is the iOS 26 modal sheet container. It renders the grabber,
controls row, and body for the chosen LiqSheetVariant. The host is
responsible for animating presentation and dimming the parent scrim.
Full Screen
// ignore_for_file: file_namesimport 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/examples.dart';Widget sheetFullScreenBuilder(BuildContext context) { return const SnippetFrame(child: SheetFullScreenExample());}
Stacked
import 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/liqkit_ui.dart';/// Snippet builder consumed by `apps/docs_snippets/lib/src/routes.g.dart`.Widget sheetStackedBuilder(BuildContext context) { return const _SheetStackedDemo();}class _SheetStackedDemo extends StatefulWidget { const _SheetStackedDemo(); @override State<_SheetStackedDemo> createState() => _SheetStackedDemoState();}class _SheetStackedDemoState extends State<_SheetStackedDemo> { bool _presented = true; @override Widget build(BuildContext context) { return SnippetFrame( maxWidth: 430, height: 500, padding: const EdgeInsets.symmetric(horizontal: 12), surface: SnippetFrameSurface.liquidThemed, surfacePadding: EdgeInsets.zero, surfaceScrimOpacity: 0.18, child: Stack( alignment: Alignment.bottomCenter, children: <Widget>[ _StackedBackdrop(onPressed: () => setState(() => _presented = true)), AnimatedSlide( offset: _presented ? Offset.zero : const Offset(0, 1.1), duration: LiqMotion.normal, curve: LiqMotion.snappy, child: AnimatedOpacity( opacity: _presented ? 1 : 0, duration: LiqMotion.fast, child: LiqSheet( title: 'Payment', variant: LiqSheetVariant.stacked, height: 430, leading: LiqSheetTopButton( semanticsLabel: 'Close', onPressed: () => setState(() => _presented = false), child: const Text('x'), ), trailing: LiqSheetTopButton( style: LiqSheetTopButtonStyle.primary, semanticsLabel: 'Confirm', onPressed: () => setState(() => _presented = false), child: const Text('OK'), ), child: const _PaymentSheetBody(), ), ), ), ], ), ); }}class _StackedBackdrop extends StatelessWidget { const _StackedBackdrop({required this.onPressed}); final VoidCallback onPressed; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(18), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ const SnippetLabel( 'Checkout', fontSize: 28, fontWeight: FontWeight.w700, ), const SizedBox(height: 12), const _InvoiceCard(), const Spacer(), LiqButton(label: 'Show stacked sheet', onPressed: onPressed), ], ), ); }}class _InvoiceCard extends StatelessWidget { const _InvoiceCard(); @override Widget build(BuildContext context) { final isDark = LiqTheme.maybeOf(context)?.brightness == Brightness.dark; return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: isDark ? const Color(0xFF2C2C2E) : const Color(0xFFF2F2F7), borderRadius: const BorderRadius.all(Radius.circular(18)), ), child: const Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ _LineItem(label: 'Liqkit Pro', value: r'$24'), _LineItem(label: 'Tax', value: r'$2'), _LineItem(label: 'Total', value: r'$26', strong: true), ], ), ); }}class _PaymentSheetBody extends StatelessWidget { const _PaymentSheetBody(); @override Widget build(BuildContext context) { final isDark = LiqTheme.maybeOf(context)?.brightness == Brightness.dark; return Padding( padding: const EdgeInsets.fromLTRB(22, 8, 22, 22), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ const _LineItem(label: 'Card', value: 'Apple Pay', strong: true), const _LineItem(label: 'Billing cycle', value: 'Monthly'), const _LineItem(label: 'Due today', value: r'$26', strong: true), const SizedBox(height: 18), Text( 'Stacked sheets show the previous modal page tucked underneath, ' 'making layered presentation obvious.', textDirection: TextDirection.ltr, style: TextStyle( color: isDark ? const Color(0xFFA1A1AA) : const Color(0xFF6E6E73), fontSize: 15, height: 1.35, ), ), ], ), ); }}class _LineItem extends StatelessWidget { const _LineItem({ required this.label, required this.value, this.strong = false, }); final String label; final String value; final bool strong; @override Widget build(BuildContext context) { final isDark = LiqTheme.maybeOf(context)?.brightness == Brightness.dark; return Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Row( children: <Widget>[ Expanded( child: Text( label, textDirection: TextDirection.ltr, style: TextStyle( fontSize: 15, color: isDark ? const Color(0xFFA1A1AA) : const Color(0xFF6E6E73), ), ), ), Text( value, textDirection: TextDirection.ltr, style: TextStyle( color: isDark ? const Color(0xFFF5F5F7) : const Color(0xFF1A1A1A), fontSize: 15, fontWeight: strong ? FontWeight.w700 : FontWeight.w500, ), ), ], ), ); }}
Inspector
import 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/liqkit_ui.dart';/// Snippet builder consumed by `apps/docs_snippets/lib/src/routes.g.dart`.Widget sheetInspectorBuilder(BuildContext context) { return const _SheetInspectorDemo();}class _SheetInspectorDemo extends StatefulWidget { const _SheetInspectorDemo(); @override State<_SheetInspectorDemo> createState() => _SheetInspectorDemoState();}class _SheetInspectorDemoState extends State<_SheetInspectorDemo> { bool _presented = true; @override Widget build(BuildContext context) { return SnippetFrame( maxWidth: 430, height: 540, padding: const EdgeInsets.symmetric(horizontal: 12), surface: SnippetFrameSurface.liquidThemed, surfacePadding: EdgeInsets.zero, surfaceScrimOpacity: 0.12, child: Stack( alignment: Alignment.bottomCenter, children: <Widget>[ _InspectorCanvas(onPressed: () => setState(() => _presented = true)), AnimatedSlide( offset: _presented ? Offset.zero : const Offset(0, 1.1), duration: LiqMotion.normal, curve: LiqMotion.snappy, child: AnimatedOpacity( opacity: _presented ? 1 : 0, duration: LiqMotion.fast, child: LiqSheet( title: 'Inspector', variant: LiqSheetVariant.inspector, leading: LiqSheetTopButton( semanticsLabel: 'Close', onPressed: () => setState(() => _presented = false), child: const Text('x'), ), trailing: LiqSheetTopButton( style: LiqSheetTopButtonStyle.primary, semanticsLabel: 'Apply', onPressed: () => setState(() => _presented = false), child: const Text('OK'), ), child: const _InspectorSheetBody(), ), ), ), ], ), ); }}class _InspectorCanvas extends StatelessWidget { const _InspectorCanvas({required this.onPressed}); final VoidCallback onPressed; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(18), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ const SnippetLabel( 'Photo', fontSize: 28, fontWeight: FontWeight.w700, ), const SizedBox(height: 14), const Expanded( child: DecoratedBox( decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(22)), gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: <Color>[ Color(0xFFFF6B8A), Color(0xFF2F8DFF), Color(0xFF58D68D), ], ), boxShadow: <BoxShadow>[ BoxShadow(color: Color(0x22000000), blurRadius: 20), ], ), ), ), const SizedBox(height: 14), LiqButton(label: 'Show inspector', onPressed: onPressed), ], ), ); }}class _InspectorSheetBody extends StatelessWidget { const _InspectorSheetBody(); @override Widget build(BuildContext context) { final isDark = LiqTheme.maybeOf(context)?.brightness == Brightness.dark; return Padding( padding: const EdgeInsets.fromLTRB(22, 4, 22, 20), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ const _InspectorControl(label: 'Exposure', value: '+0.4'), const _InspectorControl(label: 'Contrast', value: '18%'), const _InspectorControl(label: 'Warmth', value: 'Neutral'), const SizedBox(height: 12), Text( 'Inspector sheets float over the content they adjust, using a ' 'glass surface so the edited object remains visible.', textDirection: TextDirection.ltr, style: TextStyle( color: isDark ? const Color(0xFFA1A1AA) : const Color(0xFF6E6E73), fontSize: 15, height: 1.35, ), ), ], ), ); }}class _InspectorControl extends StatelessWidget { const _InspectorControl({required this.label, required this.value}); final String label; final String value; @override Widget build(BuildContext context) { final isDark = LiqTheme.maybeOf(context)?.brightness == Brightness.dark; return Container( margin: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), decoration: BoxDecoration( color: isDark ? const Color(0x3DFFFFFF) : const Color(0x4DFFFFFF), borderRadius: const BorderRadius.all(Radius.circular(12)), ), child: Row( children: <Widget>[ Expanded( child: Text( label, textDirection: TextDirection.ltr, style: TextStyle( color: isDark ? const Color(0xFFF5F5F7) : const Color(0xFF1A1A1A), fontSize: 15, ), ), ), Text( value, textDirection: TextDirection.ltr, style: TextStyle( color: isDark ? const Color(0xFFF5F5F7) : const Color(0xFF1A1A1A), fontSize: 15, fontWeight: FontWeight.w600, ), ), ], ), ); }}
Bottom
// ignore_for_file: file_namesimport 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/examples.dart';Widget sheetBottomBuilder(BuildContext context) { return const SnippetFrame(child: SheetBottomExample());}
Action
// ignore_for_file: file_namesimport 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/examples.dart';Widget sheetActionBuilder(BuildContext context) { return const SnippetFrame(child: SheetActionExample());}
Compact Action
// ignore_for_file: file_namesimport 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/examples.dart';Widget sheetCompactActionBuilder(BuildContext context) { return const SnippetFrame(child: SheetCompactActionExample());}
Custom Content
// ignore_for_file: file_namesimport 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/examples.dart';Widget sheetCustomContentBuilder(BuildContext context) { return const SnippetFrame(child: SheetCustomContentExample());}
Non Dismissible
// ignore_for_file: file_namesimport 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/examples.dart';Widget sheetNonDismissibleBuilder(BuildContext context) { return const SnippetFrame(child: SheetNonDismissibleExample());}
Destructive Action
// ignore_for_file: file_namesimport 'package:docs_snippets/src/snippet_frame.dart';import 'package:flutter/widgets.dart';import 'package:liqkit_ui/examples.dart';Widget sheetDestructiveActionBuilder(BuildContext context) { return const SnippetFrame(child: SheetDestructiveActionExample());}