Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an optional gradient over the sticky action bar #29

Merged
merged 2 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ Pagination involves a sequence of screens the user navigates sequentially. We ch
The code snippet above produces the following:
</br>
</br>
![Example app](https://github.com/woltapp/wolt_modal_sheet/blob/main/doc/example_app_recording.gif?raw=true)
![Example app](https://github.com/woltapp/wolt_modal_sheet/blob/main/doc/example_app_record.gif?raw=true)

### Playground app with imperative navigation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class AddWaterDescriptionModalPage {
image: AssetImage('lib/assets/images/add_water_description.png'),
fit: BoxFit.cover,
),
stickyActionBar: StickyActionBarWrapper(
stickyActionBar: Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Column(
children: [
WoltElevatedButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class WaterSettingsModalPage {
stickyActionBar: ValueListenableBuilder<bool>(
valueListenable: buttonEnabledListener,
builder: (_, isEnabled, __) {
return StickyActionBarWrapper(
return Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: onWaterAdded,
enabled: isEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class GrindOrRejectModalPage {
required VoidCallback onClosed,
}) {
return WoltModalSheetPage.withSingleChild(
stickyActionBar: StickyActionBarWrapper(
stickyActionBar: Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Column(
children: [
WoltElevatedButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class RejectOrderModalPage {
stickyActionBar: ValueListenableBuilder<bool>(
valueListenable: buttonEnabledListener,
builder: (_, isEnabled, __) {
return StickyActionBarWrapper(
return Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: onCoffeeOrderRejected,
theme: WoltElevatedButtonTheme.secondary,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class OfferRecommendationModalPage {
} else {
buttonText = 'Serve with $count suggestions';
}
return StickyActionBarWrapper(
return Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: onCoffeeOrderServed,
enabled: count > 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class ServeOrOfferModalPage {
image: AssetImage('lib/assets/images/coffee_is_ready.png'),
fit: BoxFit.cover,
),
stickyActionBar: StickyActionBarWrapper(
stickyActionBar: Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Column(
children: [
WoltElevatedButton(
Expand Down
1 change: 0 additions & 1 deletion demo_ui_components/lib/demo_ui_components.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export 'src/button/sticky_action_bar_wrapper.dart';
export 'src/button/wolt_modal_sheet_back_button.dart';
export 'src/button/wolt_circular_elevated_button.dart';
export 'src/button/wolt_modal_sheet_close_button.dart';
Expand Down
51 changes: 0 additions & 51 deletions demo_ui_components/lib/src/button/sticky_action_bar_wrapper.dart

This file was deleted.

Binary file added doc/example_app_record.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/example_app_recording.gif
Binary file not shown.
2 changes: 1 addition & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class MainApp extends StatelessWidget {
onPressed: Navigator.of(modalSheetContext).pop,
),
child: const Padding(
padding: EdgeInsets.only(bottom: 120),
padding: EdgeInsets.only(bottom: 150),
child: Text(
'''
Pagination involves a sequence of screens the user navigates sequentially. We chose a lateral motion for these transitions. When proceeding forward, the next screen emerges from the right; moving backward, the screen reverts to its original position. We felt that sliding the next screen entirely from the right could be overly distracting. As a result, we decided to move and fade in the next page using 30% of the modal side.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import 'package:flutter/material.dart';
class CurrentSabAnimatedBuilder extends StatelessWidget {
final AnimationController controller;
final Animation<double> _opacity;
final Widget stickyActionBar;
final Widget stickyActionBarWrapper;

CurrentSabAnimatedBuilder({
required this.controller,
required this.stickyActionBar,
required this.stickyActionBarWrapper,
super.key,
}) : _opacity = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
Expand All @@ -21,7 +21,7 @@ class CurrentSabAnimatedBuilder extends StatelessWidget {
return AnimatedBuilder(
animation: controller,
builder: (BuildContext _, Widget? __) {
return Opacity(opacity: _opacity.value, child: stickyActionBar);
return Opacity(opacity: _opacity.value, child: stickyActionBarWrapper);
},
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import 'package:flutter/material.dart';
class OutgoingSabAnimatedBuilder extends StatelessWidget {
final AnimationController controller;
final Animation<double> _opacity;
final Widget sab;
final Widget stickyActionBarWrapper;

OutgoingSabAnimatedBuilder({
required this.controller,
required this.sab,
required this.stickyActionBarWrapper,
super.key,
}) : _opacity = Tween<double>(begin: 1.0, end: 0.0).animate(
CurvedAnimation(
Expand All @@ -24,7 +24,7 @@ class OutgoingSabAnimatedBuilder extends StatelessWidget {
return AnimatedBuilder(
animation: controller,
builder: (BuildContext _, Widget? __) {
return Opacity(opacity: _opacity.value, child: sab);
return Opacity(opacity: _opacity.value, child: stickyActionBarWrapper);
},
);
}
Expand Down
7 changes: 4 additions & 3 deletions lib/src/content/wolt_modal_sheet_animated_switcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:wolt_modal_sheet/src/content/components/main_content/wolt_modal_
import 'package:wolt_modal_sheet/src/content/components/main_content/wolt_modal_sheet_top_bar_title_flow.dart';
import 'package:wolt_modal_sheet/src/content/components/outgoing/outgoing_navigation_toolbar_animated_builder.dart';
import 'package:wolt_modal_sheet/src/content/components/paginating_group/paginating_widgets_group.dart';
import 'package:wolt_modal_sheet/src/widgets/wolt_sticky_action_bar_wrapper.dart';
import 'package:wolt_modal_sheet/src/content/wolt_modal_sheet_layout.dart';
import 'package:wolt_modal_sheet/src/widgets/wolt_navigation_toolbar.dart';
import 'package:wolt_modal_sheet/wolt_modal_sheet.dart';
Expand Down Expand Up @@ -270,7 +271,7 @@ class _WoltModalSheetAnimatedSwitcherState extends State<WoltModalSheetAnimatedS
),
),
sabAnimatedBuilder: CurrentSabAnimatedBuilder(
stickyActionBar: _page.stickyActionBar ?? const SizedBox.shrink(),
stickyActionBarWrapper: WoltStickyActionBarWrapper(page: _page),
controller: animationController,
),
);
Expand Down Expand Up @@ -309,8 +310,8 @@ class _WoltModalSheetAnimatedSwitcherState extends State<WoltModalSheetAnimatedS
),
sabAnimatedBuilder: OutgoingSabAnimatedBuilder(
controller: animationController,
sab: (currentWidgetsToBeOutgoing.sabAnimatedBuilder as CurrentSabAnimatedBuilder)
.stickyActionBar,
stickyActionBarWrapper: (currentWidgetsToBeOutgoing.sabAnimatedBuilder as CurrentSabAnimatedBuilder)
.stickyActionBarWrapper,
),
);
}
Expand Down
13 changes: 13 additions & 0 deletions lib/src/modal_page/wolt_modal_sheet_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ class WoltModalSheetPage {
/// content to be explored below the fold.
final Widget? stickyActionBar;

/// Indicates whether a gentle gradient overlay should be rendered above the
/// [stickyActionBar]. The purpose of this gradient is to visually suggest
/// to the user that additional content might be present below the action bar.
///
/// If set to `true`, a gradient from the page's background color to transparent
/// is rendered right above the [stickyActionBar]. If `false`, no gradient is rendered.
/// By default, it's set to `true`.
final bool hasSabGradient;

/// The padding applied to the main content of the page. If not provided, the default padding
/// will be used depending on the [WoltModalType] (16 for [WoltModalType.bottomSheet] and 32
/// for [WoltModalType.dialog]).
Expand Down Expand Up @@ -138,6 +147,7 @@ class WoltModalSheetPage {
this.heroImage,
this.heroImageHeight,
this.backgroundColor = Colors.white,
this.hasSabGradient = true,
this.forceMaxHeight = false,
this.scrollController,
this.stickyActionBar,
Expand All @@ -159,6 +169,7 @@ class WoltModalSheetPage {
Widget? heroImage,
double? heroImageHeight,
Color backgroundColor = Colors.white,
bool hasSabGradient = true,
bool forceMaxHeight = false,
bool isTopBarLayerAlwaysVisible = false,
bool hasTopBarLayer = true,
Expand All @@ -177,6 +188,7 @@ class WoltModalSheetPage {
heroImage: heroImage,
heroImageHeight: heroImageHeight,
backgroundColor: backgroundColor,
hasSabGradient: hasSabGradient,
forceMaxHeight: forceMaxHeight,
scrollController: scrollController,
stickyActionBar: stickyActionBar,
Expand All @@ -199,6 +211,7 @@ class WoltModalSheetPage {
Widget? heroImage,
double? heroImageHeight,
Color backgroundColor = Colors.white,
bool hasSabGradient = true,
bool forceMaxHeight = false,
bool isTopBarLayerAlwaysVisible = false,
bool hasTopBarLayer = true,
Expand Down
61 changes: 61 additions & 0 deletions lib/src/widgets/wolt_sticky_action_bar_wrapper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
import 'package:wolt_modal_sheet/src/modal_page/wolt_modal_sheet_page.dart';

/// A widget that wraps the Sticky Action Bar in the [WoltModalSheetPage].
///
/// It handles the conditional rendering of the Sticky Action Bar and the
/// gradient overlay above it, based on the configurations provided in the [WoltModalSheetPage].
class WoltStickyActionBarWrapper extends StatelessWidget {
/// Constructs a `WoltStickyActionBarWrapper`.
///
/// The [page] argument must not be null.
const WoltStickyActionBarWrapper({required this.page, Key? key}) : super(key: key);

/// The [WoltModalSheetPage] which provides configuration for the Sticky Action Bar
/// and potentially its gradient overlay.
final WoltModalSheetPage page;

@visibleForTesting
static const gradientWidgetKey = ValueKey("WoltStickyActionBarWrapperGradient");

@override
Widget build(BuildContext context) {
// Fetch the sticky action bar from the provided page
final stickyActionBar = page.stickyActionBar;

// If there's no action bar provided, render nothing.
if (stickyActionBar == null) {
return const SizedBox.shrink();
}

// The background color for the sticky action bar and potentially its gradient overlay.
final backgroundColor = page.backgroundColor;

// Render a Column widget containing the sticky action bar
// and its gradient overlay if needed.
return Column(
children: [
// If a gradient is required, add a Container with a linear gradient decoration.
if (page.hasSabGradient)
Container(
key: gradientWidgetKey,
/// TODO(ulusoyca): get the gradient height value from the theme extensions
height: 24.0,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
backgroundColor,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at some point we could make this even customisable, so that the user can pass in its own gradient. That way the user can use any gradient form and color

backgroundColor.withOpacity(0),
],
),
),
),
// Render the sticky action bar with its background color.
ColoredBox(color: backgroundColor, child: stickyActionBar),
],
);
}
}
2 changes: 1 addition & 1 deletion playground/lib/home/pages/root_sheet_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class RootSheetPage {
valueListenable: isButtonEnabledNotifier,
builder: (_, value, __) {
return Padding(
padding: const EdgeInsets.all(16),
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: onSabPressed,
enabled: value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class SheetPageWithForcedMaxHeight {
mainContentPadding: const EdgeInsetsDirectional.all(16),
forceMaxHeight: true,
stickyActionBar: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: onSabPressed,
colorName: WoltColorName.green,
Expand Down
2 changes: 1 addition & 1 deletion playground/lib/home/pages/sheet_page_with_hero_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SheetPageWithHeroImage {
fit: BoxFit.cover,
),
stickyActionBar: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: onSabPressed,
child: Text(isLastPage ? "Close" : "Next"),
Expand Down
13 changes: 5 additions & 8 deletions playground/lib/home/pages/sheet_page_with_lazy_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@ class SheetPageWithLazyList {
const titleText = 'Material Colors';
return WoltModalSheetPage.withCustomSliverList(
mainContentPadding: EdgeInsetsDirectional.zero,
stickyActionBar: StickyActionBarWrapper(
padding: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: WoltElevatedButton(
onPressed: onSabPressed,
child: Text(isLastPage ? "Close" : "Next"),
),
stickyActionBar: Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: onSabPressed,
child: Text(isLastPage ? "Close" : "Next"),
),
),
pageTitle: const Padding(
Expand Down
2 changes: 1 addition & 1 deletion playground/lib/home/pages/sheet_page_with_text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class SheetPageWithTextField {
valueListenable: isButtonEnabledNotifier,
builder: (_, isEnabled, __) {
return Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: onSabPressed,
enabled: isEnabled,
Expand Down
2 changes: 1 addition & 1 deletion playground_navigator2/lib/modal/pages/root_sheet_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class RootSheetPage {
valueListenable: isButtonEnabledNotifier,
builder: (_, value, __) {
return Padding(
padding: const EdgeInsets.all(16),
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: () => context.read<RouterCubit>().goToPage(1),
enabled: value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SheetPageWithForcedMaxHeight {
mainContentPadding: const EdgeInsetsDirectional.all(16),
forceMaxHeight: true,
stickyActionBar: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: WoltElevatedButton(
onPressed: isLastPage ? cubit.closeSheet : () => cubit.goToPage(currentPage + 1),
colorName: WoltColorName.green,
Expand Down
Loading