diff --git a/lib/features/results/charts/quick_chart_view.dart b/lib/features/results/charts/quick_chart_view.dart index f875efb1..07ff4772 100644 --- a/lib/features/results/charts/quick_chart_view.dart +++ b/lib/features/results/charts/quick_chart_view.dart @@ -295,20 +295,17 @@ class _QuickChartViewState extends material.State { runSpacing: 8, crossAxisAlignment: material.WrapCrossAlignment.center, children: [ - material.SizedBox( - height: 32, - width: 260, - child: QueryaTabStrip( - labels: const ['Bar', 'Line', 'Pie'], - selectedIndex: QuickChartType.values.indexOf(_type), - onSelected: (i) => setState(() { - _type = QuickChartType.values[i]; - _topN = _type == QuickChartType.pie - ? ChartData.pieTopN - : ChartData.defaultTopN; - _hoveredSlice = null; - }), - ), + QueryaTabStrip( + dense: true, + labels: const ['Bar', 'Line', 'Pie'], + selectedIndex: QuickChartType.values.indexOf(_type), + onSelected: (i) => setState(() { + _type = QuickChartType.values[i]; + _topN = _type == QuickChartType.pie + ? ChartData.pieTopN + : ChartData.defaultTopN; + _hoveredSlice = null; + }), ), const material.SizedBox(width: 12), Text(_xLabel), diff --git a/lib/features/workspace/results_tab.dart b/lib/features/workspace/results_tab.dart index bf5f2327..e8f84a9e 100644 --- a/lib/features/workspace/results_tab.dart +++ b/lib/features/workspace/results_tab.dart @@ -404,15 +404,15 @@ class _ResultsTabState extends material.State { mainAxisSize: material.MainAxisSize.min, children: [ // Grid / Groupings View Selector - material.SizedBox( - height: 32, - width: 240, - child: QueryaTabStrip( - labels: const ['Grid', 'Groupings', 'Charts'], - selectedIndex: ResultViewMode.values.indexOf(_viewMode), - onSelected: (i) => - setState(() => _viewMode = ResultViewMode.values[i]), - ), + // Sized by its labels: a fixed box clipped the tabs and + // let "Groupings" run into its neighbours at larger UI + // scales. + QueryaTabStrip( + dense: true, + labels: const ['Grid', 'Groupings', 'Charts'], + selectedIndex: ResultViewMode.values.indexOf(_viewMode), + onSelected: (i) => + setState(() => _viewMode = ResultViewMode.values[i]), ), const Gap(10), Text( diff --git a/lib/shared/widgets/querya_tab_strip.dart b/lib/shared/widgets/querya_tab_strip.dart index a451b07f..be8d83df 100644 --- a/lib/shared/widgets/querya_tab_strip.dart +++ b/lib/shared/widgets/querya_tab_strip.dart @@ -25,6 +25,7 @@ class QueryaTabStrip extends material.StatefulWidget { this.onAdd, this.canClose, this.scrollController, + this.dense = false, }) : assert(labels.length > 0); final List labels; @@ -35,6 +36,10 @@ class QueryaTabStrip extends material.StatefulWidget { final bool Function(int index)? canClose; final material.ScrollController? scrollController; + /// Tighter vertical padding for toolbars: the strip is as tall as a dense + /// icon button instead of a full tab row. + final bool dense; + @override material.State createState() => QueryaTabStripState(); } @@ -268,7 +273,7 @@ class QueryaTabStripState extends material.State curve: context.motionCurve(QueryaMotion.enter), padding: material.EdgeInsets.symmetric( horizontal: showClose ? 10 : 12, - vertical: 8, + vertical: widget.dense ? 4 : 8, ), decoration: material.BoxDecoration( color: material.Colors.transparent, diff --git a/test/features/workspace/results_tab_test.dart b/test/features/workspace/results_tab_test.dart index 901d11db..b6a0df37 100644 --- a/test/features/workspace/results_tab_test.dart +++ b/test/features/workspace/results_tab_test.dart @@ -1343,5 +1343,50 @@ void main() { expect(tester.takeException(), isNull); }); }); -} + group('result view tabs', () { + testWidgets( + 'Grid, Groupings and Charts sit side by side at any text scale', + (tester) async { + for (final scale in [1.0, 1.3, 1.6]) { + await tester.pumpWidget( + material.MediaQuery( + data: material.MediaQueryData( + size: const material.Size(900, 500), + textScaler: material.TextScaler.linear(scale), + ), + child: resultsShell( + child: const material.Scaffold( + body: material.SizedBox( + width: 900, + height: 500, + child: ResultsTab( + columns: ['id', 'name'], + rows: [ + ['1', 'Alice'], + ], + ), + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + final grid = + tester.getRect(find.byKey(const material.ValueKey('querya_tab_Grid'))); + final groupings = tester.getRect( + find.byKey(const material.ValueKey('querya_tab_Groupings'))); + final charts = tester.getRect( + find.byKey(const material.ValueKey('querya_tab_Charts'))); + + expect(grid.right, lessThanOrEqualTo(groupings.left), reason: 'x$scale'); + expect(groupings.right, lessThanOrEqualTo(charts.left), + reason: 'x$scale'); + // The tabs are as tall as their own content: nothing is clipped by a + // box that is shorter than them. + expect(tester.takeException(), isNull, reason: 'x$scale'); + } + }); + }); +}