holy_sheet 0.0.3 copy "holy_sheet: ^0.0.3" to clipboard
holy_sheet: ^0.0.3 copied to clipboard

A Flutter sheet & panel widget that's good as hell.

holy_sheet #

A Flutter sheet & panel widget that's good as hell.

Use it to build something like:

  • Spotify's currently playing sheet
  • Material Bottom Sheet, but from the top of the screen
  • Apple's NFC / Apple Pay modals
  • Google Maps' scrollable detail views

HolySheet respects the following conventions:

  1. The sheet is always modal.
  2. The sheet is always draggable.
  3. The sheet passes its constraints to its child, which it then (by default) translates with a custom layout.
  4. The sheet expects that all scrollable areas within itself respect the gesture arena and declare defeat when reasonable.


  • simple methods for controlling the sheet using a non-sibling gesture recognizer
    • i.e., making the background of the modal draggable
  • make sure it handles google maps-style cascading

Install #

  holy_sheet: ^0.0.1

Usage #

import 'package:holy_sheet/holy_sheet.dart';

// see exampe/lib/main.dart for details

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _opacity;

  void initState() {
    _controller = Harusaki.controller(
      value: 1.0,
      vsync: this,
    _opacity = Tween<double>(begin: 0, end: 1).animate(_controller);

  Widget build(BuildContext context) {
    final padding = MediaQuery.of(context).padding.top;
    final headerHeight = padding + kToolbarHeight;
    final contentHeight = MediaQuery.of(context).size.height - kToolbarHeight - headerHeight;
    final _height = Tween<double>(
      begin: headerHeight,
      end: headerHeight + contentHeight,

    return Stack(
      children: <Widget>[
        // the background
          color: Colors.yellow,
        // the darkening background
          opacity: _opacity,
          child: Container(
            color: Colors.black45,
        // the sheet layer
          // use the `.normal` SpringDescription
          description: Harusaki.normal,
          // descend from the top
          riseFrom: RiseFrom.Heaven,
          animationController: _controller,
          // a custom animation for entrance/exit
          animationBuilder: (context, child) {
            return Align(
              alignment: Alignment.topCenter,
              child: SizedBox(
                height: _height.transform(_controller.value).clamp(0.0, double.infinity),
                child: child,
          // the contents of the sheet
          builder: (context) {
            // a simple layout for showing the different layers
            // it uses a Material as the primary background
            return Material(
              elevation: 1,
              color: Theme.of(context).bottomSheetTheme.backgroundColor,
              // then clips the content within an overflow box
              child: ClipRect(
                child: OverflowBox(
                  minHeight: headerHeight,
                  maxHeight: headerHeight + contentHeight,
                  alignment: Alignment.topCenter,
                  // which is a purple back layer
                  child: Container(
                    color: Colors.purple,
                    child: Column(
                      // and some simple containers that illustrate the dimensions of the device
                      children: <Widget>[
                        Container(color: Colors.red, height: padding),
                        Container(color: Colors.blue, height: kToolbarHeight),

pub points


verified publisherbydot.app

A Flutter sheet & panel widget that's good as hell.

Repository (GitHub)
View/report issues


BSD-2-Clause (LICENSE)




Packages that depend on holy_sheet