From 661e89b8ef4f7830a87ae07f9871f6693a36a17f Mon Sep 17 00:00:00 2001 From: thelukewalton Date: Tue, 3 Jun 2025 12:42:01 +0100 Subject: [PATCH 1/2] fix(WFCNG-21252): Add auto close to slidable --- lib/src/components/molecules/comment.dart | 23 ++++++++++++++--- .../molecules/slidable_list_tile.dart | 25 +++++++++++++++++-- lib/src/utils/theme/theme.dart | 11 +++++--- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/lib/src/components/molecules/comment.dart b/lib/src/components/molecules/comment.dart index ccfb3682..f7a8f01f 100644 --- a/lib/src/components/molecules/comment.dart +++ b/lib/src/components/molecules/comment.dart @@ -1,10 +1,12 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; - +import 'package:flutter_slidable/flutter_slidable.dart'; import '../../../zds_flutter.dart'; -/// Displays a comment with an optional attachment and delete and reply swipeable actions. +/// Displays a comment with an optional attachment and delete and reply slidable actions. +/// +/// For the correct behavior, any app using this widget should be wrapped with either a [SlidableAutoCloseBehavior] or a [ZdsBottomBarTheme]. class ZdsComment extends StatelessWidget { /// Constructs a [ZdsComment] widget. const ZdsComment({ @@ -26,6 +28,8 @@ class ZdsComment extends StatelessWidget { this.onMenuItemSelected, this.backgroundColor, this.popupMenuBackgroundColor, + this.slidableCloseOnScroll = false, + this.scrollableGroupTag = 'zds-comment', }) : assert( onReply != null && replySemanticLabel != null || onReply == null && replySemanticLabel == null, 'replySemanticLabel must be not null if onReply is defined', @@ -98,6 +102,16 @@ class ZdsComment extends StatelessWidget { /// Defaults to [ZetaColors.surfacePrimary]. final Color? popupMenuBackgroundColor; + /// Whether the slidable actions should close when the list is scrolled. + final bool slidableCloseOnScroll; + + /// The tag for the scrollable group. + /// + /// This is used to group comments in a scrollable list. + /// + /// The default is 'zds-comment'. This means that all comments will be in the same group, so only one comments slidable actions can be open at a time. + final String? scrollableGroupTag; + @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; @@ -128,6 +142,7 @@ class ZdsComment extends StatelessWidget { builder: (context, constraints) { return ZdsSlidableListTile( width: constraints.maxWidth, + closeOnScroll: slidableCloseOnScroll, elevation: 0, actions: [ if (!isReply && onReply != null && replySemanticLabel != null) @@ -271,7 +286,9 @@ class ZdsComment extends StatelessWidget { ..add(EnumProperty('menuPosition', menuPosition)) ..add(ObjectFlagProperty?>.has('onMenuItemSelected', onMenuItemSelected)) ..add(ColorProperty('backgroundColor', backgroundColor)) - ..add(ColorProperty('popupMenuBackgroundColor', popupMenuBackgroundColor)); + ..add(ColorProperty('popupMenuBackgroundColor', popupMenuBackgroundColor)) + ..add(DiagnosticsProperty('slidableCloseOnScroll', slidableCloseOnScroll)) + ..add(StringProperty('scrollableGroupTag', scrollableGroupTag)); } } diff --git a/lib/src/components/molecules/slidable_list_tile.dart b/lib/src/components/molecules/slidable_list_tile.dart index 224f5336..77fd210f 100644 --- a/lib/src/components/molecules/slidable_list_tile.dart +++ b/lib/src/components/molecules/slidable_list_tile.dart @@ -5,9 +5,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/semantics.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; +import '../../../zds_flutter.dart'; /// A widget that creates a slidable list tile, which can be slid right-to-left to reveal further actions. +/// +/// For the correct behavior, any app using this widget should be wrapped with either a [SlidableAutoCloseBehavior] or a [ZdsBottomBarTheme]. +/// /// Takes a [child] which can be any widget, although a [Row] is recommended to use like so: /// ```dart /// ZdsSlidableListTile( @@ -33,6 +36,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; /// null. /// /// This widget's actions are defined through [ZdsSlidableAction]. +/// class ZdsSlidableListTile extends StatelessWidget { /// A tile that can be slid to reveal further actions. /// @@ -52,6 +56,8 @@ class ZdsSlidableListTile extends StatelessWidget { this.slideEnabled = true, this.semanticDescription, this.excludeSemantics = false, + this.closeOnScroll = false, + this.groupTag = 'zds-slidable-list-tile', }) : assert(actions == null || slideButtonWidth * actions.length <= width, ''); /// The tile's main content. Usually a [Row] @@ -94,6 +100,17 @@ class ZdsSlidableListTile extends StatelessWidget { /// Flag to exclude child component semantics. final bool excludeSemantics; + + /// Whether to close the slidable when the user scrolls. + final bool closeOnScroll; + + /// Tag used to group multiple slidable widgets together. + /// + /// The default value is 'zds-slidable-list-tile', which means that all slidable widgets with this tag will be grouped together. + /// + /// This is useful when you have multiple slidable widgets in a scrollable list and you want to ensure that only one of them can be open at a time. + final String? groupTag; + @override Widget build(BuildContext context) { final Map semanticActions = {}; @@ -110,6 +127,8 @@ class ZdsSlidableListTile extends StatelessWidget { excludeSemantics: excludeSemantics, child: Slidable( enabled: slideEnabled, + closeOnScroll: closeOnScroll, + groupTag: groupTag, startActionPane: leadingActions != null && leadingActions!.isNotEmpty ? ActionPane( motion: const DrawerMotion(), @@ -158,7 +177,9 @@ class ZdsSlidableListTile extends StatelessWidget { ..add(DoubleProperty('minHeight', minHeight)) ..add(StringProperty('semanticDescription', semanticDescription)) ..add(DiagnosticsProperty('excludeSemantics', excludeSemantics)) - ..add(DoubleProperty('elevation', elevation)); + ..add(DoubleProperty('elevation', elevation)) + ..add(DiagnosticsProperty('closeOnScroll', closeOnScroll)) + ..add(StringProperty('scrollableGroupTag', groupTag)); } } diff --git a/lib/src/utils/theme/theme.dart b/lib/src/utils/theme/theme.dart index 864217bf..c89a1831 100644 --- a/lib/src/utils/theme/theme.dart +++ b/lib/src/utils/theme/theme.dart @@ -1,5 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import '../../../zds_flutter.dart'; @@ -98,13 +99,17 @@ class ZdsBottomBarThemeData { } /// Theme for ZdsBottomBar. +/// +/// Note: This should wrap the entire widget tree for all apps using ZDS Flutter. +/// +/// This wrapper also provides the [SlidableAutoCloseBehavior] to ensure that any [Slidable] widgets automatically close when another slidable action is triggered. class ZdsBottomBarTheme extends InheritedWidget { /// Constructs a [ZdsBottomBarTheme]. - const ZdsBottomBarTheme({ - required super.child, + ZdsBottomBarTheme({ + required Widget child, required this.data, super.key, - }); + }) : super(child: SlidableAutoCloseBehavior(child: child)); /// Theme data to be applied. final ZdsBottomBarThemeData data; From 4a7d1db63a5ab6b0dd95ffcf7fe13ba834ef7550 Mon Sep 17 00:00:00 2001 From: thelukewalton Date: Wed, 4 Jun 2025 09:23:12 +0100 Subject: [PATCH 2/2] add misisng group tag --- lib/src/components/molecules/comment.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/components/molecules/comment.dart b/lib/src/components/molecules/comment.dart index f7a8f01f..79204624 100644 --- a/lib/src/components/molecules/comment.dart +++ b/lib/src/components/molecules/comment.dart @@ -143,6 +143,7 @@ class ZdsComment extends StatelessWidget { return ZdsSlidableListTile( width: constraints.maxWidth, closeOnScroll: slidableCloseOnScroll, + groupTag: scrollableGroupTag, elevation: 0, actions: [ if (!isReply && onReply != null && replySemanticLabel != null)