From a93274e752130cf615fe3e19a614552727fa4b23 Mon Sep 17 00:00:00 2001 From: Carson Underwood Date: Tue, 28 Jan 2025 16:21:21 -0600 Subject: [PATCH] Allow tables to be scrollable with IntrinsicColumnWidth --- packages/flutter_markdown/CHANGELOG.md | 5 +++ .../flutter_markdown/lib/src/builder.dart | 4 +- .../flutter_markdown/lib/src/style_sheet.dart | 7 +++ packages/flutter_markdown/pubspec.yaml | 2 +- .../test/scrollable_test.dart | 30 ++++++++++++- .../flutter_markdown/test/table_test.dart | 44 +++++++++++++++++++ 6 files changed, 89 insertions(+), 3 deletions(-) diff --git a/packages/flutter_markdown/CHANGELOG.md b/packages/flutter_markdown/CHANGELOG.md index a7274b56908c..bbf8fa279e7f 100644 --- a/packages/flutter_markdown/CHANGELOG.md +++ b/packages/flutter_markdown/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.7.6 + +* Adds horizontal scrolling for table when using `tableColumnWidth: IntrinsicColumnWidth()`. +* Adds styleSheet option `tableScrollbarThumbVisibility` for setting the `thumbVisibility` on tables' `ScrollBar`. + ## 0.7.5 * Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. diff --git a/packages/flutter_markdown/lib/src/builder.dart b/packages/flutter_markdown/lib/src/builder.dart index 3fdd9ff13e2c..d35c8e7da8f3 100644 --- a/packages/flutter_markdown/lib/src/builder.dart +++ b/packages/flutter_markdown/lib/src/builder.dart @@ -451,12 +451,14 @@ class MarkdownBuilder implements md.NodeVisitor { ); } } else if (tag == 'table') { - if (styleSheet.tableColumnWidth is FixedColumnWidth) { + if (styleSheet.tableColumnWidth is FixedColumnWidth || + styleSheet.tableColumnWidth is IntrinsicColumnWidth) { child = _ScrollControllerBuilder( builder: (BuildContext context, ScrollController tableScrollController, Widget? child) { return Scrollbar( controller: tableScrollController, + thumbVisibility: styleSheet.tableScrollbarThumbVisibility, child: SingleChildScrollView( controller: tableScrollController, scrollDirection: Axis.horizontal, diff --git a/packages/flutter_markdown/lib/src/style_sheet.dart b/packages/flutter_markdown/lib/src/style_sheet.dart index 0a6b1b430e72..157300acdcad 100644 --- a/packages/flutter_markdown/lib/src/style_sheet.dart +++ b/packages/flutter_markdown/lib/src/style_sheet.dart @@ -41,6 +41,7 @@ class MarkdownStyleSheet { this.tablePadding, this.tableBorder, this.tableColumnWidth, + this.tableScrollbarThumbVisibility, this.tableCellsPadding, this.tableCellsDecoration, this.tableVerticalAlignment = TableCellVerticalAlignment.middle, @@ -375,6 +376,7 @@ class MarkdownStyleSheet { EdgeInsets? tablePadding, TableBorder? tableBorder, TableColumnWidth? tableColumnWidth, + bool? tableScrollbarThumbVisibility, EdgeInsets? tableCellsPadding, Decoration? tableCellsDecoration, TableCellVerticalAlignment? tableVerticalAlignment, @@ -441,6 +443,7 @@ class MarkdownStyleSheet { tablePadding: tablePadding ?? this.tablePadding, tableBorder: tableBorder ?? this.tableBorder, tableColumnWidth: tableColumnWidth ?? this.tableColumnWidth, + tableScrollbarThumbVisibility: tableScrollbarThumbVisibility, tableCellsPadding: tableCellsPadding ?? this.tableCellsPadding, tableCellsDecoration: tableCellsDecoration ?? this.tableCellsDecoration, tableVerticalAlignment: @@ -508,6 +511,7 @@ class MarkdownStyleSheet { tablePadding: other.tablePadding, tableBorder: other.tableBorder, tableColumnWidth: other.tableColumnWidth, + tableScrollbarThumbVisibility: other.tableScrollbarThumbVisibility, tableCellsPadding: other.tableCellsPadding, tableCellsDecoration: other.tableCellsDecoration, tableVerticalAlignment: other.tableVerticalAlignment, @@ -633,6 +637,9 @@ class MarkdownStyleSheet { /// The [TableColumnWidth] to use for `th` and `td` elements. final TableColumnWidth? tableColumnWidth; + /// The scrollbar thumbVisibility when the table is scrollable. + final bool? tableScrollbarThumbVisibility; + /// The padding to use for `th` and `td` elements. final EdgeInsets? tableCellsPadding; diff --git a/packages/flutter_markdown/pubspec.yaml b/packages/flutter_markdown/pubspec.yaml index 997d092ae8bd..d82c42f2bcaf 100644 --- a/packages/flutter_markdown/pubspec.yaml +++ b/packages/flutter_markdown/pubspec.yaml @@ -4,7 +4,7 @@ description: A Markdown renderer for Flutter. Create rich text output, formatted with simple Markdown tags. repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22 -version: 0.7.5 +version: 0.7.6 environment: sdk: ^3.4.0 diff --git a/packages/flutter_markdown/test/scrollable_test.dart b/packages/flutter_markdown/test/scrollable_test.dart index 90f6f8967299..645677efd342 100644 --- a/packages/flutter_markdown/test/scrollable_test.dart +++ b/packages/flutter_markdown/test/scrollable_test.dart @@ -113,7 +113,7 @@ void defineTests() { ); testWidgets( - 'table', + 'table with fixed column width', (WidgetTester tester) async { const String data = '|Header 1|Header 2|Header 3|' '\n|-----|-----|-----|' @@ -140,6 +140,34 @@ void defineTests() { }, ); + testWidgets( + 'table with intrinsic column width', + (WidgetTester tester) async { + const String data = '|Header 1|Header 2|Header 3|' + '\n|-----|-----|-----|' + '\n|Col 1|Col 2|Col 3|'; + await tester.pumpWidget( + boilerplate( + MediaQuery( + data: const MediaQueryData(), + child: MarkdownBody( + data: data, + styleSheet: MarkdownStyleSheet( + tableColumnWidth: const IntrinsicColumnWidth(), + ), + ), + ), + ), + ); + + final Iterable widgets = tester.allWidgets; + final Iterable scrollViews = + widgets.whereType(); + expect(scrollViews, isNotEmpty); + expect(scrollViews.first.controller, isNotNull); + }, + ); + testWidgets( 'two tables use different scroll controllers', (WidgetTester tester) async { diff --git a/packages/flutter_markdown/test/table_test.dart b/packages/flutter_markdown/test/table_test.dart index 9a7a4daf87e5..93341ee625af 100644 --- a/packages/flutter_markdown/test/table_test.dart +++ b/packages/flutter_markdown/test/table_test.dart @@ -200,6 +200,50 @@ void defineTests() { }, ); + testWidgets( + 'table scrollbar thumbVisibility should follow stylesheet', + (WidgetTester tester) async { + final ThemeData theme = + ThemeData.light().copyWith(textTheme: textTheme); + + const String data = '|Header|\n|----|\n|Column|'; + const bool tableScrollbarThumbVisibility = true; + final MarkdownStyleSheet style = MarkdownStyleSheet.fromTheme(theme) + .copyWith( + tableColumnWidth: const FixedColumnWidth(100), + tableScrollbarThumbVisibility: tableScrollbarThumbVisibility); + + await tester.pumpWidget( + boilerplate(MarkdownBody(data: data, styleSheet: style))); + + final Scrollbar scrollbar = tester.widget(find.byType(Scrollbar)); + + expect(scrollbar.thumbVisibility, tableScrollbarThumbVisibility); + }, + ); + + testWidgets( + 'table scrollbar thumbVisibility should follow stylesheet', + (WidgetTester tester) async { + final ThemeData theme = + ThemeData.light().copyWith(textTheme: textTheme); + + const String data = '|Header|\n|----|\n|Column|'; + const bool tableScrollbarThumbVisibility = false; + final MarkdownStyleSheet style = MarkdownStyleSheet.fromTheme(theme) + .copyWith( + tableColumnWidth: const FixedColumnWidth(100), + tableScrollbarThumbVisibility: tableScrollbarThumbVisibility); + + await tester.pumpWidget( + boilerplate(MarkdownBody(data: data, styleSheet: style))); + + final Scrollbar scrollbar = tester.widget(find.byType(Scrollbar)); + + expect(scrollbar.thumbVisibility, tableScrollbarThumbVisibility); + }, + ); + testWidgets( 'table with last row of empty table cells', (WidgetTester tester) async {